Add event paging
Change-Id: Ifaa82db925ca954fea19a91de43f07ff15f8ebd8
This commit is contained in:
parent
cd907a7622
commit
3d09835ea7
@ -23,43 +23,6 @@ class EventHandler(handler.Handler):
|
||||
def get_all(self, live_query=None):
|
||||
"""Return all logs."""
|
||||
influx_client = self.request.influxdb_client
|
||||
query = influxdb_query.build_influxdb_query(live_query, "EVENT")
|
||||
response = influx_client.query(query)
|
||||
|
||||
events = []
|
||||
|
||||
for item in response.items():
|
||||
tags = item[0][1]
|
||||
for point in response.get_points(tags=tags):
|
||||
point.update(tags)
|
||||
event_dict = self._event_dict_from_influx_item(point)
|
||||
events.append(event.Event(**event_dict))
|
||||
|
||||
return events
|
||||
|
||||
def _event_dict_from_influx_item(self, item):
|
||||
mappings = [
|
||||
'time',
|
||||
'event_type',
|
||||
'host_name',
|
||||
'service_description',
|
||||
'state',
|
||||
'state_type',
|
||||
'attempts',
|
||||
'downtime_type',
|
||||
'notification_type',
|
||||
'notification_method',
|
||||
'contact',
|
||||
'alert_type',
|
||||
'output',
|
||||
'acknowledgement'
|
||||
]
|
||||
|
||||
event_dict = {}
|
||||
|
||||
for field in mappings:
|
||||
value = item.get(field, None)
|
||||
if value is not None and value != "":
|
||||
event_dict[field] = value
|
||||
|
||||
return event_dict
|
||||
query = influxdb_query.build_influxdb_query(live_query, "EVENT",
|
||||
multiple_series=True)
|
||||
return influxdb_query.paging(influx_client.query(query), event.Event, live_query)
|
@ -12,6 +12,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import functools
|
||||
import json
|
||||
|
||||
|
||||
@ -20,8 +21,8 @@ def build_influxdb_query(live_query,
|
||||
group_by=[],
|
||||
order_by=[],
|
||||
additional_filters={},
|
||||
limit=None):
|
||||
|
||||
limit=None,
|
||||
multiple_series=False):
|
||||
query = ['SELECT * FROM', measurement]
|
||||
|
||||
filters = {}
|
||||
@ -33,8 +34,11 @@ def build_influxdb_query(live_query,
|
||||
if live_query.time_interval:
|
||||
time = live_query.time_interval
|
||||
if live_query.paging:
|
||||
limit = live_query.paging.size
|
||||
offset = limit * live_query.paging.page
|
||||
if multiple_series:
|
||||
limit = live_query.paging.size * (live_query.paging.page + 1)
|
||||
else:
|
||||
limit = live_query.paging.size
|
||||
offset = (live_query.paging.page + 1) * live_query.paging.size
|
||||
|
||||
filters.update(additional_filters)
|
||||
query += _build_where_clause(filters, time)
|
||||
@ -90,3 +94,66 @@ def _build_where_clause(filters, time=None):
|
||||
value))
|
||||
|
||||
return clause
|
||||
|
||||
|
||||
def paging(response, datamodel, live_query=None):
|
||||
"""Paging function
|
||||
|
||||
:param response: a python-influxdb resulset
|
||||
:param datamodel: an Surveil API datamodel class
|
||||
:param live_query: an influxdb_query
|
||||
:return: a dict of datamodel object. If the live query contain paging,
|
||||
the dict is sorted by datamodel time attribute and contain
|
||||
live_query.paging.size object for the live_query.paging.page page
|
||||
"""
|
||||
if live_query and live_query.paging:
|
||||
limit_paging = live_query.paging.size * (live_query.paging.page + 1)
|
||||
limit = live_query.paging.size + live_query.paging.page
|
||||
offset_paging = live_query.paging.page * live_query.paging.size
|
||||
|
||||
def sort_by_time(init, point_tag):
|
||||
event = {}
|
||||
event.update(point_tag[0])
|
||||
event.update(point_tag[1])
|
||||
init.append(datamodel(**event))
|
||||
init.sort(key=lambda event: event.time,
|
||||
reverse=True)
|
||||
return init[:limit_paging]
|
||||
|
||||
response = [(tag[1], _dict_from_influx_item(datamodel, point))
|
||||
for tag, points in response.items()
|
||||
for point in points]
|
||||
|
||||
event_list = functools.reduce(sort_by_time, response, [])
|
||||
|
||||
return event_list[offset_paging:limit+1]
|
||||
|
||||
else:
|
||||
events = []
|
||||
|
||||
for item in response.items():
|
||||
tags = item[0][1]
|
||||
for point in response.get_points(tags=tags):
|
||||
point.update(tags)
|
||||
event_dict = _dict_from_influx_item(datamodel, point)
|
||||
events.append(datamodel(**event_dict))
|
||||
|
||||
return events
|
||||
|
||||
|
||||
def _dict_from_influx_item(datamodel, item):
|
||||
"""Create a dict representing a python-influxdb item
|
||||
|
||||
:param item: an python influxdb item object
|
||||
:param datamodel: an Surveil API datamodel class
|
||||
:return: a dict (datamodel_attribute:item_value)
|
||||
|
||||
>>> _event_dict_from_influx_item(Event, {"time": 4})
|
||||
{'time': 4}
|
||||
>>> _event_dict_from_influx_item(Event, {"time": "null"})
|
||||
{}
|
||||
"""
|
||||
|
||||
fields = [attr.name for attr in getattr(datamodel, "_wsme_attributes")]
|
||||
return dict([(field, item.get(field, None)) for field in fields
|
||||
if item.get(field, None) is not None])
|
||||
|
@ -44,7 +44,7 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
],
|
||||
"values": [
|
||||
[
|
||||
"2015-06-04T18:55:12Z",
|
||||
"2015-06-04T18:55:19Z",
|
||||
1,
|
||||
"Connection refused",
|
||||
"CRITICAL",
|
||||
@ -52,7 +52,7 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
"SERVICE"
|
||||
],
|
||||
[
|
||||
'2015-06-04T18:55:12Z',
|
||||
'2015-06-04T18:55:18Z',
|
||||
2,
|
||||
'Connection refused',
|
||||
'CRITICAL',
|
||||
@ -60,7 +60,7 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
'SERVICE'
|
||||
],
|
||||
[
|
||||
'2015-06-04T18:55:12Z',
|
||||
'2015-06-04T18:55:17Z',
|
||||
3,
|
||||
'Connection refused',
|
||||
'CRITICAL',
|
||||
@ -86,7 +86,7 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
],
|
||||
'values': [
|
||||
[
|
||||
'2015-06-04T18:55:12Z',
|
||||
'2015-06-04T18:55:16Z',
|
||||
1,
|
||||
'Warning - Connection refused',
|
||||
'CRITICAL',
|
||||
@ -94,7 +94,7 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
'SERVICE'
|
||||
],
|
||||
[
|
||||
'2015-06-04T18:55:12Z',
|
||||
'2015-06-04T18:55:15Z',
|
||||
2,
|
||||
'Warning - Connection refused',
|
||||
'WARNING',
|
||||
@ -120,7 +120,7 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
],
|
||||
'values': [
|
||||
[
|
||||
'2015-06-04T18:55:12Z',
|
||||
'2015-06-04T18:55:14Z',
|
||||
'SERVICE',
|
||||
'admin',
|
||||
'CRITICAL',
|
||||
@ -128,7 +128,7 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
None
|
||||
],
|
||||
[
|
||||
'2015-06-04T18:55:12Z',
|
||||
'2015-06-04T18:55:13Z',
|
||||
'SERVICE',
|
||||
'admin',
|
||||
'CRITICAL',
|
||||
@ -174,7 +174,7 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
"host_name": "myServiceIsDown",
|
||||
"event_type": "ALERT",
|
||||
"service_description": "iAmADownService",
|
||||
"time": "2015-06-04T18:55:12Z",
|
||||
"time": "2015-06-04T18:55:19Z",
|
||||
"attempts": 1,
|
||||
"output": "Connection refused",
|
||||
"state": "CRITICAL",
|
||||
@ -185,7 +185,7 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
'host_name': 'myServiceIsDown',
|
||||
'event_type': 'ALERT',
|
||||
'service_description': 'iAmADownService',
|
||||
'time': '2015-06-04T18:55:12Z',
|
||||
'time': '2015-06-04T18:55:18Z',
|
||||
'attempts': 2,
|
||||
'output': 'Connection refused',
|
||||
'state': 'CRITICAL',
|
||||
@ -196,7 +196,7 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
'host_name': 'myServiceIsDown',
|
||||
'event_type': 'ALERT',
|
||||
'service_description': 'iAmADownService',
|
||||
'time': '2015-06-04T18:55:12Z',
|
||||
'time': '2015-06-04T18:55:17Z',
|
||||
'attempts': 3,
|
||||
'output': 'Connection refused',
|
||||
'state': 'CRITICAL',
|
||||
@ -207,7 +207,7 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
'host_name': 'savoirfairelinux',
|
||||
'event_type': 'ALERT',
|
||||
'service_description': 'CPU',
|
||||
'time': '2015-06-04T18:55:12Z',
|
||||
'time': '2015-06-04T18:55:16Z',
|
||||
'attempts': 1,
|
||||
'output': 'Warning - Connection refused',
|
||||
'state': 'CRITICAL',
|
||||
@ -218,7 +218,7 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
'host_name': 'savoirfairelinux',
|
||||
'event_type': 'ALERT',
|
||||
'service_description': 'CPU',
|
||||
'time': '2015-06-04T18:55:12Z',
|
||||
'time': '2015-06-04T18:55:15Z',
|
||||
'attempts': 2,
|
||||
'output': 'Warning - Connection refused',
|
||||
'state': 'WARNING',
|
||||
@ -229,7 +229,7 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
'host_name': 'savoirfairelinux',
|
||||
'event_type': 'NOTIFICATION',
|
||||
'service_description': 'CPU',
|
||||
'time': '2015-06-04T18:55:12Z',
|
||||
'time': '2015-06-04T18:55:14Z',
|
||||
'notification_type': 'SERVICE',
|
||||
'contact': 'admin',
|
||||
'state': 'CRITICAL',
|
||||
@ -239,7 +239,7 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
'host_name': 'savoirfairelinux',
|
||||
'event_type': 'NOTIFICATION',
|
||||
'service_description': 'CPU',
|
||||
'time': '2015-06-04T18:55:12Z',
|
||||
'time': '2015-06-04T18:55:13Z',
|
||||
'notification_type': 'SERVICE',
|
||||
'contact': 'admin',
|
||||
'state': 'CRITICAL',
|
||||
@ -344,3 +344,45 @@ class TestEvents(functionalTest.FunctionalTest):
|
||||
'notification_method': 'notify-service-by-email'
|
||||
}]
|
||||
)
|
||||
|
||||
def test_paging(self):
|
||||
with requests_mock.Mocker() as m:
|
||||
m.register_uri(requests_mock.GET,
|
||||
'http://influxdb:8086/query',
|
||||
text=self.influxdb_response)
|
||||
|
||||
query = {'paging': {'page': 1, 'size': 2}}
|
||||
|
||||
response = self.post_json('/v2/status/events', params=query)
|
||||
|
||||
self.assertEqual(
|
||||
m.last_request.qs['q'],
|
||||
["select * from event limit 4"]
|
||||
)
|
||||
|
||||
self.assert_count_equal_backport(
|
||||
json.loads(response.body.decode()), [
|
||||
|
||||
{
|
||||
'host_name': 'myServiceIsDown',
|
||||
'event_type': 'ALERT',
|
||||
'service_description': 'iAmADownService',
|
||||
'time': '2015-06-04T18:55:17Z',
|
||||
'attempts': 3,
|
||||
'output': 'Connection refused',
|
||||
'state': 'CRITICAL',
|
||||
'state_type': 'SOFT',
|
||||
'alert_type': 'SERVICE'
|
||||
},
|
||||
{
|
||||
'host_name': 'savoirfairelinux',
|
||||
'event_type': 'ALERT',
|
||||
'service_description': 'CPU',
|
||||
'time': '2015-06-04T18:55:16Z',
|
||||
'attempts': 1,
|
||||
'output': 'Warning - Connection refused',
|
||||
'state': 'CRITICAL',
|
||||
'state_type': 'HARD',
|
||||
'alert_type': 'SERVICE'
|
||||
}]
|
||||
)
|
@ -4,7 +4,7 @@
|
||||
# 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
|
||||
# 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
|
||||
|
@ -230,7 +230,7 @@ class TestHostMetric(functionalTest.FunctionalTest):
|
||||
"and host_name='srv-monitoring-01' "
|
||||
"and service_description='load' "
|
||||
"order by time desc "
|
||||
"limit 10 offset 30"
|
||||
"limit 10 offset 40"
|
||||
]
|
||||
)
|
||||
self.assert_count_equal_backport(
|
||||
|
Loading…
x
Reference in New Issue
Block a user