diff --git a/surveil/api/controllers/v2/status/hosts.py b/surveil/api/controllers/v2/status/hosts.py index 13a50e7..6f6e031 100644 --- a/surveil/api/controllers/v2/status/hosts.py +++ b/surveil/api/controllers/v2/status/hosts.py @@ -69,6 +69,17 @@ class HostServicesController(rest.RestController): class HostServiceMetricsController(rest.RestController): + @util.policy_enforce(['authenticated']) + @wsme_pecan.wsexpose([live_metric.LiveMetric]) + def get(self): + """Returns all metrics name for a host with a service.""" + handler = live_metric_handler.MetricHandler(pecan.request) + metrics_name = handler.get_metric( + pecan.request.context['host_name'], + pecan.request.context['service_name'] + ) + return metrics_name + @pecan.expose() def _lookup(self, metric_name, *remainder): return HostServiceMetricController(metric_name), remainder @@ -76,6 +87,14 @@ class HostServiceMetricsController(rest.RestController): class HostMetricsController(rest.RestController): + @util.policy_enforce(['authenticated']) + @wsme_pecan.wsexpose([live_metric.LiveMetric]) + def get(self): + """Returns all metrics name for a host.""" + handler = live_metric_handler.MetricHandler(pecan.request) + metrics_name = handler.get_metric(pecan.request.context['host_name']) + return metrics_name + @pecan.expose() def _lookup(self, metric_name, *remainder): return HostMetricController(metric_name), remainder diff --git a/surveil/api/handlers/status/metrics/live_metric_handler.py b/surveil/api/handlers/status/metrics/live_metric_handler.py index dfab039..e396a0a 100644 --- a/surveil/api/handlers/status/metrics/live_metric_handler.py +++ b/surveil/api/handlers/status/metrics/live_metric_handler.py @@ -21,10 +21,37 @@ from surveil.api.handlers.status.metrics import influxdb_time_query class MetricHandler(handler.Handler): """Fulfills a request on the metrics.""" - def get(self, metric_name, host_name, service_description=None): - """Return a metric.""" + def get_metric(self, host_name, service_description=None): + """Return all metrics name for a given host.""" + cli = self.request.influxdb_client + if service_description is None: + query = "SHOW measurements WHERE host_name='%s'" % host_name + else: + query = ("SHOW measurements WHERE host_name='%s' " + "AND service_description='%s'" + % (host_name, service_description)) + + response = cli.query(query) + + metric_name_dicts = [] + + for item in response[None]: + metric_name_dict = self._metrics_name_from_influx_item(item) + metric_name_dicts.append(metric_name_dict) + + metrics = [] + for metric_dict in metric_name_dicts: + metric = live_metric.LiveMetric(**metric_dict) + metrics.append(metric) + + return metrics + + def get(self, metric_name, host_name, service_description=None): + """Return a metric.""" + + cli = self.request.influxdb_client if service_description is None: query = ("SELECT * FROM metric_%s " "WHERE host_name= '%s' " @@ -73,7 +100,9 @@ class MetricHandler(handler.Handler): return metrics def _metric_dict_from_influx_item(self, item, metric_name): + metric_dict = {"metric_name": str(metric_name)} + mappings = [ ('min', str), ('max', str), @@ -88,4 +117,15 @@ class MetricHandler(handler.Handler): if value is not None: metric_dict[field[0]] = field[1](value) - return metric_dict \ No newline at end of file + return metric_dict + + def _metrics_name_from_influx_item(self, item): + + metric_name = {} + mappings = [('metric_name', 'name', str), ] + for field in mappings: + value = item.get(field[1], None) + if value is not None: + metric_name[field[0]] = field[2](value) + + return metric_name \ No newline at end of file diff --git a/surveil/tests/api/controllers/v2/status/test_hosts_metric.py b/surveil/tests/api/controllers/v2/status/test_hosts_metric.py index 4d9c6b4..abb48eb 100644 --- a/surveil/tests/api/controllers/v2/status/test_hosts_metric.py +++ b/surveil/tests/api/controllers/v2/status/test_hosts_metric.py @@ -91,7 +91,7 @@ class TestHostMetric(functionalTest.FunctionalTest): response = self.get( "/v2/status/hosts/srv-monitoring-01/metrics/load1" - ) + ) expected = { "metric_name": "load1", @@ -115,26 +115,27 @@ class TestHostMetric(functionalTest.FunctionalTest): def test_time_hosts(self): self.influxdb_response = json.dumps({ "results": [ - {"series": [ - {"name": "metric_load1", - "tags": {"host_name": "srv-monitoring-01", - "service_description": "load"}, - "columns": ["time", - "critical", - "min", - "value", - "warning", - ], - "values": [["2015-04-19T01:09:24Z", - "30", - "0", - "0.6", - "15"], - ["2015-04-19T01:09:25Z", - "40", - "4", - "10", - "10"]]}]}] + { + "series": [ + {"name": "metric_load1", + "tags": {"host_name": "srv-monitoring-01", + "service_description": "load"}, + "columns": ["time", + "critical", + "min", + "value", + "warning", + ], + "values": [["2015-04-19T01:09:24Z", + "30", + "0", + "0.6", + "15"], + ["2015-04-19T01:09:25Z", + "40", + "4", + "10", + "10"]]}]}] }) @@ -176,3 +177,85 @@ class TestHostMetric(functionalTest.FunctionalTest): "order by time desc" ] ) + + def test_metric_names(self): + self.influxdb_response = json.dumps({ + "results": [ + { + "series": [ + { + "name": "measurements", + "columns": ["name"], + "values": [ + ["ALERT"], + ["HOST_STATE"], + ["metric_pl"], + ["metric_rta"], + ["metric_rtmax"], + ["metric_rtmin"] + ] + } + ] + } + ] + }) + with requests_mock.Mocker() as m: + m.register_uri(requests_mock.GET, + "http://influxdb:8086/query", + text=self.influxdb_response) + + response = self.get( + "/v2/status/hosts/localhost/metrics" + ) + + expected = [{"metric_name": "ALERT"}, + {"metric_name": "HOST_STATE"}, + {"metric_name": "metric_pl"}, + {"metric_name": "metric_rta"}, + {"metric_name": "metric_rtmax"}, + {"metric_name": "metric_rtmin"}, + ] + + self.assert_count_equal_backport( + json.loads(response.body.decode()), + expected) + self.assertEqual( + m.last_request.qs['q'], + ["show measurements where host_name='localhost'"] + ) + + def test_metric_names_services(self): + self.influxdb_response = json.dumps({ + "results": [ + { + "series": [ + { + "name": "measurements", + "columns": ["name"], + "values": [ + ["SERVICE_STATE"] + ] + } + ] + } + ] + }) + with requests_mock.Mocker() as m: + m.register_uri(requests_mock.GET, + "http://influxdb:8086/query", + text=self.influxdb_response) + + response = self.get( + "/v2/status/hosts/localhost/services/load/metrics" + ) + + expected = [{"metric_name": "SERVICE_STATE"}, ] + + self.assert_count_equal_backport( + json.loads(response.body.decode()), + expected) + self.assertEqual( + m.last_request.qs['q'], + ["show measurements where host_name='localhost' " + "and service_description='load'"] + ) \ No newline at end of file