Merge "Add metrics controller + change status datamodel for Influxdb 0.9"
This commit is contained in:
commit
b9b3bf1dd9
@ -23,9 +23,21 @@ Hosts
|
|||||||
.. rest-controller:: surveil.api.controllers.v2.status.hosts:HostCheckResultsSubController
|
.. rest-controller:: surveil.api.controllers.v2.status.hosts:HostCheckResultsSubController
|
||||||
:webprefix: /v2/status/hosts/(host_name)/results
|
:webprefix: /v2/status/hosts/(host_name)/results
|
||||||
|
|
||||||
|
.. rest-controller:: surveil.api.controllers.v2.status.hosts:HostMetricsController
|
||||||
|
:webprefix: /v2/status/hosts/(host_name)/metrics
|
||||||
|
|
||||||
|
.. rest-controller:: surveil.api.controllers.v2.status.hosts:HostMetricController
|
||||||
|
:webprefix: /v2/status/hosts/(host_name)/metrics
|
||||||
|
|
||||||
.. rest-controller:: surveil.api.controllers.v2.status.hosts:ServiceCheckResultsSubController
|
.. rest-controller:: surveil.api.controllers.v2.status.hosts:ServiceCheckResultsSubController
|
||||||
:webprefix: /v2/status/hosts/(host_name)/services/(service_description)/results
|
:webprefix: /v2/status/hosts/(host_name)/services/(service_description)/results
|
||||||
|
|
||||||
|
.. rest-controller:: surveil.api.controllers.v2.status.hosts:HostServiceMetricsController
|
||||||
|
:webprefix: /v2/status/hosts/(host_name)/services/(service_description)/metrics
|
||||||
|
|
||||||
|
.. rest-controller:: surveil.api.controllers.v2.status.hosts:HostServiceMetricController
|
||||||
|
:webprefix: /v2/status/hosts/(host_name)/services/(service_description)/metrics
|
||||||
|
|
||||||
.. rest-controller:: surveil.api.controllers.v2.logs:LogsController
|
.. rest-controller:: surveil.api.controllers.v2.logs:LogsController
|
||||||
:webprefix: /v2/status/hosts/(host_name)/events
|
:webprefix: /v2/status/hosts/(host_name)/events
|
||||||
|
|
||||||
@ -59,3 +71,9 @@ types documentation
|
|||||||
|
|
||||||
.. autotype:: surveil.api.datamodel.status.live_query.LiveQuery
|
.. autotype:: surveil.api.datamodel.status.live_query.LiveQuery
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. autotype:: surveil.api.datamodel.status.metrics.live_metric.LiveMetric
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autotype:: surveil.api.datamodel.status.metrics.time_delta.TimeDelta
|
||||||
|
:members:
|
@ -21,4 +21,4 @@ from surveil.api.controllers.v2.status import services as v2_services
|
|||||||
class StatusController(rest.RestController):
|
class StatusController(rest.RestController):
|
||||||
# events = EventsController()
|
# events = EventsController()
|
||||||
hosts = v2_hosts.HostsController()
|
hosts = v2_hosts.HostsController()
|
||||||
services = v2_services.ServicesController()
|
services = v2_services.ServicesController()
|
||||||
|
@ -76,9 +76,9 @@ class HostServiceMetricsController(rest.RestController):
|
|||||||
def get(self):
|
def get(self):
|
||||||
"""Returns all metrics name for a host with a service."""
|
"""Returns all metrics name for a host with a service."""
|
||||||
handler = live_metric_handler.MetricHandler(pecan.request)
|
handler = live_metric_handler.MetricHandler(pecan.request)
|
||||||
metrics_name = handler.get_metric(
|
metrics_name = handler.get(
|
||||||
pecan.request.context['host_name'],
|
pecan.request.context['host_name'],
|
||||||
pecan.request.context['service_name']
|
service_description=pecan.request.context['service_name']
|
||||||
)
|
)
|
||||||
return metrics_name
|
return metrics_name
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ class HostMetricsController(rest.RestController):
|
|||||||
def get(self):
|
def get(self):
|
||||||
"""Returns all metrics name for a host."""
|
"""Returns all metrics name for a host."""
|
||||||
handler = live_metric_handler.MetricHandler(pecan.request)
|
handler = live_metric_handler.MetricHandler(pecan.request)
|
||||||
metrics_name = handler.get_metric(pecan.request.context['host_name'])
|
metrics_name = handler.get(pecan.request.context['host_name'])
|
||||||
return metrics_name
|
return metrics_name
|
||||||
|
|
||||||
@pecan.expose()
|
@pecan.expose()
|
||||||
@ -178,8 +178,8 @@ class HostServiceMetricController(rest.RestController):
|
|||||||
"""
|
"""
|
||||||
handler = live_metric_handler.MetricHandler(pecan.request)
|
handler = live_metric_handler.MetricHandler(pecan.request)
|
||||||
metric = handler.get(
|
metric = handler.get(
|
||||||
self.metric_name,
|
|
||||||
pecan.request.context['host_name'],
|
pecan.request.context['host_name'],
|
||||||
|
self.metric_name,
|
||||||
pecan.request.context['service_name']
|
pecan.request.context['service_name']
|
||||||
)
|
)
|
||||||
return metric
|
return metric
|
||||||
@ -187,7 +187,10 @@ class HostServiceMetricController(rest.RestController):
|
|||||||
@util.policy_enforce(['authenticated'])
|
@util.policy_enforce(['authenticated'])
|
||||||
@wsme_pecan.wsexpose([live_metric.LiveMetric], body=time_delta.TimeDelta)
|
@wsme_pecan.wsexpose([live_metric.LiveMetric], body=time_delta.TimeDelta)
|
||||||
def post(self, time):
|
def post(self, time):
|
||||||
"""Given a LiveQuery, returns all matching s."""
|
"""Returns all matching metrics.
|
||||||
|
|
||||||
|
:param time: a time delta within the request body.
|
||||||
|
"""
|
||||||
handler = live_metric_handler.MetricHandler(pecan.request)
|
handler = live_metric_handler.MetricHandler(pecan.request)
|
||||||
metrics = handler.get_all(time_delta=time,
|
metrics = handler.get_all(time_delta=time,
|
||||||
metric_name=self.metric_name,
|
metric_name=self.metric_name,
|
||||||
@ -212,15 +215,18 @@ class HostMetricController(rest.RestController):
|
|||||||
"""
|
"""
|
||||||
handler = live_metric_handler.MetricHandler(pecan.request)
|
handler = live_metric_handler.MetricHandler(pecan.request)
|
||||||
metric = handler.get(
|
metric = handler.get(
|
||||||
self.metric_name,
|
pecan.request.context['host_name'],
|
||||||
pecan.request.context['host_name']
|
self.metric_name
|
||||||
)
|
)
|
||||||
return metric
|
return metric
|
||||||
|
|
||||||
@util.policy_enforce(['authenticated'])
|
@util.policy_enforce(['authenticated'])
|
||||||
@wsme_pecan.wsexpose([live_metric.LiveMetric], body=time_delta.TimeDelta)
|
@wsme_pecan.wsexpose([live_metric.LiveMetric], body=time_delta.TimeDelta)
|
||||||
def post(self, time):
|
def post(self, time):
|
||||||
"""Given a LiveQuery, returns all matching s."""
|
"""Given a time delta, returns all matching metrics.
|
||||||
|
|
||||||
|
:param time: a time delta within the request body.
|
||||||
|
"""
|
||||||
handler = live_metric_handler.MetricHandler(pecan.request)
|
handler = live_metric_handler.MetricHandler(pecan.request)
|
||||||
metrics = handler.get_all(time_delta=time,
|
metrics = handler.get_all(time_delta=time,
|
||||||
metric_name=self.metric_name,
|
metric_name=self.metric_name,
|
||||||
|
@ -31,4 +31,4 @@ class V2Controller(object):
|
|||||||
surveil = v2_admin.AdminController()
|
surveil = v2_admin.AdminController()
|
||||||
auth = v2_auth.AuthController()
|
auth = v2_auth.AuthController()
|
||||||
logs = v2_logs.LogsController()
|
logs = v2_logs.LogsController()
|
||||||
bansho = v2_bansho.BanshoController()
|
bansho = v2_bansho.BanshoController()
|
@ -37,7 +37,7 @@ class LiveService(types.Base):
|
|||||||
last_check = wsme.wsattr(int, mandatory=False)
|
last_check = wsme.wsattr(int, mandatory=False)
|
||||||
"""The last time the service was checked"""
|
"""The last time the service was checked"""
|
||||||
|
|
||||||
last_state_change = wsme.wsattr(int, mandatory=False)
|
last_state_change = wsme.wsattr(float, mandatory=False)
|
||||||
"""The last time the state has changed"""
|
"""The last time the state has changed"""
|
||||||
|
|
||||||
plugin_output = wsme.wsattr(wtypes.text, mandatory=False)
|
plugin_output = wsme.wsattr(wtypes.text, mandatory=False)
|
||||||
@ -54,7 +54,7 @@ class LiveService(types.Base):
|
|||||||
description='Serves Stuff',
|
description='Serves Stuff',
|
||||||
state='OK',
|
state='OK',
|
||||||
last_check=1429220785,
|
last_check=1429220785,
|
||||||
last_state_change=1429220785,
|
last_state_change=1429220785.481679,
|
||||||
plugin_output='HTTP OK - GOT NICE RESPONSE',
|
plugin_output='HTTP OK - GOT NICE RESPONSE',
|
||||||
acknowledged=True,
|
acknowledged=True,
|
||||||
long_output='Serves /var/www/\nServes /home/webserver/www/'
|
long_output='Serves /var/www/\nServes /home/webserver/www/'
|
||||||
|
@ -102,7 +102,7 @@ def _service_dict_from_mongo_item(mongo_item):
|
|||||||
|
|
||||||
mappings = [
|
mappings = [
|
||||||
('last_chk', 'last_check', int),
|
('last_chk', 'last_check', int),
|
||||||
('last_state_change', 'last_state_change', int),
|
('last_state_change', 'last_state_change', float),
|
||||||
('output', 'plugin_output', str),
|
('output', 'plugin_output', str),
|
||||||
('problem_has_been_acknowledged', 'acknowledged', bool),
|
('problem_has_been_acknowledged', 'acknowledged', bool),
|
||||||
]
|
]
|
||||||
|
@ -21,58 +21,60 @@ from surveil.api.handlers.status.metrics import influxdb_time_query
|
|||||||
class MetricHandler(handler.Handler):
|
class MetricHandler(handler.Handler):
|
||||||
"""Fulfills a request on the metrics."""
|
"""Fulfills a request on the metrics."""
|
||||||
|
|
||||||
def get_metric(self, host_name, service_description=None):
|
def get(self, host_name, metric_name=None, service_description=None):
|
||||||
"""Return all metrics name for a given host."""
|
"""Return metrics name if param metric_name is null,
|
||||||
|
|
||||||
|
else , return the last metric.
|
||||||
|
"""
|
||||||
|
metrics = []
|
||||||
cli = self.request.influxdb_client
|
cli = self.request.influxdb_client
|
||||||
|
if metric_name is None:
|
||||||
if service_description is None:
|
if service_description is None:
|
||||||
query = "SHOW measurements WHERE host_name='%s'" % host_name
|
query = ("SHOW measurements WHERE host_name='%s' "
|
||||||
|
"AND service_description=''"
|
||||||
|
% host_name)
|
||||||
|
else:
|
||||||
|
query = ("SHOW measurements WHERE host_name='%s' "
|
||||||
|
"AND service_description='%s'"
|
||||||
|
% (host_name, service_description))
|
||||||
else:
|
else:
|
||||||
query = ("SHOW measurements WHERE host_name='%s' "
|
if service_description is None:
|
||||||
"AND service_description='%s'"
|
query = ("SELECT * FROM metric_%s "
|
||||||
% (host_name, service_description))
|
"WHERE host_name= '%s' "
|
||||||
|
"GROUP BY service_description "
|
||||||
|
"ORDER BY time DESC "
|
||||||
|
"LIMIT 1"
|
||||||
|
% (metric_name, host_name))
|
||||||
|
else:
|
||||||
|
query = ("SELECT * FROM metric_%s "
|
||||||
|
"WHERE host_name= '%s' "
|
||||||
|
"AND service_description= '%s'"
|
||||||
|
"ORDER BY time DESC "
|
||||||
|
"LIMIT 1"
|
||||||
|
% (metric_name, host_name, service_description))
|
||||||
|
|
||||||
response = cli.query(query)
|
response = cli.query(query)
|
||||||
|
|
||||||
metric_name_dicts = []
|
if metric_name is None:
|
||||||
|
metric_dicts = []
|
||||||
|
|
||||||
for item in response[None]:
|
for item in response[None]:
|
||||||
metric_name_dict = self._metrics_name_from_influx_item(item)
|
metric_dict = self._metric_dict_from_influx_item(item)
|
||||||
metric_name_dicts.append(metric_name_dict)
|
if metric_dict is not None:
|
||||||
|
metric_dicts.append(metric_dict)
|
||||||
|
|
||||||
metrics = []
|
for metric_dict in metric_dicts:
|
||||||
for metric_dict in metric_name_dicts:
|
metric = live_metric.LiveMetric(**metric_dict)
|
||||||
metric = live_metric.LiveMetric(**metric_dict)
|
metrics.append(metric)
|
||||||
metrics.append(metric)
|
|
||||||
|
else:
|
||||||
|
metrics = live_metric.LiveMetric(**self.
|
||||||
|
_metric_dict_from_influx_item(
|
||||||
|
next(response.items()[0][1]),
|
||||||
|
metric_name))
|
||||||
|
|
||||||
return metrics
|
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' "
|
|
||||||
"GROUP BY service_description "
|
|
||||||
"ORDER BY time DESC "
|
|
||||||
"LIMIT 1" % (metric_name, host_name))
|
|
||||||
else:
|
|
||||||
query = ("SELECT * FROM metric_%s "
|
|
||||||
"WHERE host_name= '%s' "
|
|
||||||
"AND service_description= '%s'"
|
|
||||||
"ORDER BY time DESC "
|
|
||||||
"LIMIT 1" % (metric_name, host_name, service_description))
|
|
||||||
|
|
||||||
response = cli.query(query)
|
|
||||||
metric = live_metric.LiveMetric(
|
|
||||||
**self._metric_dict_from_influx_item(next(response.items()[0][1]),
|
|
||||||
metric_name)
|
|
||||||
)
|
|
||||||
|
|
||||||
return metric
|
|
||||||
|
|
||||||
def get_all(self, metric_name, time_delta, host_name=None,
|
def get_all(self, metric_name, time_delta, host_name=None,
|
||||||
service_description=None):
|
service_description=None):
|
||||||
"""Return all metrics."""
|
"""Return all metrics."""
|
||||||
@ -99,33 +101,30 @@ class MetricHandler(handler.Handler):
|
|||||||
|
|
||||||
return metrics
|
return metrics
|
||||||
|
|
||||||
def _metric_dict_from_influx_item(self, item, metric_name):
|
def _metric_dict_from_influx_item(self, item, metric_name=None):
|
||||||
|
|
||||||
metric_dict = {"metric_name": str(metric_name)}
|
if metric_name is None:
|
||||||
|
metric_dict = None
|
||||||
mappings = [
|
mappings = [('name', 'metric_name', str), ]
|
||||||
('min', str),
|
else:
|
||||||
('max', str),
|
metric_dict = {"metric_name": str(metric_name)}
|
||||||
('critical', str),
|
mappings = [
|
||||||
('warning', str),
|
('min', str),
|
||||||
('value', str),
|
('max', str),
|
||||||
('unit', str),
|
('critical', str),
|
||||||
]
|
('warning', str),
|
||||||
|
('value', str),
|
||||||
|
('unit', str),
|
||||||
|
]
|
||||||
|
|
||||||
for field in mappings:
|
for field in mappings:
|
||||||
value = item.get(field[0], None)
|
value = item.get(field[0], None)
|
||||||
if value is not None:
|
if value is not None:
|
||||||
metric_dict[field[0]] = field[1](value)
|
if field[0] == 'name':
|
||||||
|
if value.startswith('metric_'):
|
||||||
|
metric_dict = {}
|
||||||
|
metric_dict[field[1]] = field[2](value[7:])
|
||||||
|
else:
|
||||||
|
metric_dict[field[0]] = field[1](value)
|
||||||
|
|
||||||
return metric_dict
|
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
|
|
@ -187,12 +187,8 @@ class TestHostMetric(functionalTest.FunctionalTest):
|
|||||||
"name": "measurements",
|
"name": "measurements",
|
||||||
"columns": ["name"],
|
"columns": ["name"],
|
||||||
"values": [
|
"values": [
|
||||||
["ALERT"],
|
["metric_rtmin"],
|
||||||
["HOST_STATE"],
|
["ALERT"]
|
||||||
["metric_pl"],
|
|
||||||
["metric_rta"],
|
|
||||||
["metric_rtmax"],
|
|
||||||
["metric_rtmin"]
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -205,23 +201,18 @@ class TestHostMetric(functionalTest.FunctionalTest):
|
|||||||
text=self.influxdb_response)
|
text=self.influxdb_response)
|
||||||
|
|
||||||
response = self.get(
|
response = self.get(
|
||||||
"/v2/status/hosts/localhost/metrics"
|
"/v2/status/hosts/ws-arbiter/metrics"
|
||||||
)
|
)
|
||||||
|
|
||||||
expected = [{"metric_name": "ALERT"},
|
expected = [{"metric_name": "rtmin"}, ]
|
||||||
{"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(
|
self.assert_count_equal_backport(
|
||||||
json.loads(response.body.decode()),
|
json.loads(response.body.decode()),
|
||||||
expected)
|
expected)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
m.last_request.qs['q'],
|
m.last_request.qs['q'],
|
||||||
["show measurements where host_name='localhost'"]
|
["show measurements where host_name='ws-arbiter' "
|
||||||
|
"and service_description=''"]
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_metric_names_services(self):
|
def test_metric_names_services(self):
|
||||||
@ -233,7 +224,8 @@ class TestHostMetric(functionalTest.FunctionalTest):
|
|||||||
"name": "measurements",
|
"name": "measurements",
|
||||||
"columns": ["name"],
|
"columns": ["name"],
|
||||||
"values": [
|
"values": [
|
||||||
["SERVICE_STATE"]
|
["metric_rtmin"],
|
||||||
|
["ALERT"]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -249,7 +241,7 @@ class TestHostMetric(functionalTest.FunctionalTest):
|
|||||||
"/v2/status/hosts/localhost/services/load/metrics"
|
"/v2/status/hosts/localhost/services/load/metrics"
|
||||||
)
|
)
|
||||||
|
|
||||||
expected = [{"metric_name": "SERVICE_STATE"}, ]
|
expected = [{"metric_name": "rtmin"}, ]
|
||||||
|
|
||||||
self.assert_count_equal_backport(
|
self.assert_count_equal_backport(
|
||||||
json.loads(response.body.decode()),
|
json.loads(response.body.decode()),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user