Add metrics/dimensions/names into monasca-api
This endpoint will return all the dimension names for a given metric name. Added dimension-names for influx in python api and java api Added dimension-names for vertica in java api Depends-On: Id981dafd00778a6d4a376b9ceab011231e94c0c6 Change-Id: I0192ccb9276ea94103a477bd2ad7d10f21e64d31 Implements: blueprint dimensions-api
This commit is contained in:
parent
e7a7732446
commit
f26c427b4b
|
@ -22,6 +22,7 @@ alarms_count = monasca_api.v2.reference.alarms:AlarmsCount
|
||||||
alarms_state_history = monasca_api.v2.reference.alarms:AlarmsStateHistory
|
alarms_state_history = monasca_api.v2.reference.alarms:AlarmsStateHistory
|
||||||
notification_methods = monasca_api.v2.reference.notifications:Notifications
|
notification_methods = monasca_api.v2.reference.notifications:Notifications
|
||||||
dimension_values = monasca_api.v2.reference.metrics:DimensionValues
|
dimension_values = monasca_api.v2.reference.metrics:DimensionValues
|
||||||
|
dimension_names = monasca_api.v2.reference.metrics:DimensionNames
|
||||||
notification_method_types = monasca_api.v2.reference.notificationstype:NotificationsType
|
notification_method_types = monasca_api.v2.reference.notificationstype:NotificationsType
|
||||||
|
|
||||||
[security]
|
[security]
|
||||||
|
|
|
@ -94,9 +94,8 @@ Document Version: v2.0
|
||||||
- [Status Code](#status-code-2)
|
- [Status Code](#status-code-2)
|
||||||
- [Response Body](#response-body-4)
|
- [Response Body](#response-body-4)
|
||||||
- [Response Examples](#response-examples-3)
|
- [Response Examples](#response-examples-3)
|
||||||
- [Measurements](#measurements)
|
- [List dimension names](#list-dimension-names)
|
||||||
- [List measurements](#list-measurements)
|
- [GET /v2.0/metrics/dimensions/names](#get-v20metricsdimensionsnames)
|
||||||
- [GET /v2.0/metrics/measurements](#get-v20metricsmeasurements)
|
|
||||||
- [Headers](#headers-5)
|
- [Headers](#headers-5)
|
||||||
- [Path Parameters](#path-parameters-5)
|
- [Path Parameters](#path-parameters-5)
|
||||||
- [Query Parameters](#query-parameters-5)
|
- [Query Parameters](#query-parameters-5)
|
||||||
|
@ -106,9 +105,9 @@ Document Version: v2.0
|
||||||
- [Status Code](#status-code-3)
|
- [Status Code](#status-code-3)
|
||||||
- [Response Body](#response-body-5)
|
- [Response Body](#response-body-5)
|
||||||
- [Response Examples](#response-examples-4)
|
- [Response Examples](#response-examples-4)
|
||||||
- [Metric Names](#metric-names)
|
- [Measurements](#measurements)
|
||||||
- [List names](#list-names)
|
- [List measurements](#list-measurements)
|
||||||
- [GET /v2.0/metrics/names](#get-v20metricsnames)
|
- [GET /v2.0/metrics/measurements](#get-v20metricsmeasurements)
|
||||||
- [Headers](#headers-6)
|
- [Headers](#headers-6)
|
||||||
- [Path Parameters](#path-parameters-6)
|
- [Path Parameters](#path-parameters-6)
|
||||||
- [Query Parameters](#query-parameters-6)
|
- [Query Parameters](#query-parameters-6)
|
||||||
|
@ -118,9 +117,9 @@ Document Version: v2.0
|
||||||
- [Status Code](#status-code-4)
|
- [Status Code](#status-code-4)
|
||||||
- [Response Body](#response-body-6)
|
- [Response Body](#response-body-6)
|
||||||
- [Response Examples](#response-examples-5)
|
- [Response Examples](#response-examples-5)
|
||||||
- [Statistics](#statistics)
|
- [Metric Names](#metric-names)
|
||||||
- [List statistics](#list-statistics)
|
- [List names](#list-names)
|
||||||
- [GET /v2.0/metrics/statistics](#get-v20metricsstatistics)
|
- [GET /v2.0/metrics/names](#get-v20metricsnames)
|
||||||
- [Headers](#headers-7)
|
- [Headers](#headers-7)
|
||||||
- [Path Parameters](#path-parameters-7)
|
- [Path Parameters](#path-parameters-7)
|
||||||
- [Query Parameters](#query-parameters-7)
|
- [Query Parameters](#query-parameters-7)
|
||||||
|
@ -130,9 +129,9 @@ Document Version: v2.0
|
||||||
- [Status Code](#status-code-5)
|
- [Status Code](#status-code-5)
|
||||||
- [Response Body](#response-body-7)
|
- [Response Body](#response-body-7)
|
||||||
- [Response Examples](#response-examples-6)
|
- [Response Examples](#response-examples-6)
|
||||||
- [Notification Methods](#notification-methods-1)
|
- [Statistics](#statistics)
|
||||||
- [Create Notification Method](#create-notification-method)
|
- [List statistics](#list-statistics)
|
||||||
- [POST /v2.0/notification-methods](#post-v20notification-methods)
|
- [GET /v2.0/metrics/statistics](#get-v20metricsstatistics)
|
||||||
- [Headers](#headers-8)
|
- [Headers](#headers-8)
|
||||||
- [Path Parameters](#path-parameters-8)
|
- [Path Parameters](#path-parameters-8)
|
||||||
- [Query Parameters](#query-parameters-8)
|
- [Query Parameters](#query-parameters-8)
|
||||||
|
@ -142,8 +141,9 @@ Document Version: v2.0
|
||||||
- [Status Code](#status-code-6)
|
- [Status Code](#status-code-6)
|
||||||
- [Response Body](#response-body-8)
|
- [Response Body](#response-body-8)
|
||||||
- [Response Examples](#response-examples-7)
|
- [Response Examples](#response-examples-7)
|
||||||
- [List Notification Methods](#list-notification-methods)
|
- [Notification Methods](#notification-methods-1)
|
||||||
- [GET /v2.0/notification-methods](#get-v20notification-methods)
|
- [Create Notification Method](#create-notification-method)
|
||||||
|
- [POST /v2.0/notification-methods](#post-v20notification-methods)
|
||||||
- [Headers](#headers-9)
|
- [Headers](#headers-9)
|
||||||
- [Path Parameters](#path-parameters-9)
|
- [Path Parameters](#path-parameters-9)
|
||||||
- [Query Parameters](#query-parameters-9)
|
- [Query Parameters](#query-parameters-9)
|
||||||
|
@ -153,8 +153,8 @@ Document Version: v2.0
|
||||||
- [Status Code](#status-code-7)
|
- [Status Code](#status-code-7)
|
||||||
- [Response Body](#response-body-9)
|
- [Response Body](#response-body-9)
|
||||||
- [Response Examples](#response-examples-8)
|
- [Response Examples](#response-examples-8)
|
||||||
- [Get Notification Method](#get-notification-method)
|
- [List Notification Methods](#list-notification-methods)
|
||||||
- [GET /v2.0/notification-methods/{notification_method_id}](#get-v20notification-methodsnotification_method_id)
|
- [GET /v2.0/notification-methods](#get-v20notification-methods)
|
||||||
- [Headers](#headers-10)
|
- [Headers](#headers-10)
|
||||||
- [Path Parameters](#path-parameters-10)
|
- [Path Parameters](#path-parameters-10)
|
||||||
- [Query Parameters](#query-parameters-10)
|
- [Query Parameters](#query-parameters-10)
|
||||||
|
@ -164,8 +164,8 @@ Document Version: v2.0
|
||||||
- [Status Code](#status-code-8)
|
- [Status Code](#status-code-8)
|
||||||
- [Response Body](#response-body-10)
|
- [Response Body](#response-body-10)
|
||||||
- [Response Examples](#response-examples-9)
|
- [Response Examples](#response-examples-9)
|
||||||
- [Update Notification Method](#update-notification-method)
|
- [Get Notification Method](#get-notification-method)
|
||||||
- [PUT /v2.0/notification-methods/{notification_method_id}](#put-v20notification-methodsnotification_method_id)
|
- [GET /v2.0/notification-methods/{notification_method_id}](#get-v20notification-methodsnotification_method_id)
|
||||||
- [Headers](#headers-11)
|
- [Headers](#headers-11)
|
||||||
- [Path Parameters](#path-parameters-11)
|
- [Path Parameters](#path-parameters-11)
|
||||||
- [Query Parameters](#query-parameters-11)
|
- [Query Parameters](#query-parameters-11)
|
||||||
|
@ -175,8 +175,8 @@ Document Version: v2.0
|
||||||
- [Status Code](#status-code-9)
|
- [Status Code](#status-code-9)
|
||||||
- [Response Body](#response-body-11)
|
- [Response Body](#response-body-11)
|
||||||
- [Response Examples](#response-examples-10)
|
- [Response Examples](#response-examples-10)
|
||||||
- [Patch Notification Method](#patch-notification-method)
|
- [Update Notification Method](#update-notification-method)
|
||||||
- [PATCH /v2.0/notification-methods/{notification_method_id}](#patch-v20notification-methodsnotification_method_id)
|
- [PUT /v2.0/notification-methods/{notification_method_id}](#put-v20notification-methodsnotification_method_id)
|
||||||
- [Headers](#headers-12)
|
- [Headers](#headers-12)
|
||||||
- [Path Parameters](#path-parameters-12)
|
- [Path Parameters](#path-parameters-12)
|
||||||
- [Query Parameters](#query-parameters-12)
|
- [Query Parameters](#query-parameters-12)
|
||||||
|
@ -186,8 +186,8 @@ Document Version: v2.0
|
||||||
- [Status Code](#status-code-10)
|
- [Status Code](#status-code-10)
|
||||||
- [Response Body](#response-body-12)
|
- [Response Body](#response-body-12)
|
||||||
- [Response Examples](#response-examples-11)
|
- [Response Examples](#response-examples-11)
|
||||||
- [Delete Notification Method](#delete-notification-method)
|
- [Patch Notification Method](#patch-notification-method)
|
||||||
- [DELETE /v2.0/notification-methods/{notification_method_id}](#delete-v20notification-methodsnotification_method_id)
|
- [PATCH /v2.0/notification-methods/{notification_method_id}](#patch-v20notification-methodsnotification_method_id)
|
||||||
- [Headers](#headers-13)
|
- [Headers](#headers-13)
|
||||||
- [Path Parameters](#path-parameters-13)
|
- [Path Parameters](#path-parameters-13)
|
||||||
- [Query Parameters](#query-parameters-13)
|
- [Query Parameters](#query-parameters-13)
|
||||||
|
@ -196,21 +196,20 @@ Document Version: v2.0
|
||||||
- [Response](#response-13)
|
- [Response](#response-13)
|
||||||
- [Status Code](#status-code-11)
|
- [Status Code](#status-code-11)
|
||||||
- [Response Body](#response-body-13)
|
- [Response Body](#response-body-13)
|
||||||
- [List supported Notification Method Types](#list-supported-notification-method-types)
|
- [Response Examples](#response-examples-12)
|
||||||
- [GET /v2.0/notification-methods/types/](#get-v20notification-methodstypes)
|
- [Delete Notification Method](#delete-notification-method)
|
||||||
|
- [DELETE /v2.0/notification-methods/{notification_method_id}](#delete-v20notification-methodsnotification_method_id)
|
||||||
- [Headers](#headers-14)
|
- [Headers](#headers-14)
|
||||||
|
- [Path Parameters](#path-parameters-14)
|
||||||
- [Query Parameters](#query-parameters-14)
|
- [Query Parameters](#query-parameters-14)
|
||||||
- [Request Body](#request-body-14)
|
- [Request Body](#request-body-14)
|
||||||
- [Request Examples](#request-examples-14)
|
- [Request Examples](#request-examples-14)
|
||||||
- [Response](#response-14)
|
- [Response](#response-14)
|
||||||
- [Status Code](#status-code-12)
|
- [Status Code](#status-code-12)
|
||||||
- [Response Body](#response-body-14)
|
- [Response Body](#response-body-14)
|
||||||
- [Response Examples](#response-examples-12)
|
- [List supported Notification Method Types](#list-supported-notification-method-types)
|
||||||
- [Alarm Definitions](#alarm-definitions)
|
- [GET /v2.0/notification-methods/types/](#get-v20notification-methodstypes)
|
||||||
- [Create Alarm Definition](#create-alarm-definition)
|
|
||||||
- [POST /v2.0/alarm-definitions](#post-v20alarm-definitions)
|
|
||||||
- [Headers](#headers-15)
|
- [Headers](#headers-15)
|
||||||
- [Path Parameters](#path-parameters-14)
|
|
||||||
- [Query Parameters](#query-parameters-15)
|
- [Query Parameters](#query-parameters-15)
|
||||||
- [Request Body](#request-body-15)
|
- [Request Body](#request-body-15)
|
||||||
- [Request Examples](#request-examples-15)
|
- [Request Examples](#request-examples-15)
|
||||||
|
@ -218,8 +217,9 @@ Document Version: v2.0
|
||||||
- [Status Code](#status-code-13)
|
- [Status Code](#status-code-13)
|
||||||
- [Response Body](#response-body-15)
|
- [Response Body](#response-body-15)
|
||||||
- [Response Examples](#response-examples-13)
|
- [Response Examples](#response-examples-13)
|
||||||
- [List Alarm Definitions](#list-alarm-definitions)
|
- [Alarm Definitions](#alarm-definitions)
|
||||||
- [GET /v2.0/alarm-definitions](#get-v20alarm-definitions)
|
- [Create Alarm Definition](#create-alarm-definition)
|
||||||
|
- [POST /v2.0/alarm-definitions](#post-v20alarm-definitions)
|
||||||
- [Headers](#headers-16)
|
- [Headers](#headers-16)
|
||||||
- [Path Parameters](#path-parameters-15)
|
- [Path Parameters](#path-parameters-15)
|
||||||
- [Query Parameters](#query-parameters-16)
|
- [Query Parameters](#query-parameters-16)
|
||||||
|
@ -229,29 +229,29 @@ Document Version: v2.0
|
||||||
- [Status Code](#status-code-14)
|
- [Status Code](#status-code-14)
|
||||||
- [Response Body](#response-body-16)
|
- [Response Body](#response-body-16)
|
||||||
- [Response Examples](#response-examples-14)
|
- [Response Examples](#response-examples-14)
|
||||||
- [Get Alarm Definition](#get-alarm-definition)
|
- [List Alarm Definitions](#list-alarm-definitions)
|
||||||
- [GET /v2.0/alarm-definitions/{alarm_definition_id}](#get-v20alarm-definitionsalarm_definition_id)
|
- [GET /v2.0/alarm-definitions](#get-v20alarm-definitions)
|
||||||
- [Headers](#headers-17)
|
- [Headers](#headers-17)
|
||||||
- [Path Parameters](#path-parameters-16)
|
- [Path Parameters](#path-parameters-16)
|
||||||
- [Query Parameters](#query-parameters-17)
|
- [Query Parameters](#query-parameters-17)
|
||||||
- [Request Body](#request-body-17)
|
- [Request Body](#request-body-17)
|
||||||
|
- [Request Examples](#request-examples-17)
|
||||||
- [Response](#response-17)
|
- [Response](#response-17)
|
||||||
- [Status Code](#status-code-15)
|
- [Status Code](#status-code-15)
|
||||||
- [Response Body](#response-body-17)
|
- [Response Body](#response-body-17)
|
||||||
- [Response Examples](#response-examples-15)
|
- [Response Examples](#response-examples-15)
|
||||||
- [Update Alarm Definition](#update-alarm-definition)
|
- [Get Alarm Definition](#get-alarm-definition)
|
||||||
- [PUT /v2.0/alarm-definitions/{alarm_definition_id}](#put-v20alarm-definitionsalarm_definition_id)
|
- [GET /v2.0/alarm-definitions/{alarm_definition_id}](#get-v20alarm-definitionsalarm_definition_id)
|
||||||
- [Headers](#headers-18)
|
- [Headers](#headers-18)
|
||||||
- [Path Parameters](#path-parameters-17)
|
- [Path Parameters](#path-parameters-17)
|
||||||
- [Query Parameters](#query-parameters-18)
|
- [Query Parameters](#query-parameters-18)
|
||||||
- [Request Body](#request-body-18)
|
- [Request Body](#request-body-18)
|
||||||
- [Request Examples](#request-examples-17)
|
|
||||||
- [Response](#response-18)
|
- [Response](#response-18)
|
||||||
- [Status Code](#status-code-16)
|
- [Status Code](#status-code-16)
|
||||||
- [Response Body](#response-body-18)
|
- [Response Body](#response-body-18)
|
||||||
- [Response Examples](#response-examples-16)
|
- [Response Examples](#response-examples-16)
|
||||||
- [Patch Alarm Definition](#patch-alarm-definition)
|
- [Update Alarm Definition](#update-alarm-definition)
|
||||||
- [PATCH /v2.0/alarm-definitions/{alarm_definition_id}](#patch-v20alarm-definitionsalarm_definition_id)
|
- [PUT /v2.0/alarm-definitions/{alarm_definition_id}](#put-v20alarm-definitionsalarm_definition_id)
|
||||||
- [Headers](#headers-19)
|
- [Headers](#headers-19)
|
||||||
- [Path Parameters](#path-parameters-18)
|
- [Path Parameters](#path-parameters-18)
|
||||||
- [Query Parameters](#query-parameters-19)
|
- [Query Parameters](#query-parameters-19)
|
||||||
|
@ -261,8 +261,8 @@ Document Version: v2.0
|
||||||
- [Status Code](#status-code-17)
|
- [Status Code](#status-code-17)
|
||||||
- [Response Body](#response-body-19)
|
- [Response Body](#response-body-19)
|
||||||
- [Response Examples](#response-examples-17)
|
- [Response Examples](#response-examples-17)
|
||||||
- [Delete Alarm Definition](#delete-alarm-definition)
|
- [Patch Alarm Definition](#patch-alarm-definition)
|
||||||
- [DELETE /v2.0/alarm-definitions/{alarm_definition_id}](#delete-v20alarm-definitionsalarm_definition_id)
|
- [PATCH /v2.0/alarm-definitions/{alarm_definition_id}](#patch-v20alarm-definitionsalarm_definition_id)
|
||||||
- [Headers](#headers-20)
|
- [Headers](#headers-20)
|
||||||
- [Path Parameters](#path-parameters-19)
|
- [Path Parameters](#path-parameters-19)
|
||||||
- [Query Parameters](#query-parameters-20)
|
- [Query Parameters](#query-parameters-20)
|
||||||
|
@ -271,9 +271,9 @@ Document Version: v2.0
|
||||||
- [Response](#response-20)
|
- [Response](#response-20)
|
||||||
- [Status Code](#status-code-18)
|
- [Status Code](#status-code-18)
|
||||||
- [Response Body](#response-body-20)
|
- [Response Body](#response-body-20)
|
||||||
- [Alarms](#alarms)
|
- [Response Examples](#response-examples-18)
|
||||||
- [List Alarms](#list-alarms)
|
- [Delete Alarm Definition](#delete-alarm-definition)
|
||||||
- [GET /v2.0/alarms](#get-v20alarms)
|
- [DELETE /v2.0/alarm-definitions/{alarm_definition_id}](#delete-v20alarm-definitionsalarm_definition_id)
|
||||||
- [Headers](#headers-21)
|
- [Headers](#headers-21)
|
||||||
- [Path Parameters](#path-parameters-20)
|
- [Path Parameters](#path-parameters-20)
|
||||||
- [Query Parameters](#query-parameters-21)
|
- [Query Parameters](#query-parameters-21)
|
||||||
|
@ -282,19 +282,20 @@ Document Version: v2.0
|
||||||
- [Response](#response-21)
|
- [Response](#response-21)
|
||||||
- [Status Code](#status-code-19)
|
- [Status Code](#status-code-19)
|
||||||
- [Response Body](#response-body-21)
|
- [Response Body](#response-body-21)
|
||||||
- [Response Examples](#response-examples-18)
|
- [Alarms](#alarms)
|
||||||
- [List Alarms State History](#list-alarms-state-history)
|
- [List Alarms](#list-alarms)
|
||||||
- [GET /v2.0/alarms/state-history](#get-v20alarmsstate-history)
|
- [GET /v2.0/alarms](#get-v20alarms)
|
||||||
- [Headers](#headers-22)
|
- [Headers](#headers-22)
|
||||||
- [Path Parameters](#path-parameters-21)
|
- [Path Parameters](#path-parameters-21)
|
||||||
- [Query Parameters](#query-parameters-22)
|
- [Query Parameters](#query-parameters-22)
|
||||||
- [Request Body](#request-body-22)
|
- [Request Body](#request-body-22)
|
||||||
|
- [Request Examples](#request-examples-21)
|
||||||
- [Response](#response-22)
|
- [Response](#response-22)
|
||||||
- [Status Code](#status-code-20)
|
- [Status Code](#status-code-20)
|
||||||
- [Response Body](#response-body-22)
|
- [Response Body](#response-body-22)
|
||||||
- [Response Examples](#response-examples-19)
|
- [Response Examples](#response-examples-19)
|
||||||
- [Get Alarm](#get-alarm)
|
- [List Alarms State History](#list-alarms-state-history)
|
||||||
- [GET /v2.0/alarms/{alarm_id}](#get-v20alarmsalarm_id)
|
- [GET /v2.0/alarms/state-history](#get-v20alarmsstate-history)
|
||||||
- [Headers](#headers-23)
|
- [Headers](#headers-23)
|
||||||
- [Path Parameters](#path-parameters-22)
|
- [Path Parameters](#path-parameters-22)
|
||||||
- [Query Parameters](#query-parameters-23)
|
- [Query Parameters](#query-parameters-23)
|
||||||
|
@ -303,19 +304,18 @@ Document Version: v2.0
|
||||||
- [Status Code](#status-code-21)
|
- [Status Code](#status-code-21)
|
||||||
- [Response Body](#response-body-23)
|
- [Response Body](#response-body-23)
|
||||||
- [Response Examples](#response-examples-20)
|
- [Response Examples](#response-examples-20)
|
||||||
- [Update Alarm](#update-alarm)
|
- [Get Alarm](#get-alarm)
|
||||||
- [PUT /v2.0/alarms/{alarm_id}](#put-v20alarmsalarm_id)
|
- [GET /v2.0/alarms/{alarm_id}](#get-v20alarmsalarm_id)
|
||||||
- [Headers](#headers-24)
|
- [Headers](#headers-24)
|
||||||
- [Path Parameters](#path-parameters-23)
|
- [Path Parameters](#path-parameters-23)
|
||||||
- [Query Parameters](#query-parameters-24)
|
- [Query Parameters](#query-parameters-24)
|
||||||
- [Request Body](#request-body-24)
|
- [Request Body](#request-body-24)
|
||||||
- [Request Examples](#request-examples-21)
|
|
||||||
- [Response](#response-24)
|
- [Response](#response-24)
|
||||||
- [Status Code](#status-code-22)
|
- [Status Code](#status-code-22)
|
||||||
- [Response Body](#response-body-24)
|
- [Response Body](#response-body-24)
|
||||||
- [Response Examples](#response-examples-21)
|
- [Response Examples](#response-examples-21)
|
||||||
- [Patch Alarm](#patch-alarm)
|
- [Update Alarm](#update-alarm)
|
||||||
- [PATCH /v2.0/alarms/{alarm_id}](#patch-v20alarmsalarm_id)
|
- [PUT /v2.0/alarms/{alarm_id}](#put-v20alarmsalarm_id)
|
||||||
- [Headers](#headers-25)
|
- [Headers](#headers-25)
|
||||||
- [Path Parameters](#path-parameters-24)
|
- [Path Parameters](#path-parameters-24)
|
||||||
- [Query Parameters](#query-parameters-25)
|
- [Query Parameters](#query-parameters-25)
|
||||||
|
@ -325,8 +325,8 @@ Document Version: v2.0
|
||||||
- [Status Code](#status-code-23)
|
- [Status Code](#status-code-23)
|
||||||
- [Response Body](#response-body-25)
|
- [Response Body](#response-body-25)
|
||||||
- [Response Examples](#response-examples-22)
|
- [Response Examples](#response-examples-22)
|
||||||
- [Delete Alarm](#delete-alarm)
|
- [Patch Alarm](#patch-alarm)
|
||||||
- [DELETE /v2.0/alarms/{alarm_id}](#delete-v20alarmsalarm_id)
|
- [PATCH /v2.0/alarms/{alarm_id}](#patch-v20alarmsalarm_id)
|
||||||
- [Headers](#headers-26)
|
- [Headers](#headers-26)
|
||||||
- [Path Parameters](#path-parameters-25)
|
- [Path Parameters](#path-parameters-25)
|
||||||
- [Query Parameters](#query-parameters-26)
|
- [Query Parameters](#query-parameters-26)
|
||||||
|
@ -335,17 +335,28 @@ Document Version: v2.0
|
||||||
- [Response](#response-26)
|
- [Response](#response-26)
|
||||||
- [Status Code](#status-code-24)
|
- [Status Code](#status-code-24)
|
||||||
- [Response Body](#response-body-26)
|
- [Response Body](#response-body-26)
|
||||||
- [List Alarm State History](#list-alarm-state-history)
|
- [Response Examples](#response-examples-23)
|
||||||
- [GET /v2.0/alarms/{alarm_id}/state-history](#get-v20alarmsalarm_idstate-history)
|
- [Delete Alarm](#delete-alarm)
|
||||||
|
- [DELETE /v2.0/alarms/{alarm_id}](#delete-v20alarmsalarm_id)
|
||||||
- [Headers](#headers-27)
|
- [Headers](#headers-27)
|
||||||
- [Path Parameters](#path-parameters-26)
|
- [Path Parameters](#path-parameters-26)
|
||||||
- [Query Parameters](#query-parameters-27)
|
- [Query Parameters](#query-parameters-27)
|
||||||
- [Request Body](#request-body-27)
|
- [Request Body](#request-body-27)
|
||||||
- [Request Data](#request-data)
|
- [Request Examples](#request-examples-24)
|
||||||
- [Response](#response-27)
|
- [Response](#response-27)
|
||||||
- [Status Code](#status-code-25)
|
- [Status Code](#status-code-25)
|
||||||
- [Response Body](#response-body-27)
|
- [Response Body](#response-body-27)
|
||||||
- [Response Examples](#response-examples-23)
|
- [List Alarm State History](#list-alarm-state-history)
|
||||||
|
- [GET /v2.0/alarms/{alarm_id}/state-history](#get-v20alarmsalarm_idstate-history)
|
||||||
|
- [Headers](#headers-28)
|
||||||
|
- [Path Parameters](#path-parameters-27)
|
||||||
|
- [Query Parameters](#query-parameters-28)
|
||||||
|
- [Request Body](#request-body-28)
|
||||||
|
- [Request Data](#request-data)
|
||||||
|
- [Response](#response-28)
|
||||||
|
- [Status Code](#status-code-26)
|
||||||
|
- [Response Body](#response-body-28)
|
||||||
|
- [Response Examples](#response-examples-24)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
|
|
||||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
|
@ -1194,40 +1205,93 @@ Cache-Control: no-cache
|
||||||
* 200 - OK
|
* 200 - OK
|
||||||
|
|
||||||
#### Response Body
|
#### Response Body
|
||||||
Returns a JSON object with a 'links' array of links and an 'elements' array of metric definition objects with the following fields:
|
Returns a JSON object with a 'links' array of links and an 'elements' array of dimension values.
|
||||||
|
|
||||||
* dimension_name (string)
|
|
||||||
* metric_name (string)
|
|
||||||
* values (list of strings)
|
|
||||||
|
|
||||||
#### Response Examples
|
#### Response Examples
|
||||||
````
|
````
|
||||||
{
|
{
|
||||||
"links": [
|
"elements": [
|
||||||
{
|
{
|
||||||
"rel": "self",
|
"dimension_value": "value2"
|
||||||
"href": "http://192.168.10.4:8080/v2.0/metrics/dimensions/names/values?dimension_name=dimension_name"
|
},
|
||||||
},
|
{
|
||||||
{
|
"dimension_value": "value3"
|
||||||
"rel": "next",
|
}
|
||||||
"href": "http://192.168.10.4:8080/v2.0/metrics/dimensions/names/values?dimension_name=dimension_name&offset=dimensionValue2"
|
],
|
||||||
}
|
"links": [
|
||||||
],
|
{
|
||||||
"elements": [
|
"href": "http://192.168.10.6:8070/v2.0/metrics/dimensions/names/values?dimension_name=dim_name&offset=value1&limit=2",
|
||||||
{
|
"rel": "self"
|
||||||
"id": "b63d9bc1e16582d0ca039616ce3c870556b3095b",
|
},
|
||||||
"metric_name": "metric_name",
|
{
|
||||||
"dimension_name": "dimension_name",
|
"href": "http://192.168.10.6:8070/v2.0/metrics/dimensions/names/values?offset=value3&dimension_name=dim_name&limit=2",
|
||||||
"values": [
|
"rel": "next"
|
||||||
"dimensonValue1",
|
}
|
||||||
"dimensonValue2"
|
]
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
````
|
````
|
||||||
___
|
___
|
||||||
|
|
||||||
|
## List dimension names
|
||||||
|
Get dimension names
|
||||||
|
|
||||||
|
#### GET /v2.0/metrics/dimensions/names
|
||||||
|
|
||||||
|
#### Headers
|
||||||
|
* X-Auth-Token (string, required) - Keystone auth token
|
||||||
|
* Accept (string) - application/json
|
||||||
|
|
||||||
|
#### Path Parameters
|
||||||
|
None.
|
||||||
|
|
||||||
|
#### Query Parameters
|
||||||
|
* tenant_id (string, optional, restricted) - Tenant ID from which to get dimension names. This parameter can be used to get dimension names from a tenant other than the tenant the request auth token is scoped to. Usage of this query parameter is restricted to users with the monasca admin role, as defined in the monasca api configuration file, which defaults to `monasca-admin`.
|
||||||
|
* metric_name (string(255), optional) - A metric name to filter dimension names by.
|
||||||
|
* offset (string(255), optional) - The dimension names are returned in alphabetic order, and the offset is the dimension name after which will return in the next pagination request.
|
||||||
|
* limit (integer, optional)
|
||||||
|
|
||||||
|
#### Request Body
|
||||||
|
None.
|
||||||
|
|
||||||
|
#### Request Examples
|
||||||
|
```
|
||||||
|
GET /v2.0/metrics/dimensions/names HTTP/1.1
|
||||||
|
Host: 192.168.10.6:8070
|
||||||
|
Content-Type: application/json
|
||||||
|
X-Auth-Token: 818d3d8f10bd4987adb3f84bc94a801d
|
||||||
|
Cache-Control: no-cache
|
||||||
|
```
|
||||||
|
|
||||||
|
### Response
|
||||||
|
#### Status Code
|
||||||
|
* 200 - OK
|
||||||
|
|
||||||
|
#### Response Body
|
||||||
|
Returns a JSON object with a 'links' array of links and an 'elements' array of dimension names.
|
||||||
|
#### Response Examples
|
||||||
|
````
|
||||||
|
{
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"dimension_name": "name2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dimension_name": "name3"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"href": "http://192.168.10.6:8070/v2.0/metrics/dimensions/names?offset=name1&limit=2",
|
||||||
|
"rel": "self"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href": "http://192.168.10.6:8070/v2.0/metrics/dimensions/names?offset=name3&limit=2",
|
||||||
|
"rel": "next"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
````
|
||||||
|
|
||||||
# Measurements
|
# Measurements
|
||||||
Operations for accessing measurements of metrics.
|
Operations for accessing measurements of metrics.
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ alarms_count = monasca_api.v2.reference.alarms:AlarmsCount
|
||||||
alarms_state_history = monasca_api.v2.reference.alarms:AlarmsStateHistory
|
alarms_state_history = monasca_api.v2.reference.alarms:AlarmsStateHistory
|
||||||
notification_methods = monasca_api.v2.reference.notifications:Notifications
|
notification_methods = monasca_api.v2.reference.notifications:Notifications
|
||||||
dimension_values = monasca_api.v2.reference.metrics:DimensionValues
|
dimension_values = monasca_api.v2.reference.metrics:DimensionValues
|
||||||
|
dimension_names = monasca_api.v2.reference.metrics:DimensionNames
|
||||||
notification_method_types = monasca_api.v2.reference.notificationstype:NotificationsType
|
notification_method_types = monasca_api.v2.reference.notificationstype:NotificationsType
|
||||||
|
|
||||||
[security]
|
[security]
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package monasca.api.domain.model.dimension;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
|
import monasca.common.model.domain.common.AbstractEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for DimensionNames and DimensionValues.
|
||||||
|
*/
|
||||||
|
public abstract class DimensionBase extends AbstractEntity {
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
final private String metricName;
|
||||||
|
final private String id;
|
||||||
|
|
||||||
|
public DimensionBase(String metricName, String id) {
|
||||||
|
this.metricName = metricName;
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMetricName() {
|
||||||
|
return metricName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
DimensionBase other = (DimensionBase) obj;
|
||||||
|
if (metricName == null) {
|
||||||
|
if (other.getMetricName() != null)
|
||||||
|
return false;
|
||||||
|
} else if (!metricName.equals(other.getMetricName()))
|
||||||
|
return false;
|
||||||
|
if (id == null) {
|
||||||
|
if (other.id != null)
|
||||||
|
return false;
|
||||||
|
} else if (!id.equals(other.id))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 17;
|
||||||
|
result = prime * result + ((metricName == null) ? 0 : metricName.hashCode());
|
||||||
|
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package monasca.api.domain.model.dimension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates dimension name for an optional metric name.
|
||||||
|
*/
|
||||||
|
public class DimensionName extends DimensionBase {
|
||||||
|
final private String dimensionName;
|
||||||
|
|
||||||
|
public DimensionName(String metricName, String dimensionName) {
|
||||||
|
super(metricName, dimensionName);
|
||||||
|
this.dimensionName = dimensionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDimensionName() {
|
||||||
|
return dimensionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
DimensionName other = (DimensionName) obj;
|
||||||
|
if (dimensionName == null) {
|
||||||
|
if (other.dimensionName != null)
|
||||||
|
return false;
|
||||||
|
} else if (!dimensionName.equals(other.dimensionName))
|
||||||
|
return false;
|
||||||
|
return super.equals(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = prime * result + ((dimensionName == null) ? 0 : dimensionName.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("DimensionName: MetricName=%s DimensionName [names=%s]",
|
||||||
|
getMetricName(), dimensionName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016 Hewlett-Packard Development Company, L.P.
|
* (C) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
* in compliance with the License. You may obtain a copy of the License at
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
@ -13,10 +13,10 @@
|
||||||
*/
|
*/
|
||||||
package monasca.api.domain.model.dimension;
|
package monasca.api.domain.model.dimension;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repository for dimensions.
|
* Repository for dimensions.
|
||||||
*/
|
*/
|
||||||
|
@ -25,10 +25,19 @@ public interface DimensionRepo {
|
||||||
* Finds dimension values given a dimension name and
|
* Finds dimension values given a dimension name and
|
||||||
* optional metric name.
|
* optional metric name.
|
||||||
*/
|
*/
|
||||||
DimensionValues find(String metricName,
|
List<DimensionValue> findValues(String metricName,
|
||||||
String tenantId,
|
String tenantId,
|
||||||
String dimensionName,
|
String dimensionName,
|
||||||
@Nullable String offset,
|
@Nullable String offset,
|
||||||
int limit)
|
int limit)
|
||||||
|
throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds dimension names given an optional metric name.
|
||||||
|
*/
|
||||||
|
List<DimensionName> findNames(String metricName,
|
||||||
|
String tenantId,
|
||||||
|
@Nullable String offset,
|
||||||
|
int limit)
|
||||||
throws Exception;
|
throws Exception;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package monasca.api.domain.model.dimension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates dimension value for a given dimension name
|
||||||
|
* (and optional metric-name).
|
||||||
|
*/
|
||||||
|
public class DimensionValue extends DimensionBase {
|
||||||
|
|
||||||
|
final private String dimensionName;
|
||||||
|
final private String dimensionValue;
|
||||||
|
|
||||||
|
public DimensionValue(String metricName, String dimensionName, String dimensionValue) {
|
||||||
|
super(metricName, dimensionValue);
|
||||||
|
this.dimensionName = dimensionName;
|
||||||
|
this.dimensionValue = dimensionValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDimensionValue() {
|
||||||
|
return dimensionValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
DimensionValue other = (DimensionValue) obj;
|
||||||
|
if (dimensionName == null) {
|
||||||
|
if (other.dimensionName != null)
|
||||||
|
return false;
|
||||||
|
} else if (!dimensionName.equals(other.dimensionName))
|
||||||
|
return false;
|
||||||
|
if (dimensionValue == null) {
|
||||||
|
if (other.dimensionValue != null)
|
||||||
|
return false;
|
||||||
|
} else if (!dimensionValue.equals(other.dimensionValue))
|
||||||
|
return false;
|
||||||
|
return super.equals(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = prime * result + ((dimensionName == null) ? 0 : dimensionName.hashCode());
|
||||||
|
result = prime * result + ((dimensionValue == null) ? 0 : dimensionValue.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("DimensionValue: MetricName=%s DimensionValue [name=%s, values=%s]",
|
||||||
|
getMetricName(), dimensionName, dimensionValue);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,122 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
|
||||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
||||||
* or implied. See the License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package monasca.api.domain.model.dimension;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
|
|
||||||
import monasca.common.model.domain.common.AbstractEntity;
|
|
||||||
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
import org.apache.commons.codec.binary.Hex;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encapsulates the list of dimension values for a given dimension name
|
|
||||||
* (and optional metric-name).
|
|
||||||
*/
|
|
||||||
public class DimensionValues extends AbstractEntity {
|
|
||||||
|
|
||||||
protected String id = null;
|
|
||||||
protected String dimensionName;
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
protected String metricName;
|
|
||||||
protected List<String> values;
|
|
||||||
protected Map<String, List<String>> dimensionValues;
|
|
||||||
|
|
||||||
public DimensionValues() {
|
|
||||||
this.values = new ArrayList<String>();
|
|
||||||
this.dimensionValues = new HashMap<String, List<String>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public DimensionValues(String metricName, String dimensionName, List<String> values) {
|
|
||||||
this.metricName = metricName;
|
|
||||||
this.dimensionName = dimensionName;
|
|
||||||
this.values = values;
|
|
||||||
this.dimensionValues = new HashMap<String, List<String>>();
|
|
||||||
this.dimensionValues.put(dimensionName, values);
|
|
||||||
this.id = generateId();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getValues() {
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDimensionName() {
|
|
||||||
return dimensionName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMetricName() {
|
|
||||||
return metricName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
if (null == this.id) {
|
|
||||||
this.id = generateId();
|
|
||||||
}
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String generateId() {
|
|
||||||
String hashstr = "metricName=" + metricName + "dimensionName=" + dimensionName;
|
|
||||||
byte[] sha1Hash = DigestUtils.sha(hashstr);
|
|
||||||
return Hex.encodeHexString(sha1Hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
if (obj == null)
|
|
||||||
return false;
|
|
||||||
if (getClass() != obj.getClass())
|
|
||||||
return false;
|
|
||||||
DimensionValues other = (DimensionValues) obj;
|
|
||||||
if (dimensionName == null) {
|
|
||||||
if (other.dimensionName != null)
|
|
||||||
return false;
|
|
||||||
} else if (!dimensionName.equals(other.dimensionName))
|
|
||||||
return false;
|
|
||||||
if (metricName == null) {
|
|
||||||
if (other.metricName != null)
|
|
||||||
return false;
|
|
||||||
} else if (!metricName.equals(other.metricName))
|
|
||||||
return false;
|
|
||||||
if (values == null) {
|
|
||||||
if (other.values != null)
|
|
||||||
return false;
|
|
||||||
} else if (!values.equals(other.values))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
final int prime = 31;
|
|
||||||
int result = 1;
|
|
||||||
result = prime * result + ((dimensionName == null) ? 0 : dimensionName.hashCode());
|
|
||||||
result = prime * result + ((metricName == null) ? 0 : metricName.hashCode());
|
|
||||||
result = prime * result + ((values == null) ? 0 : values.hashCode());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("MetricName=%s DimensionValues [name=%s, values=%s]",
|
|
||||||
metricName, dimensionName, values);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016 Hewlett-Packard Development Company, L.P.
|
* (C) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
* in compliance with the License. You may obtain a copy of the License at
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
@ -14,21 +14,21 @@
|
||||||
package monasca.api.infrastructure.persistence.influxdb;
|
package monasca.api.infrastructure.persistence.influxdb;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import monasca.api.ApiConfig;
|
import monasca.api.ApiConfig;
|
||||||
import monasca.api.domain.model.dimension.DimensionValues;
|
import monasca.api.domain.model.dimension.DimensionName;
|
||||||
|
import monasca.api.domain.model.dimension.DimensionValue;
|
||||||
import monasca.api.domain.model.dimension.DimensionRepo;
|
import monasca.api.domain.model.dimension.DimensionRepo;
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ public class InfluxV9DimensionRepo implements DimensionRepo {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DimensionValues find(
|
public List<DimensionValue> findValues(
|
||||||
String metricName,
|
String metricName,
|
||||||
String tenantId,
|
String tenantId,
|
||||||
String dimensionName,
|
String dimensionName,
|
||||||
|
@ -65,6 +65,7 @@ public class InfluxV9DimensionRepo implements DimensionRepo {
|
||||||
// Use treeset to keep list in alphabetic/predictable order
|
// Use treeset to keep list in alphabetic/predictable order
|
||||||
// for string based offset.
|
// for string based offset.
|
||||||
//
|
//
|
||||||
|
List<DimensionValue> dimensionValueList = new ArrayList<>();
|
||||||
Set<String> matchingValues = new TreeSet<String>();
|
Set<String> matchingValues = new TreeSet<String>();
|
||||||
String dimNamePart = "and \""
|
String dimNamePart = "and \""
|
||||||
+ this.influxV9Utils.sanitize(dimensionName)
|
+ this.influxV9Utils.sanitize(dimensionName)
|
||||||
|
@ -93,19 +94,22 @@ public class InfluxV9DimensionRepo implements DimensionRepo {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> filteredValues = filterDimensionValues(matchingValues,
|
List<String> filteredValues = filterDimensionValues(matchingValues,
|
||||||
dimensionName,
|
|
||||||
limit,
|
limit,
|
||||||
offset);
|
offset);
|
||||||
|
|
||||||
return new DimensionValues(metricName, dimensionName, filteredValues);
|
for (String filteredValue : filteredValues) {
|
||||||
|
DimensionValue dimValue = new DimensionValue(metricName, dimensionName, filteredValue);
|
||||||
|
dimensionValueList.add(dimValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dimensionValueList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> filterDimensionValues(Set<String> matchingValues,
|
private List<String> filterDimensionValues(Set<String> matchingValues,
|
||||||
String dimensionName,
|
|
||||||
int limit,
|
int limit,
|
||||||
String offset)
|
String offset)
|
||||||
{
|
{
|
||||||
Boolean haveOffset = (null != offset && !"".equals(offset));
|
Boolean haveOffset = !Strings.isNullOrEmpty(offset);
|
||||||
List<String> filteredValues = new ArrayList<String>();
|
List<String> filteredValues = new ArrayList<String>();
|
||||||
int remaining_limit = limit + 1;
|
int remaining_limit = limit + 1;
|
||||||
|
|
||||||
|
@ -122,4 +126,68 @@ public class InfluxV9DimensionRepo implements DimensionRepo {
|
||||||
|
|
||||||
return filteredValues;
|
return filteredValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DimensionName> findNames(
|
||||||
|
String metricName,
|
||||||
|
String tenantId,
|
||||||
|
String offset,
|
||||||
|
int limit) throws Exception
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Use treeset to keep list in alphabetic/predictable order
|
||||||
|
// for string based offset.
|
||||||
|
//
|
||||||
|
List<DimensionName> dimensionNameList = new ArrayList<>();
|
||||||
|
Set<String> matchingNames = new TreeSet<String>();
|
||||||
|
|
||||||
|
String q = String.format("show series %1$s where %2$s",
|
||||||
|
this.influxV9Utils.namePart(metricName, false),
|
||||||
|
this.influxV9Utils.privateTenantIdPart(tenantId));
|
||||||
|
|
||||||
|
logger.debug("Dimension names query: {}", q);
|
||||||
|
String r = this.influxV9RepoReader.read(q);
|
||||||
|
Series series = this.objectMapper.readValue(r, Series.class);
|
||||||
|
|
||||||
|
if (!series.isEmpty()) {
|
||||||
|
for (Serie serie : series.getSeries()) {
|
||||||
|
for (String[] names : serie.getValues()) {
|
||||||
|
Map<String, String> dimensions = this.influxV9Utils.getDimensions(names, serie.getColumns());
|
||||||
|
for (Map.Entry<String, String> entry : dimensions.entrySet()) {
|
||||||
|
matchingNames.add(entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> filteredNames = filterDimensionNames(matchingNames, limit, offset);
|
||||||
|
|
||||||
|
for (String filteredName : filteredNames) {
|
||||||
|
DimensionName dimName = new DimensionName(metricName, filteredName);
|
||||||
|
dimensionNameList.add(dimName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dimensionNameList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> filterDimensionNames(Set<String> matchingNames,
|
||||||
|
int limit,
|
||||||
|
String offset) {
|
||||||
|
Boolean haveOffset = !Strings.isNullOrEmpty(offset);
|
||||||
|
List<String> filteredNames = new ArrayList<String>();
|
||||||
|
int remaining_limit = limit + 1;
|
||||||
|
|
||||||
|
for (String dimName : matchingNames) {
|
||||||
|
if (remaining_limit <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (haveOffset && dimName.compareTo(offset) <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
filteredNames.add(dimName);
|
||||||
|
remaining_limit--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredNames;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2016 Hewlett-Packard Development Company, L.P.
|
/* (C) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
* in compliance with the License. You may obtain a copy of the License at
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
@ -13,16 +13,17 @@
|
||||||
package monasca.api.infrastructure.persistence.vertica;
|
package monasca.api.infrastructure.persistence.vertica;
|
||||||
|
|
||||||
import monasca.api.ApiConfig;
|
import monasca.api.ApiConfig;
|
||||||
|
import monasca.api.domain.model.dimension.DimensionName;
|
||||||
import monasca.api.domain.model.dimension.DimensionRepo;
|
import monasca.api.domain.model.dimension.DimensionRepo;
|
||||||
import monasca.api.domain.model.dimension.DimensionValues;
|
import monasca.api.domain.model.dimension.DimensionValue;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.skife.jdbi.v2.DBI;
|
import org.skife.jdbi.v2.DBI;
|
||||||
import org.skife.jdbi.v2.Handle;
|
import org.skife.jdbi.v2.Handle;
|
||||||
|
@ -53,6 +54,23 @@ public class DimensionVerticaRepoImpl implements DimensionRepo {
|
||||||
+ "ORDER BY dims.value ASC "
|
+ "ORDER BY dims.value ASC "
|
||||||
+ "%s "; // limit goes here
|
+ "%s "; // limit goes here
|
||||||
|
|
||||||
|
private static final String FIND_DIMENSION_NAMES_SQL =
|
||||||
|
"SELECT %s" // dbHint goes here
|
||||||
|
+ " DISTINCT dims.name as dName "
|
||||||
|
+ "FROM "
|
||||||
|
+ " MonMetrics.Definitions def,"
|
||||||
|
+ " MonMetrics.DefinitionDimensions defdims "
|
||||||
|
+ "LEFT OUTER JOIN"
|
||||||
|
+ " MonMetrics.Dimensions dims"
|
||||||
|
+ " ON dims.dimension_set_id = defdims.dimension_set_id "
|
||||||
|
+ "WHERE "
|
||||||
|
+ " def.id = defdims.definition_id"
|
||||||
|
+ " %s " // optional offset goes here
|
||||||
|
+ " %s " // metric name goes here
|
||||||
|
+ " and def.tenant_id = '%s' " // tenant_id goes here
|
||||||
|
+ "ORDER BY dims.name ASC "
|
||||||
|
+ "%s "; // limit goes here
|
||||||
|
|
||||||
private final DBI db;
|
private final DBI db;
|
||||||
private final String dbHint;
|
private final String dbHint;
|
||||||
|
|
||||||
|
@ -65,25 +83,24 @@ public class DimensionVerticaRepoImpl implements DimensionRepo {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DimensionValues find(
|
public List<DimensionValue> findValues(
|
||||||
String metricName,
|
String metricName,
|
||||||
String tenantId,
|
String tenantId,
|
||||||
String dimensionName,
|
String dimensionName,
|
||||||
String offset,
|
String offset,
|
||||||
int limit) throws Exception
|
int limit) throws Exception
|
||||||
{
|
{
|
||||||
List<String> values = new ArrayList<String>();
|
|
||||||
String offsetPart = "";
|
String offsetPart = "";
|
||||||
String metricNamePart = "";
|
String metricNamePart = "";
|
||||||
|
|
||||||
try (Handle h = db.open()) {
|
try (Handle h = db.open()) {
|
||||||
|
|
||||||
if (offset != null && !offset.isEmpty()) {
|
if (offset != null && !offset.isEmpty()) {
|
||||||
offsetPart = " and dims.value > '" + offset + "' ";
|
offsetPart = " and dims.value > :offset";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metricName != null && !metricName.isEmpty()) {
|
if (metricName != null && !metricName.isEmpty()) {
|
||||||
metricNamePart = " and def.name = '" + metricName + "' ";
|
metricNamePart = " and def.name = :metricName";
|
||||||
}
|
}
|
||||||
|
|
||||||
String limitPart = " limit " + Integer.toString(limit + 1);
|
String limitPart = " limit " + Integer.toString(limit + 1);
|
||||||
|
@ -98,12 +115,82 @@ public class DimensionVerticaRepoImpl implements DimensionRepo {
|
||||||
|
|
||||||
Query<Map<String, Object>> query = h.createQuery(sql);
|
Query<Map<String, Object>> query = h.createQuery(sql);
|
||||||
|
|
||||||
List<Map<String, Object>> rows = query.list();
|
|
||||||
for (Map<String, Object> row : rows) {
|
if (!Strings.isNullOrEmpty(offset)) {
|
||||||
String dimValue = (String) row.get("dValue");
|
logger.debug("binding offset: {}", offset);
|
||||||
values.add(dimValue);
|
query.bind("offset", offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Strings.isNullOrEmpty(metricName)) {
|
||||||
|
logger.debug("binding metricName: {}", metricName);
|
||||||
|
query.bind("metricName", metricName);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map<String, Object>> rows = query.list();
|
||||||
|
|
||||||
|
List<DimensionValue> dimensionValuesList = new ArrayList<>(rows.size());
|
||||||
|
|
||||||
|
for (Map<String, Object> row : rows) {
|
||||||
|
String dimensionValue = (String) row.get("dValue");
|
||||||
|
DimensionValue dimValue = new DimensionValue(metricName, dimensionName, dimensionValue);
|
||||||
|
dimensionValuesList.add(dimValue);
|
||||||
|
}
|
||||||
|
return dimensionValuesList;
|
||||||
}
|
}
|
||||||
return new DimensionValues(metricName, dimensionName, values);
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DimensionName> findNames(
|
||||||
|
String metricName,
|
||||||
|
String tenantId,
|
||||||
|
String offset,
|
||||||
|
int limit) throws Exception
|
||||||
|
{
|
||||||
|
String offsetPart = "";
|
||||||
|
String metricNamePart = "";
|
||||||
|
|
||||||
|
try (Handle h = db.open()) {
|
||||||
|
|
||||||
|
if (!Strings.isNullOrEmpty(offset)) {
|
||||||
|
offsetPart = " and dims.name > :offset";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Strings.isNullOrEmpty(metricName)) {
|
||||||
|
metricNamePart = " and def.name = :metricName";
|
||||||
|
}
|
||||||
|
|
||||||
|
String limitPart = " limit " + Integer.toString(limit + 1);
|
||||||
|
|
||||||
|
String sql = String.format(FIND_DIMENSION_NAMES_SQL,
|
||||||
|
this.dbHint,
|
||||||
|
offsetPart,
|
||||||
|
metricNamePart,
|
||||||
|
tenantId,
|
||||||
|
limitPart);
|
||||||
|
|
||||||
|
Query<Map<String, Object>> query = h.createQuery(sql);
|
||||||
|
|
||||||
|
if (!Strings.isNullOrEmpty(offset)) {
|
||||||
|
logger.debug("binding offset: {}", offset);
|
||||||
|
query.bind("offset", offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Strings.isNullOrEmpty(metricName)) {
|
||||||
|
logger.debug("binding metricName: {}", metricName);
|
||||||
|
query.bind("metricName", metricName);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map<String, Object>> rows = query.list();
|
||||||
|
List<DimensionName> dimensionNamesList = new ArrayList<>(rows.size());
|
||||||
|
|
||||||
|
for (Map<String, Object> row : rows) {
|
||||||
|
String dimensionName = (String) row.get("dName");
|
||||||
|
DimensionName dimName = new DimensionName(metricName, dimensionName);
|
||||||
|
dimensionNamesList.add(dimName);
|
||||||
|
}
|
||||||
|
return dimensionNamesList;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016 Hewlett-Packard Development Company, L.P.
|
* (C) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
* in compliance with the License. You may obtain a copy of the License at
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
@ -15,12 +15,10 @@ package monasca.api.resource;
|
||||||
|
|
||||||
import static monasca.api.app.validation.Validation.DEFAULT_ADMIN_ROLE;
|
import static monasca.api.app.validation.Validation.DEFAULT_ADMIN_ROLE;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
|
|
||||||
import com.codahale.metrics.annotation.Timed;
|
import com.codahale.metrics.annotation.Timed;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
|
@ -32,35 +30,36 @@ import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
||||||
import monasca.api.app.validation.MetricNameValidation;
|
|
||||||
import monasca.api.ApiConfig;
|
import monasca.api.ApiConfig;
|
||||||
import monasca.api.app.validation.Validation;
|
import monasca.api.app.validation.Validation;
|
||||||
|
import monasca.api.domain.model.dimension.DimensionName;
|
||||||
import monasca.api.domain.model.dimension.DimensionRepo;
|
import monasca.api.domain.model.dimension.DimensionRepo;
|
||||||
import monasca.api.domain.model.dimension.DimensionValues;
|
import monasca.api.domain.model.dimension.DimensionValue;
|
||||||
import monasca.api.infrastructure.persistence.PersistUtils;
|
import monasca.api.infrastructure.persistence.PersistUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dimension resource implementation.
|
* Dimension resource implementation.
|
||||||
*/
|
*/
|
||||||
@Path("/v2.0/metrics/dimensions/names/values")
|
@Path("/v2.0/metrics/dimensions")
|
||||||
public class DimensionResource {
|
public class DimensionResource {
|
||||||
|
|
||||||
private final DimensionRepo repo;
|
private final DimensionRepo repo;
|
||||||
private final PersistUtils persistUtils;
|
private final PersistUtils persistUtils;
|
||||||
private final String admin_role;
|
private final String adminRole;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public DimensionResource(ApiConfig config, DimensionRepo repo, PersistUtils persistUtils) {
|
public DimensionResource(ApiConfig config, DimensionRepo repo, PersistUtils persistUtils) {
|
||||||
this.admin_role = (config.middleware == null || config.middleware.adminRole == null)
|
this.adminRole = (config.middleware == null || config.middleware.adminRole == null)
|
||||||
? DEFAULT_ADMIN_ROLE : config.middleware.adminRole;
|
? DEFAULT_ADMIN_ROLE : config.middleware.adminRole;
|
||||||
this.repo = repo;
|
this.repo = repo;
|
||||||
this.persistUtils = persistUtils;
|
this.persistUtils = persistUtils;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
@Path("/names/values")
|
||||||
@Timed
|
@Timed
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Object get(
|
public Object getDimensionValues(
|
||||||
@Context UriInfo uriInfo,
|
@Context UriInfo uriInfo,
|
||||||
@HeaderParam("X-Tenant-Id") String tenantId,
|
@HeaderParam("X-Tenant-Id") String tenantId,
|
||||||
@HeaderParam("X-Roles") String roles,
|
@HeaderParam("X-Roles") String roles,
|
||||||
|
@ -71,9 +70,28 @@ public class DimensionResource {
|
||||||
@QueryParam("tenant_id") String crossTenantId) throws Exception
|
@QueryParam("tenant_id") String crossTenantId) throws Exception
|
||||||
{
|
{
|
||||||
Validation.validateNotNullOrEmpty(dimensionName, "dimension_name");
|
Validation.validateNotNullOrEmpty(dimensionName, "dimension_name");
|
||||||
|
final int pagingLimit = this.persistUtils.getLimit(limit);
|
||||||
|
String queryTenantId = Validation.getQueryProject(roles, crossTenantId, tenantId, adminRole);
|
||||||
|
List<DimensionValue> dimValues = repo.findValues(metricName, queryTenantId, dimensionName, offset, pagingLimit);
|
||||||
|
return Links.paginate(pagingLimit, dimValues, uriInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/names")
|
||||||
|
@Timed
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Object getDimensionNames(
|
||||||
|
@Context UriInfo uriInfo,
|
||||||
|
@HeaderParam("X-Tenant-Id") String tenantId,
|
||||||
|
@HeaderParam("X-Roles") String roles,
|
||||||
|
@QueryParam("limit") String limit,
|
||||||
|
@QueryParam("metric_name") String metricName,
|
||||||
|
@QueryParam("offset") String offset,
|
||||||
|
@QueryParam("tenant_id") String crossTenantId) throws Exception
|
||||||
|
{
|
||||||
final int paging_limit = this.persistUtils.getLimit(limit);
|
final int paging_limit = this.persistUtils.getLimit(limit);
|
||||||
String queryTenantId = Validation.getQueryProject(roles, crossTenantId, tenantId, admin_role);
|
String queryTenantId = Validation.getQueryProject(roles, crossTenantId, tenantId, adminRole);
|
||||||
DimensionValues dimVals = repo.find(metricName, queryTenantId, dimensionName, offset, paging_limit);
|
List<DimensionName> dimNames = repo.findNames(metricName, queryTenantId, offset, paging_limit);
|
||||||
return Links.paginateDimensionValues(dimVals, paging_limit, uriInfo);
|
return Links.paginate(paging_limit, dimNames, uriInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
|
* (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
* in compliance with the License. You may obtain a copy of the License at
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
@ -26,7 +26,7 @@ import com.google.common.base.Preconditions;
|
||||||
import monasca.api.ApiConfig;
|
import monasca.api.ApiConfig;
|
||||||
import monasca.api.domain.model.alarm.AlarmCount;
|
import monasca.api.domain.model.alarm.AlarmCount;
|
||||||
import monasca.api.domain.model.common.Paged;
|
import monasca.api.domain.model.common.Paged;
|
||||||
import monasca.api.domain.model.dimension.DimensionValues;
|
import monasca.api.domain.model.dimension.DimensionBase;
|
||||||
import monasca.api.domain.model.measurement.Measurements;
|
import monasca.api.domain.model.measurement.Measurements;
|
||||||
import monasca.common.model.domain.common.AbstractEntity;
|
import monasca.common.model.domain.common.AbstractEntity;
|
||||||
import monasca.api.domain.model.common.Link;
|
import monasca.api.domain.model.common.Link;
|
||||||
|
@ -360,21 +360,4 @@ public final class Links {
|
||||||
alarmCount.setLinks(links);
|
alarmCount.setLinks(links);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Paged paginateDimensionValues(DimensionValues dimVals, int limit, UriInfo uriInfo)
|
|
||||||
throws UnsupportedEncodingException {
|
|
||||||
Paged paged = new Paged();
|
|
||||||
List<DimensionValues> elements = new ArrayList<DimensionValues>();
|
|
||||||
paged.links.add(getSelfLink(uriInfo));
|
|
||||||
|
|
||||||
if ((null != dimVals) && (dimVals.getValues().size() > limit)) {
|
|
||||||
dimVals.getValues().remove(dimVals.getValues().size()-1);
|
|
||||||
String offset = dimVals.getValues().get(dimVals.getValues().size()-1);
|
|
||||||
paged.links.add(getNextLink(offset, uriInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
elements.add(dimVals);
|
|
||||||
paged.elements = elements;
|
|
||||||
return paged;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016 Hewlett-Packard Development Company, L.P.
|
* (C) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
* in compliance with the License. You may obtain a copy of the License at
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
@ -14,18 +14,11 @@
|
||||||
|
|
||||||
package monasca.api.resource;
|
package monasca.api.resource;
|
||||||
|
|
||||||
import static org.mockito.Matchers.any;
|
|
||||||
import static org.mockito.Matchers.anyBoolean;
|
|
||||||
import static org.mockito.Matchers.anyInt;
|
import static org.mockito.Matchers.anyInt;
|
||||||
import static org.mockito.Matchers.anyString;
|
import static org.mockito.Matchers.anyString;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.joda.time.DateTime;
|
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import monasca.api.ApiConfig;
|
import monasca.api.ApiConfig;
|
||||||
|
@ -49,23 +42,32 @@ public class DimensionResourceTest extends AbstractMonApiResourceTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void shouldQueryWithDefaultParams() throws Exception {
|
public void shouldQueryDimensionValuesWithDefaultParams() throws Exception {
|
||||||
|
|
||||||
client()
|
client()
|
||||||
.resource(
|
.resource(
|
||||||
"/v2.0/metrics/dimensions/names/values?dimension_name=hpcs.compute")
|
"/v2.0/metrics/dimensions/names/values?dimension_name=hpcs.compute")
|
||||||
.header("X-Tenant-Id", "abc").get(ClientResponse.class);
|
.header("X-Tenant-Id", "abc").get(ClientResponse.class);
|
||||||
verify(dimensionRepo).find(anyString(), anyString(), anyString(), anyString(),
|
verify(dimensionRepo).findValues(anyString(), anyString(), anyString(), anyString(),
|
||||||
anyInt());
|
anyInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shouldQueryWithOptionalMetricName() throws Exception {
|
public void shouldQueryDimensionValuesWithOptionalMetricName() throws Exception {
|
||||||
|
|
||||||
client()
|
client()
|
||||||
.resource(
|
.resource(
|
||||||
"/v2.0/metrics/dimensions/names/values?dimension_name=hpcs.compute&metric_name=cpu_utilization")
|
"/v2.0/metrics/dimensions/names/values?dimension_name=hpcs.compute&metric_name=cpu_utilization")
|
||||||
.header("X-Tenant-Id", "abc").get(ClientResponse.class);
|
.header("X-Tenant-Id", "abc").get(ClientResponse.class);
|
||||||
verify(dimensionRepo).find(anyString(), anyString(), anyString(), anyString(),
|
verify(dimensionRepo).findValues(anyString(), anyString(), anyString(), anyString(),
|
||||||
anyInt());
|
anyInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void shouldQueryDimensionNamesWithDefaultParams() throws Exception {
|
||||||
|
|
||||||
|
client()
|
||||||
|
.resource(
|
||||||
|
"/v2.0/metrics/dimensions/names")
|
||||||
|
.header("X-Tenant-Id", "abc").get(ClientResponse.class);
|
||||||
|
verify(dimensionRepo).findNames(anyString(), anyString(), anyString(), anyInt());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* (C) Copyright 2015-2016 Hewlett Packard Enterprise Development Company LP
|
* (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
* in compliance with the License. You may obtain a copy of the License at
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
@ -18,7 +18,6 @@ import monasca.api.domain.model.alarm.Alarm;
|
||||||
import monasca.api.domain.model.common.Link;
|
import monasca.api.domain.model.common.Link;
|
||||||
import monasca.api.domain.model.common.Paged;
|
import monasca.api.domain.model.common.Paged;
|
||||||
import monasca.common.model.alarm.AlarmState;
|
import monasca.common.model.alarm.AlarmState;
|
||||||
import monasca.api.domain.model.dimension.DimensionValues;
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
@ -135,49 +134,4 @@ public class LinksTest {
|
||||||
+ ALARM_DEF_ID));
|
+ ALARM_DEF_ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verifyPaginateDimensionValues() throws UnsupportedEncodingException, URISyntaxException{
|
|
||||||
final String base = "http://TheVip:8070/v2.0/metrics/dimensions/names/values";
|
|
||||||
final String limitParam = "limit=1";
|
|
||||||
final String url = base + "?" + limitParam;
|
|
||||||
final UriInfo uriInfo = mock(UriInfo.class);
|
|
||||||
when(uriInfo.getRequestUri()).thenReturn(new URI(url));
|
|
||||||
when(uriInfo.getAbsolutePath()).thenReturn(new URI(base));
|
|
||||||
|
|
||||||
final Map<String, String> params = new HashMap<>();
|
|
||||||
params.put("limit", "1");
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final MultivaluedMap<String, String> mockParams = mock(MultivaluedMap.class);
|
|
||||||
when(uriInfo.getQueryParameters()).thenReturn(mockParams);
|
|
||||||
when(mockParams.keySet()).thenReturn(params.keySet());
|
|
||||||
when(mockParams.get("limit")).thenReturn(Arrays.asList("1"));
|
|
||||||
|
|
||||||
List<String> values = new ArrayList<String>();
|
|
||||||
values.add("value1");
|
|
||||||
values.add("value2");
|
|
||||||
List<String> oneValue = Arrays.asList("value1");
|
|
||||||
|
|
||||||
DimensionValues dimVals = new DimensionValues("custom_metric",
|
|
||||||
"dimension_name",
|
|
||||||
values);
|
|
||||||
|
|
||||||
DimensionValues expectedDimVal = new DimensionValues("custom_metric",
|
|
||||||
"dimension_name",
|
|
||||||
oneValue);
|
|
||||||
final int limit = 1;
|
|
||||||
final Paged expected = new Paged();
|
|
||||||
final List<Link> links = new ArrayList<>();
|
|
||||||
String expectedSelf = url;
|
|
||||||
String expectedNext = base + "?offset=value1&" + limitParam;
|
|
||||||
links.add(new Link("self", expectedSelf));
|
|
||||||
links.add(new Link("next", expectedNext));
|
|
||||||
expected.links = links;
|
|
||||||
|
|
||||||
final ArrayList<DimensionValues> expectedElements = new ArrayList<DimensionValues>();
|
|
||||||
// Since limit is one, only the first element is returned
|
|
||||||
expectedElements.add(expectedDimVal);
|
|
||||||
expected.elements = expectedElements;
|
|
||||||
|
|
||||||
final Paged actual = Links.paginateDimensionValues(dimVals, 1, uriInfo);
|
|
||||||
assertEquals(actual, expected);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright 2014 IBM Corp
|
# Copyright 2014 IBM Corp
|
||||||
# Copyright 2014 Hewlett-Packard
|
# (C) Copyright 2014,2016 Hewlett Packard Enterprise Development LP
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
@ -64,3 +64,12 @@ class DimensionValuesV2API(object):
|
||||||
|
|
||||||
def on_get(self, req, res):
|
def on_get(self, req, res):
|
||||||
res.status = '501 Not Implemented'
|
res.status = '501 Not Implemented'
|
||||||
|
|
||||||
|
|
||||||
|
class DimensionNamesV2API(object):
|
||||||
|
def __init__(self):
|
||||||
|
super(DimensionNamesV2API, self).__init__()
|
||||||
|
LOG.info('Initializing DimensionNamesV2API!')
|
||||||
|
|
||||||
|
def on_get(self, req, res):
|
||||||
|
res.status = '501 Not Implemented'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright 2014 IBM Corp
|
# Copyright 2014 IBM Corp
|
||||||
# Copyright 2015-2016 Hewlett Packard Enterprise Development LP
|
# (C) Copyright 2015,2016 Hewlett Packard Enterprise Development LP
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
@ -46,6 +46,8 @@ dispatcher_opts = [cfg.StrOpt('versions', default=None,
|
||||||
help='Notification methods'),
|
help='Notification methods'),
|
||||||
cfg.StrOpt('dimension_values', default=None,
|
cfg.StrOpt('dimension_values', default=None,
|
||||||
help='Dimension values'),
|
help='Dimension values'),
|
||||||
|
cfg.StrOpt('dimension_names', default=None,
|
||||||
|
help='Dimension names'),
|
||||||
cfg.StrOpt('notification_method_types', default=None,
|
cfg.StrOpt('notification_method_types', default=None,
|
||||||
help='notification_method_types methods')]
|
help='notification_method_types methods')]
|
||||||
|
|
||||||
|
@ -115,6 +117,9 @@ def launch(conf, config_file="/etc/monasca/api-config.conf"):
|
||||||
dimension_values = simport.load(cfg.CONF.dispatcher.dimension_values)()
|
dimension_values = simport.load(cfg.CONF.dispatcher.dimension_values)()
|
||||||
app.add_route("/v2.0/metrics/dimensions/names/values", dimension_values)
|
app.add_route("/v2.0/metrics/dimensions/names/values", dimension_values)
|
||||||
|
|
||||||
|
dimension_names = simport.load(cfg.CONF.dispatcher.dimension_names)()
|
||||||
|
app.add_route("/v2.0/metrics/dimensions/names", dimension_names)
|
||||||
|
|
||||||
notification_method_types = simport.load(
|
notification_method_types = simport.load(
|
||||||
cfg.CONF.dispatcher.notification_method_types)()
|
cfg.CONF.dispatcher.notification_method_types)()
|
||||||
app.add_route("/v2.0/notification-methods/types", notification_method_types)
|
app.add_route("/v2.0/notification-methods/types", notification_method_types)
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import hashlib
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from influxdb import client
|
from influxdb import client
|
||||||
|
@ -207,28 +206,11 @@ class MetricsRepository(metrics_repository.AbstractMetricsRepository):
|
||||||
LOG.exception(ex)
|
LOG.exception(ex)
|
||||||
raise exceptions.RepositoryException(ex)
|
raise exceptions.RepositoryException(ex)
|
||||||
|
|
||||||
def _generate_dimension_values_id(self, metric_name, dimension_name):
|
def _build_serie_dimension_values(self, series_names, dimension_name):
|
||||||
sha1 = hashlib.sha1()
|
dim_values = []
|
||||||
hashstr = "metricName=" + (metric_name or "") + "dimensionName=" + dimension_name
|
json_dim_value_list = []
|
||||||
sha1.update(hashstr)
|
|
||||||
return sha1.hexdigest()
|
|
||||||
|
|
||||||
def _build_serie_dimension_values(self, series_names, metric_name, dimension_name,
|
|
||||||
tenant_id, region, offset):
|
|
||||||
dim_vals = []
|
|
||||||
sha1_id = self._generate_dimension_values_id(metric_name, dimension_name)
|
|
||||||
json_dim_vals = {u'id': sha1_id,
|
|
||||||
u'dimension_name': dimension_name,
|
|
||||||
u'values': dim_vals}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Only return metric name if one was provided
|
|
||||||
#
|
|
||||||
if metric_name:
|
|
||||||
json_dim_vals[u'metric_name'] = metric_name
|
|
||||||
|
|
||||||
if not series_names:
|
if not series_names:
|
||||||
return json_dim_vals
|
return json_dim_value_list
|
||||||
|
|
||||||
if 'series' in series_names.raw:
|
if 'series' in series_names.raw:
|
||||||
for series in series_names.raw['series']:
|
for series in series_names.raw['series']:
|
||||||
|
@ -240,12 +222,29 @@ class MetricsRepository(metrics_repository.AbstractMetricsRepository):
|
||||||
if value and not name.startswith(u'_')
|
if value and not name.startswith(u'_')
|
||||||
}
|
}
|
||||||
|
|
||||||
if dimension_name in dims and dims[dimension_name] not in dim_vals:
|
if dimension_name in dims and dims[dimension_name] not in\
|
||||||
dim_vals.append(dims[dimension_name])
|
dim_values:
|
||||||
|
dim_values.append(dims[dimension_name])
|
||||||
|
json_dim_value_list.append({u'dimension_value':
|
||||||
|
dims[dimension_name]})
|
||||||
|
|
||||||
dim_vals = sorted(dim_vals)
|
json_dim_value_list = sorted(json_dim_value_list)
|
||||||
json_dim_vals[u'values'] = dim_vals
|
return json_dim_value_list
|
||||||
return json_dim_vals
|
|
||||||
|
def _build_serie_dimension_names(self, series_names):
|
||||||
|
dim_names = []
|
||||||
|
json_dim_name_list = []
|
||||||
|
if not series_names:
|
||||||
|
return json_dim_name_list
|
||||||
|
|
||||||
|
if 'series' in series_names.raw:
|
||||||
|
for series in series_names.raw['series']:
|
||||||
|
for name in series[u'columns']:
|
||||||
|
if name not in dim_names and not name.startswith(u'_'):
|
||||||
|
dim_names.append(name)
|
||||||
|
json_dim_name_list.append({u'dimension_name': name})
|
||||||
|
json_dim_name_list = sorted(json_dim_name_list)
|
||||||
|
return json_dim_name_list
|
||||||
|
|
||||||
def _build_serie_metric_list(self, series_names, tenant_id, region,
|
def _build_serie_metric_list(self, series_names, tenant_id, region,
|
||||||
start_timestamp, end_timestamp,
|
start_timestamp, end_timestamp,
|
||||||
|
@ -619,21 +618,25 @@ class MetricsRepository(metrics_repository.AbstractMetricsRepository):
|
||||||
return int((dt - datetime(1970, 1, 1)).total_seconds() * 1000)
|
return int((dt - datetime(1970, 1, 1)).total_seconds() * 1000)
|
||||||
|
|
||||||
def list_dimension_values(self, tenant_id, region, metric_name,
|
def list_dimension_values(self, tenant_id, region, metric_name,
|
||||||
dimension_name, offset, limit):
|
dimension_name):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
query = self._build_show_series_query(None, metric_name, tenant_id, region)
|
query = self._build_show_series_query(None, metric_name,
|
||||||
|
tenant_id, region)
|
||||||
result = self.influxdb_client.query(query)
|
result = self.influxdb_client.query(query)
|
||||||
|
json_dim_name_list = self._build_serie_dimension_values(
|
||||||
json_dim_vals = self._build_serie_dimension_values(result,
|
result, dimension_name)
|
||||||
metric_name,
|
return json_dim_name_list
|
||||||
dimension_name,
|
except Exception as ex:
|
||||||
tenant_id,
|
LOG.exception(ex)
|
||||||
region,
|
raise exceptions.RepositoryException(ex)
|
||||||
offset)
|
|
||||||
|
def list_dimension_names(self, tenant_id, region, metric_name):
|
||||||
return json_dim_vals
|
try:
|
||||||
|
query = self._build_show_series_query(None, metric_name,
|
||||||
|
tenant_id, region)
|
||||||
|
result = self.influxdb_client.query(query)
|
||||||
|
json_dim_name_list = self._build_serie_dimension_names(result)
|
||||||
|
return json_dim_name_list
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
LOG.exception(ex)
|
LOG.exception(ex)
|
||||||
raise exceptions.RepositoryException(ex)
|
raise exceptions.RepositoryException(ex)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Copyright 2015 Cray Inc. All Rights Reserved.
|
# Copyright 2015 Cray Inc. All Rights Reserved.
|
||||||
|
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
@ -152,18 +153,40 @@ class TestRepoMetricsInfluxDB(unittest.TestCase):
|
||||||
"38dc2a2549f94d2e9a4fa1cc45a4970c",
|
"38dc2a2549f94d2e9a4fa1cc45a4970c",
|
||||||
"useast",
|
"useast",
|
||||||
"custom_metric",
|
"custom_metric",
|
||||||
"hostname",
|
"hostname")
|
||||||
offset=None,
|
|
||||||
limit=1)
|
|
||||||
|
|
||||||
self.assertEqual(result, {
|
self.assertEqual(result, [{u'dimension_value': u'custom_host'}])
|
||||||
u'dimension_name': 'hostname',
|
|
||||||
u'values': [
|
@patch("monasca_api.common.repositories.influxdb.metrics_repository.client.InfluxDBClient")
|
||||||
u'custom_host'
|
def test_list_dimension_names(self, influxdb_client_mock):
|
||||||
],
|
mock_client = influxdb_client_mock.return_value
|
||||||
u'id': 'bea9565d854a16a3366164de213694c190f27675',
|
mock_client.query.return_value.raw = {
|
||||||
u'metric_name': 'custom_metric'
|
u'series': [{
|
||||||
})
|
u'values': [[
|
||||||
|
u'custom_metric,_region=useast,_tenant_id=38dc2a2549f94d2e9a4fa1cc45a4970c,'
|
||||||
|
u'hostname=custom_host,service=custom_service',
|
||||||
|
u'useast',
|
||||||
|
u'38dc2a2549f94d2e9a4fa1cc45a4970c',
|
||||||
|
u'custom_host',
|
||||||
|
u'custom_service'
|
||||||
|
]],
|
||||||
|
u'name': u'custom_metric',
|
||||||
|
u'columns': [u'_key', u'_region', u'_tenant_id', u'hostname', u'service']
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
repo = influxdb_repo.MetricsRepository()
|
||||||
|
|
||||||
|
result = repo.list_dimension_names(
|
||||||
|
"38dc2a2549f94d2e9a4fa1cc45a4970c",
|
||||||
|
"useast",
|
||||||
|
"custom_metric")
|
||||||
|
|
||||||
|
self.assertEqual(result,
|
||||||
|
[
|
||||||
|
{u'dimension_name': u'hostname'},
|
||||||
|
{u'dimension_name': u'service'}
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
class TestRepoMetricsCassandra(testtools.TestCase):
|
class TestRepoMetricsCassandra(testtools.TestCase):
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright 2015 Cray Inc. All Rights Reserved.
|
# Copyright 2015 Cray Inc. All Rights Reserved.
|
||||||
# Copyright 2014, 2016 Hewlett Packard Enterprise Development LP
|
# Copyright 2014,2016 Hewlett Packard Enterprise Development LP
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
@ -463,61 +463,6 @@ def paginate_alarming(resource, uri, limit):
|
||||||
return resource
|
return resource
|
||||||
|
|
||||||
|
|
||||||
def paginate_dimension_values(dimvals, uri, offset, limit):
|
|
||||||
|
|
||||||
parsed_uri = urlparse.urlparse(uri)
|
|
||||||
self_link = build_base_uri(parsed_uri)
|
|
||||||
old_query_params = _get_old_query_params(parsed_uri)
|
|
||||||
|
|
||||||
if old_query_params:
|
|
||||||
self_link += '?' + '&'.join(old_query_params)
|
|
||||||
|
|
||||||
if (dimvals and dimvals[u'values']):
|
|
||||||
have_more, truncated_values = _truncate_dimension_values(dimvals[u'values'],
|
|
||||||
limit,
|
|
||||||
offset)
|
|
||||||
|
|
||||||
links = [{u'rel': u'self', u'href': self_link.decode('utf8')}]
|
|
||||||
if have_more:
|
|
||||||
new_offset = truncated_values[limit - 1]
|
|
||||||
next_link = build_base_uri(parsed_uri)
|
|
||||||
new_query_params = [u'offset' + '=' + urlparse.quote(
|
|
||||||
new_offset.encode('utf8'), safe='')]
|
|
||||||
|
|
||||||
_get_old_query_params_except_offset(new_query_params, parsed_uri)
|
|
||||||
|
|
||||||
if new_query_params:
|
|
||||||
next_link += '?' + '&'.join(new_query_params)
|
|
||||||
|
|
||||||
links.append({u'rel': u'next', u'href': next_link.decode('utf8')})
|
|
||||||
|
|
||||||
truncated_dimvals = {u'id': dimvals[u'id'],
|
|
||||||
u'dimension_name': dimvals[u'dimension_name'],
|
|
||||||
u'values': truncated_values}
|
|
||||||
#
|
|
||||||
# Only return metric name if one was provided
|
|
||||||
#
|
|
||||||
if u'metric_name' in dimvals:
|
|
||||||
truncated_dimvals[u'metric_name'] = dimvals[u'metric_name']
|
|
||||||
|
|
||||||
resource = {u'links': links,
|
|
||||||
u'elements': [truncated_dimvals]}
|
|
||||||
else:
|
|
||||||
resource = {u'links': ([{u'rel': u'self',
|
|
||||||
u'href': self_link.decode('utf8')}]),
|
|
||||||
u'elements': [dimvals]}
|
|
||||||
|
|
||||||
return resource
|
|
||||||
|
|
||||||
|
|
||||||
def _truncate_dimension_values(values, limit, offset):
|
|
||||||
if offset and offset in values:
|
|
||||||
next_value_pos = values.index(offset) + 1
|
|
||||||
values = values[next_value_pos:]
|
|
||||||
have_more = len(values) > limit
|
|
||||||
return have_more, values[:limit]
|
|
||||||
|
|
||||||
|
|
||||||
def paginate_measurement(measurement, uri, limit):
|
def paginate_measurement(measurement, uri, limit):
|
||||||
parsed_uri = urlparse.urlparse(uri)
|
parsed_uri = urlparse.urlparse(uri)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# (C) Copyright 2014, 2016 Hewlett Packard Enterprise Development Company LP
|
# (C) Copyright 2014, 2016 Hewlett Packard Enterprise Development LP
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
@ -327,7 +327,8 @@ class DimensionValues(metrics_api_v2.DimensionValuesV2API):
|
||||||
helpers.validate_authorization(req, self._get_metrics_authorized_roles)
|
helpers.validate_authorization(req, self._get_metrics_authorized_roles)
|
||||||
tenant_id = helpers.get_tenant_id(req)
|
tenant_id = helpers.get_tenant_id(req)
|
||||||
metric_name = helpers.get_query_param(req, 'metric_name')
|
metric_name = helpers.get_query_param(req, 'metric_name')
|
||||||
dimension_name = helpers.get_query_param(req, 'dimension_name', required=True)
|
dimension_name = helpers.get_query_param(req, 'dimension_name',
|
||||||
|
required=True)
|
||||||
offset = helpers.get_query_param(req, 'offset')
|
offset = helpers.get_query_param(req, 'offset')
|
||||||
limit = helpers.get_limit(req)
|
limit = helpers.get_limit(req)
|
||||||
result = self._dimension_values(tenant_id, req.uri, metric_name,
|
result = self._dimension_values(tenant_id, req.uri, metric_name,
|
||||||
|
@ -342,8 +343,43 @@ class DimensionValues(metrics_api_v2.DimensionValuesV2API):
|
||||||
result = self._metrics_repo.list_dimension_values(tenant_id,
|
result = self._metrics_repo.list_dimension_values(tenant_id,
|
||||||
self._region,
|
self._region,
|
||||||
metric_name,
|
metric_name,
|
||||||
dimension_name,
|
dimension_name)
|
||||||
offset,
|
|
||||||
limit)
|
|
||||||
|
|
||||||
return helpers.paginate_dimension_values(result, req_uri, offset, limit)
|
return helpers.paginate_with_no_id(result, req_uri, offset, limit)
|
||||||
|
|
||||||
|
|
||||||
|
class DimensionNames(metrics_api_v2.DimensionNamesV2API):
|
||||||
|
def __init__(self):
|
||||||
|
try:
|
||||||
|
super(DimensionNames, self).__init__()
|
||||||
|
self._region = cfg.CONF.region
|
||||||
|
self._get_metrics_authorized_roles = (
|
||||||
|
cfg.CONF.security.default_authorized_roles +
|
||||||
|
cfg.CONF.security.read_only_authorized_roles)
|
||||||
|
self._metrics_repo = simport.load(
|
||||||
|
cfg.CONF.repositories.metrics_driver)()
|
||||||
|
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.exception(ex)
|
||||||
|
raise falcon.HTTPInternalServerError('Service unavailable',
|
||||||
|
ex.message)
|
||||||
|
|
||||||
|
def on_get(self, req, res):
|
||||||
|
helpers.validate_authorization(req, self._get_metrics_authorized_roles)
|
||||||
|
tenant_id = helpers.get_tenant_id(req)
|
||||||
|
metric_name = helpers.get_query_param(req, 'metric_name')
|
||||||
|
offset = helpers.get_query_param(req, 'offset')
|
||||||
|
limit = helpers.get_limit(req)
|
||||||
|
result = self._dimension_names(tenant_id, req.uri, metric_name,
|
||||||
|
offset, limit)
|
||||||
|
res.body = helpers.dumpit_utf8(result)
|
||||||
|
res.status = falcon.HTTP_200
|
||||||
|
|
||||||
|
@resource.resource_try_catch_block
|
||||||
|
def _dimension_names(self, tenant_id, req_uri, metric_name, offset, limit):
|
||||||
|
|
||||||
|
result = self._metrics_repo.list_dimension_names(tenant_id,
|
||||||
|
self._region,
|
||||||
|
metric_name)
|
||||||
|
|
||||||
|
return helpers.paginate_with_no_id(result, req_uri, offset, limit)
|
||||||
|
|
|
@ -52,6 +52,13 @@ class MonascaClient(rest_client.RestClient):
|
||||||
resp, response_body = self.get(uri)
|
resp, response_body = self.get(uri)
|
||||||
return resp, json.loads(response_body)
|
return resp, json.loads(response_body)
|
||||||
|
|
||||||
|
def list_dimension_names(self, query_params=None):
|
||||||
|
uri = 'metrics/dimensions/names'
|
||||||
|
if query_params is not None:
|
||||||
|
uri = uri + query_params
|
||||||
|
resp, response_body = self.get(uri)
|
||||||
|
return resp, json.loads(response_body)
|
||||||
|
|
||||||
def list_dimension_values(self, query_params=None):
|
def list_dimension_values(self, query_params=None):
|
||||||
uri = 'metrics/dimensions/names/values'
|
uri = 'metrics/dimensions/names/values'
|
||||||
if query_params is not None:
|
if query_params is not None:
|
||||||
|
|
|
@ -93,5 +93,4 @@ class BaseMonascaTest(tempest.test.BaseTestCase):
|
||||||
query_params = urlparse.parse_qs(urlparse.urlparse(next_link).query)
|
query_params = urlparse.parse_qs(urlparse.urlparse(next_link).query)
|
||||||
if 'offset' not in query_params:
|
if 'offset' not in query_params:
|
||||||
self.fail("No offset in next link: {}".format(next_link))
|
self.fail("No offset in next link: {}".format(next_link))
|
||||||
|
|
||||||
return query_params['offset'][0]
|
return query_params['offset'][0]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
|
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
@ -14,14 +14,13 @@
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from oslo_utils import timeutils
|
|
||||||
|
|
||||||
from monasca_tempest_tests.tests.api import base
|
from monasca_tempest_tests.tests.api import base
|
||||||
from monasca_tempest_tests.tests.api import constants
|
from monasca_tempest_tests.tests.api import constants
|
||||||
from monasca_tempest_tests.tests.api import helpers
|
from monasca_tempest_tests.tests.api import helpers
|
||||||
from tempest.common.utils import data_utils
|
from tempest.common.utils import data_utils
|
||||||
from tempest import test
|
from tempest import test
|
||||||
from tempest.lib import exceptions
|
from tempest.lib import exceptions
|
||||||
|
from urllib import urlencode
|
||||||
|
|
||||||
|
|
||||||
class TestDimensions(base.BaseMonascaTest):
|
class TestDimensions(base.BaseMonascaTest):
|
||||||
|
@ -29,34 +28,56 @@ class TestDimensions(base.BaseMonascaTest):
|
||||||
@classmethod
|
@classmethod
|
||||||
def resource_setup(cls):
|
def resource_setup(cls):
|
||||||
super(TestDimensions, cls).resource_setup()
|
super(TestDimensions, cls).resource_setup()
|
||||||
name = data_utils.rand_name()
|
metric_name1 = data_utils.rand_name()
|
||||||
key = data_utils.rand_name()
|
name1 = "name_1"
|
||||||
|
name2 = "name_2"
|
||||||
value1 = "value_1"
|
value1 = "value_1"
|
||||||
value2 = "value_2"
|
value2 = "value_2"
|
||||||
cls._param = key + ':' + value1
|
|
||||||
cls._dimension_name = key
|
|
||||||
cls._dim_val_1 = value1
|
|
||||||
cls._dim_val_2 = value2
|
|
||||||
metric = helpers.create_metric(name=name,
|
|
||||||
dimensions={key: value1})
|
|
||||||
cls.monasca_client.create_metrics(metric)
|
|
||||||
metric = helpers.create_metric(name=name,
|
|
||||||
dimensions={key: value2})
|
|
||||||
cls.monasca_client.create_metrics(metric)
|
|
||||||
cls._test_metric = metric
|
|
||||||
|
|
||||||
start_time = str(timeutils.iso8601_from_timestamp(
|
timestamp = int(round(time.time() * 1000))
|
||||||
metric['timestamp'] / 1000.0))
|
time_iso = helpers.timestamp_to_iso(timestamp)
|
||||||
parms = '?name=' + str(cls._test_metric['name']) + \
|
|
||||||
'&start_time=' + start_time
|
|
||||||
|
|
||||||
|
metric1 = helpers.create_metric(name=metric_name1,
|
||||||
|
dimensions={name1: value1,
|
||||||
|
name2: value2
|
||||||
|
})
|
||||||
|
cls.monasca_client.create_metrics(metric1)
|
||||||
|
metric1 = helpers.create_metric(name=metric_name1,
|
||||||
|
dimensions={name1: value2})
|
||||||
|
cls.monasca_client.create_metrics(metric1)
|
||||||
|
|
||||||
|
metric_name2 = data_utils.rand_name()
|
||||||
|
name3 = "name_3"
|
||||||
|
value3 = "value_3"
|
||||||
|
metric2 = helpers.create_metric(name=metric_name2,
|
||||||
|
dimensions={name3: value3})
|
||||||
|
cls.monasca_client.create_metrics(metric2)
|
||||||
|
|
||||||
|
metric_name3 = data_utils.rand_name()
|
||||||
|
metric3 = helpers.create_metric(name=metric_name3,
|
||||||
|
dimensions={name1: value3})
|
||||||
|
|
||||||
|
cls.monasca_client.create_metrics(metric3)
|
||||||
|
|
||||||
|
cls._test_metric1 = metric1
|
||||||
|
cls._test_metric2 = metric2
|
||||||
|
cls._test_metric_names = {metric_name1, metric_name2, metric_name3}
|
||||||
|
cls._dim_names_metric1 = [name1, name2]
|
||||||
|
cls._dim_names_metric2 = [name3]
|
||||||
|
cls._dim_names = cls._dim_names_metric1 + cls._dim_names_metric2
|
||||||
|
cls._dim_values_for_metric1 = [value1, value2]
|
||||||
|
cls._dim_values = [value1, value2, value3]
|
||||||
|
|
||||||
|
param = '?start_time=' + time_iso
|
||||||
|
returned_name_set = set()
|
||||||
for i in xrange(constants.MAX_RETRIES):
|
for i in xrange(constants.MAX_RETRIES):
|
||||||
resp, response_body = cls.monasca_client.list_metrics(
|
resp, response_body = cls.monasca_client.list_metrics(
|
||||||
parms)
|
param)
|
||||||
elements = response_body['elements']
|
elements = response_body['elements']
|
||||||
for element in elements:
|
for element in elements:
|
||||||
if str(element['name']) == cls._test_metric['name']:
|
returned_name_set.add(str(element['name']))
|
||||||
return
|
if cls._test_metric_names.issubset(returned_name_set):
|
||||||
|
return
|
||||||
time.sleep(constants.RETRY_WAIT_SECS)
|
time.sleep(constants.RETRY_WAIT_SECS)
|
||||||
|
|
||||||
assert False, 'Unable to initialize metrics'
|
assert False, 'Unable to initialize metrics'
|
||||||
|
@ -67,46 +88,73 @@ class TestDimensions(base.BaseMonascaTest):
|
||||||
|
|
||||||
@test.attr(type='gate')
|
@test.attr(type='gate')
|
||||||
def test_list_dimension_values_without_metric_name(self):
|
def test_list_dimension_values_without_metric_name(self):
|
||||||
parms = '?dimension_name=' + self._dimension_name
|
param = '?dimension_name=' + self._dim_names[0]
|
||||||
resp, response_body = self.monasca_client.list_dimension_values(parms)
|
resp, response_body = self.monasca_client.list_dimension_values(param)
|
||||||
self.assertEqual(200, resp.status)
|
self.assertEqual(200, resp.status)
|
||||||
self.assertTrue(set(['links', 'elements']) == set(response_body))
|
self.assertTrue({'links', 'elements'} == set(response_body))
|
||||||
if not self._is_dimension_name_in_list(response_body):
|
response_values_length = len(response_body['elements'])
|
||||||
self.fail('Dimension name not found in response')
|
values = [str(response_body['elements'][i]['dimension_value'])
|
||||||
if self._is_metric_name_in_list(response_body):
|
for i in xrange(response_values_length)]
|
||||||
self.fail('Metric name was in response and should not be')
|
self.assertEqual(values, self._dim_values)
|
||||||
if not self._are_dim_vals_in_list(response_body):
|
|
||||||
self.fail('Dimension value not found in response')
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
@test.attr(type='gate')
|
||||||
def test_list_dimension_values_with_metric_name(self):
|
def test_list_dimension_values_with_metric_name(self):
|
||||||
parms = '?metric_name=' + self._test_metric['name']
|
parms = '?metric_name=' + self._test_metric1['name']
|
||||||
parms += '&dimension_name=' + self._dimension_name
|
parms += '&dimension_name=' + self._dim_names[0]
|
||||||
resp, response_body = self.monasca_client.list_dimension_values(parms)
|
resp, response_body = self.monasca_client.list_dimension_values(parms)
|
||||||
self.assertEqual(200, resp.status)
|
self.assertEqual(200, resp.status)
|
||||||
self.assertTrue(set(['links', 'elements']) == set(response_body))
|
self.assertTrue({'links', 'elements'} == set(response_body))
|
||||||
if not self._is_metric_name_in_list(response_body):
|
response_values_length = len(response_body['elements'])
|
||||||
self.fail('Metric name not found in response')
|
values = [str(response_body['elements'][i]['dimension_value'])
|
||||||
if not self._is_dimension_name_in_list(response_body):
|
for i in xrange(response_values_length)]
|
||||||
self.fail('Dimension name not found in response')
|
self.assertEqual(values, self._dim_values_for_metric1)
|
||||||
if not self._are_dim_vals_in_list(response_body):
|
|
||||||
self.fail('Dimension value not found in response')
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
@test.attr(type='gate')
|
||||||
def test_list_dimension_values_limit_and_offset(self):
|
def test_list_dimension_values_limit_and_offset(self):
|
||||||
parms = '?dimension_name=' + self._dimension_name
|
param = '?dimension_name=' + self._dim_names[0]
|
||||||
parms += '&limit=1'
|
resp, response_body = self.monasca_client.list_dimension_values(param)
|
||||||
resp, response_body = self.monasca_client.list_dimension_values(parms)
|
|
||||||
self.assertEqual(200, resp.status)
|
self.assertEqual(200, resp.status)
|
||||||
self.assertTrue(set(['links', 'elements']) == set(response_body))
|
elements = response_body['elements']
|
||||||
if not self._is_dimension_name_in_list(response_body):
|
num_dim_values = len(elements)
|
||||||
self.fail('Dimension name not found in response')
|
for limit in xrange(1, num_dim_values):
|
||||||
if not self._is_dim_val_in_list(response_body, self._dim_val_1):
|
start_index = 0
|
||||||
self.fail('First dimension value not found in response')
|
params = [('limit', limit)]
|
||||||
if not self._is_offset_in_links(response_body, self._dim_val_1):
|
offset = None
|
||||||
self.fail('Offset not found in response')
|
while True:
|
||||||
if not self._is_limit_in_links(response_body):
|
num_expected_elements = limit
|
||||||
self.fail('Limit not found in response')
|
if (num_expected_elements + start_index) > num_dim_values:
|
||||||
|
num_expected_elements = num_dim_values - start_index
|
||||||
|
|
||||||
|
these_params = list(params)
|
||||||
|
# If not the first call, use the offset returned by the last
|
||||||
|
# call
|
||||||
|
if offset:
|
||||||
|
these_params.extend([('offset', str(offset))])
|
||||||
|
query_parms = '?dimension_name=' + self._dim_names[0] + '&' + \
|
||||||
|
urlencode(these_params)
|
||||||
|
resp, response_body = \
|
||||||
|
self.monasca_client.list_dimension_values(query_parms)
|
||||||
|
self.assertEqual(200, resp.status)
|
||||||
|
if not response_body['elements']:
|
||||||
|
self.fail("No metrics returned")
|
||||||
|
response_values_length = len(response_body['elements'])
|
||||||
|
if response_values_length == 0:
|
||||||
|
self.fail("No dimension names returned")
|
||||||
|
new_elements = [str(response_body['elements'][i]
|
||||||
|
['dimension_value']) for i in
|
||||||
|
xrange(response_values_length)]
|
||||||
|
self.assertEqual(num_expected_elements, len(new_elements))
|
||||||
|
|
||||||
|
expected_elements = elements[start_index:start_index+limit]
|
||||||
|
expected_dimension_values = \
|
||||||
|
[expected_elements[i]['dimension_value'] for i in xrange(
|
||||||
|
len(expected_elements))]
|
||||||
|
self.assertEqual(expected_dimension_values, new_elements)
|
||||||
|
start_index += num_expected_elements
|
||||||
|
if start_index >= num_dim_values:
|
||||||
|
break
|
||||||
|
# Get the next set
|
||||||
|
offset = self._get_offset(response_body)
|
||||||
|
|
||||||
@test.attr(type='gate')
|
@test.attr(type='gate')
|
||||||
@test.attr(type=['negative'])
|
@test.attr(type=['negative'])
|
||||||
|
@ -114,46 +162,81 @@ class TestDimensions(base.BaseMonascaTest):
|
||||||
self.assertRaises(exceptions.UnprocessableEntity,
|
self.assertRaises(exceptions.UnprocessableEntity,
|
||||||
self.monasca_client.list_dimension_values)
|
self.monasca_client.list_dimension_values)
|
||||||
|
|
||||||
def _is_metric_name_in_list(self, response_body):
|
@test.attr(type='gate')
|
||||||
elements = response_body['elements'][0]
|
def test_list_dimension_names(self):
|
||||||
if 'metric_name' not in elements:
|
resp, response_body = self.monasca_client.list_dimension_names()
|
||||||
return False
|
self.assertEqual(200, resp.status)
|
||||||
if str(elements['metric_name']) == self._test_metric['name']:
|
self.assertTrue({'links', 'elements'} == set(response_body))
|
||||||
return True
|
response_names_length = len(response_body['elements'])
|
||||||
return False
|
names = [str(response_body['elements'][i]['dimension_name']) for i
|
||||||
|
in xrange(response_names_length)]
|
||||||
|
self.assertEqual(names, self._dim_names)
|
||||||
|
|
||||||
def _is_dimension_name_in_list(self, response_body):
|
@test.attr(type='gate')
|
||||||
elements = response_body['elements'][0]
|
def test_list_dimension_names_with_metric_name(self):
|
||||||
if str(elements['dimension_name']) == self._dimension_name:
|
self._test_list_dimension_names_with_metric_name(
|
||||||
return True
|
self._test_metric1['name'], self._dim_names_metric1)
|
||||||
return False
|
self._test_list_dimension_names_with_metric_name(
|
||||||
|
self._test_metric2['name'], self._dim_names_metric2)
|
||||||
|
|
||||||
def _are_dim_vals_in_list(self, response_body):
|
@test.attr(type='gate')
|
||||||
elements = response_body['elements'][0]
|
def test_list_dimension_names_limit_and_offset(self):
|
||||||
have_dim_1 = self._is_dim_val_in_list(response_body, self._dim_val_1)
|
resp, response_body = self.monasca_client.list_dimension_names()
|
||||||
have_dim_2 = self._is_dim_val_in_list(response_body, self._dim_val_2)
|
self.assertEqual(200, resp.status)
|
||||||
if have_dim_1 and have_dim_1:
|
elements = response_body['elements']
|
||||||
return True
|
num_dim_names = len(elements)
|
||||||
return False
|
for limit in xrange(1, num_dim_names):
|
||||||
|
start_index = 0
|
||||||
|
params = [('limit', limit)]
|
||||||
|
offset = None
|
||||||
|
while True:
|
||||||
|
num_expected_elements = limit
|
||||||
|
if (num_expected_elements + start_index) > num_dim_names:
|
||||||
|
num_expected_elements = num_dim_names - start_index
|
||||||
|
|
||||||
def _is_dim_val_in_list(self, response_body, dim_val):
|
these_params = list(params)
|
||||||
elements = response_body['elements'][0]
|
# If not the first call, use the offset returned by the last
|
||||||
if dim_val in elements['values']:
|
# call
|
||||||
return True
|
if offset:
|
||||||
return False
|
these_params.extend([('offset', str(offset))])
|
||||||
|
query_parms = '?' + urlencode(these_params)
|
||||||
|
resp, response_body = self.monasca_client.list_dimension_names(
|
||||||
|
query_parms)
|
||||||
|
self.assertEqual(200, resp.status)
|
||||||
|
if not response_body['elements']:
|
||||||
|
self.fail("No metrics returned")
|
||||||
|
response_names_length = len(response_body['elements'])
|
||||||
|
if response_names_length == 0:
|
||||||
|
self.fail("No dimension names returned")
|
||||||
|
new_elements = [str(response_body['elements'][i]
|
||||||
|
['dimension_name']) for i in
|
||||||
|
xrange(response_names_length)]
|
||||||
|
self.assertEqual(num_expected_elements, len(new_elements))
|
||||||
|
|
||||||
def _is_offset_in_links(self, response_body, dim_val):
|
expected_elements = elements[start_index:start_index+limit]
|
||||||
links = response_body['links']
|
expected_dimension_names = \
|
||||||
offset = "offset=" + dim_val
|
[expected_elements[i]['dimension_name'] for i in xrange(
|
||||||
for link in links:
|
len(expected_elements))]
|
||||||
if offset in link['href']:
|
self.assertEqual(expected_dimension_names, new_elements)
|
||||||
return True
|
start_index += num_expected_elements
|
||||||
return False
|
if start_index >= num_dim_names:
|
||||||
|
break
|
||||||
|
# Get the next set
|
||||||
|
offset = self._get_offset(response_body)
|
||||||
|
|
||||||
def _is_limit_in_links(self, response_body):
|
@test.attr(type='gate')
|
||||||
links = response_body['links']
|
@test.attr(type=['negative'])
|
||||||
limit = "limit=1"
|
def test_list_dimension_names_with_wrong_metric_name(self):
|
||||||
for link in links:
|
self._test_list_dimension_names_with_metric_name(
|
||||||
if limit in link['href']:
|
'wrong_metric_name', [])
|
||||||
return True
|
|
||||||
return False
|
def _test_list_dimension_names_with_metric_name(self, metric_name,
|
||||||
|
dimension_names):
|
||||||
|
param = '?metric_name=' + metric_name
|
||||||
|
resp, response_body = self.monasca_client.list_dimension_names(param)
|
||||||
|
self.assertEqual(200, resp.status)
|
||||||
|
self.assertTrue(set(['links', 'elements']) == set(response_body))
|
||||||
|
response_names_length = len(response_body['elements'])
|
||||||
|
names = [str(response_body['elements'][i]['dimension_name']) for i
|
||||||
|
in xrange(response_names_length)]
|
||||||
|
self.assertEqual(names, dimension_names)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#
|
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
|
@ -13,8 +13,6 @@
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import six.moves.urllib.parse as urlparse
|
|
||||||
|
|
||||||
from monasca_tempest_tests.tests.api import base
|
from monasca_tempest_tests.tests.api import base
|
||||||
from monasca_tempest_tests.tests.api import helpers
|
from monasca_tempest_tests.tests.api import helpers
|
||||||
from tempest import test
|
from tempest import test
|
||||||
|
@ -22,6 +20,7 @@ from tempest.lib import exceptions
|
||||||
|
|
||||||
from monasca_tempest_tests import clients
|
from monasca_tempest_tests import clients
|
||||||
|
|
||||||
|
|
||||||
class TestReadOnlyRole(base.BaseMonascaTest):
|
class TestReadOnlyRole(base.BaseMonascaTest):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -112,7 +111,19 @@ class TestReadOnlyRole(base.BaseMonascaTest):
|
||||||
#
|
#
|
||||||
url = '/v2.0/metrics/dimensions/names/values?dimension_name=foo'
|
url = '/v2.0/metrics/dimensions/names/values?dimension_name=foo'
|
||||||
self.assertEqual(200, resp.status)
|
self.assertEqual(200, resp.status)
|
||||||
self.assertEqual(0, len(response_body['elements'][0]['values']))
|
self.assertEqual(0, len(response_body['elements']))
|
||||||
|
self.assertTrue(response_body['links'][0]['href'].endswith(url))
|
||||||
|
|
||||||
|
@test.attr(type="gate")
|
||||||
|
def test_list_dimension_names_success(self):
|
||||||
|
resp, response_body = self.monasca_client.list_dimension_names()
|
||||||
|
#
|
||||||
|
# Validate the call succeeds with empty result (we didn't
|
||||||
|
# create any metrics/dimensions)
|
||||||
|
#
|
||||||
|
url = '/v2.0/metrics/dimensions/names'
|
||||||
|
self.assertEqual(200, resp.status)
|
||||||
|
self.assertEqual(0, len(response_body['elements']))
|
||||||
self.assertTrue(response_body['links'][0]['href'].endswith(url))
|
self.assertTrue(response_body['links'][0]['href'].endswith(url))
|
||||||
|
|
||||||
@test.attr(type="gate")
|
@test.attr(type="gate")
|
||||||
|
@ -129,7 +140,6 @@ class TestReadOnlyRole(base.BaseMonascaTest):
|
||||||
self.assertEqual(0, len(response_body['elements']))
|
self.assertEqual(0, len(response_body['elements']))
|
||||||
self.assertTrue('/v2.0/metrics/measurements' in response_body['links'][0]['href'])
|
self.assertTrue('/v2.0/metrics/measurements' in response_body['links'][0]['href'])
|
||||||
|
|
||||||
|
|
||||||
@test.attr(type="gate")
|
@test.attr(type="gate")
|
||||||
def test_list_statistics_success(self):
|
def test_list_statistics_success(self):
|
||||||
start_timestamp = int(time.time() * 1000)
|
start_timestamp = int(time.time() * 1000)
|
||||||
|
|
Loading…
Reference in New Issue