Skip to content

Commit

Permalink
Alignak statistics - first version
Browse files Browse the repository at this point in the history
  • Loading branch information
mohierf committed Dec 18, 2018
1 parent a594e7c commit fe47d22
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 14 deletions.
153 changes: 140 additions & 13 deletions module/plugins/stats/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
from collections import Counter, OrderedDict
from itertools import groupby

from shinken.log import logger

from copy import deepcopy
from logevent import LogEvent

# Will be populated by the UI with it's own value
app = None

Expand Down Expand Up @@ -74,6 +79,79 @@ def _graph(logs):
return graph


def get_alignak_stats():
user = app.bottle.request.environ['USER']
_ = user.is_administrator() or app.redirect403()

logger.info("Get Alignak stats")

days = int(app.request.GET.get('days', 30))

range_end = int(app.request.GET.get('range_end', time.time()))
range_start = int(app.request.GET.get('range_start', range_end - (days * 86400)))

# Restrictive filter on contact name
filters = ['notification']

logs = []
for log in app.alignak_events:
# Try to get a monitoring event
try:
logger.debug("Log: %s", log)
event = LogEvent(log['message'])
logger.debug("-> event: %s", event)
if not event.valid:
logger.warning("No monitoring event detected from: %s", log['message'])
continue

# -------------------------------------------
data = deepcopy(log)

if event.event_type == 'ALERT':
data.update({
"host_name": event.data['hostname'],
"service_name": event.data['service_desc'] or 'n/a',
"state": event.data['state'],
"state_type": event.data['state_type'],
"type": "alert",
})

if event.event_type == 'NOTIFICATION':
data.update({
"host_name": event.data['hostname'],
"service_name": event.data['service_desc'] or 'n/a',
"type": "notification",
})

if filters and data.get('type', 'unknown') not in filters:
continue

logs.append(data)
logger.info(data)
except ValueError:
logger.warning("Unable to decode a monitoring event from: %s", log['message'])
continue

hosts = Counter()
services = Counter()
hostsservices = Counter()
new_logs = []
for l in logs:
hosts[l['host_name']] += 1
if 'service_description' in l:
services[l['service_description']] += 1
hostsservices[l['host_name'] + '/' + l['service_description']] += 1
new_logs.append(l)

return {
'hosts': hosts,
'services': services,
'hostsservices': hostsservices,
'days': days,
'graph': _graph(new_logs) if new_logs else None
}


def get_global_stats():
user = app.bottle.request.environ['USER']
_ = user.is_administrator() or app.redirect403()
Expand All @@ -83,25 +161,44 @@ def get_global_stats():
range_end = int(app.request.GET.get('range_end', time.time()))
range_start = int(app.request.GET.get('range_start', range_end - (days * 86400)))

logs = list(app.logs_module.get_ui_logs(
range_start=range_start, range_end=range_end,
filters={'type': 'SERVICE NOTIFICATION',
'command_name': {'$regex': 'notify-service-by-slack'}},
limit=None))
filters = {'type': 'SERVICE NOTIFICATION',
'command_name': {'$regex': 'notify-service-by-slack'}}
if app.alignak:
# Restrictive filter on contact name
filters = {
'alignak.event': {'$in': ['HOST NOTIFICATION', 'SERVICE NOTIFICATION']},
'alignak.contact': 'notified'
}

logs = list(app.logs_module.get_ui_logs(range_start=range_start, range_end=range_end,
filters=filters, limit=None))

hosts = Counter()
services = Counter()
hostsservices = Counter()
new_logs = []
for l in logs:
# Alignak logstash parser....
if 'alignak' in l:
l = l['alignak']
if 'time' not in l:
l['time'] = int(time.mktime(l.pop('timestamp').timetuple()))

if 'service' in l:
l['service_description'] = l.pop('service')

hosts[l['host_name']] += 1
services[l['service_description']] += 1
hostsservices[l['host_name'] + '/' + l['service_description']] += 1
if 'service_description' in l:
services[l['service_description']] += 1
hostsservices[l['host_name'] + '/' + l['service_description']] += 1
new_logs.append(l)

return {
'hosts': hosts,
'services': services,
'hostsservices': hostsservices,
'days': days,
'graph': _graph(logs) if logs else None
'graph': _graph(new_logs) if new_logs else None
}


Expand Down Expand Up @@ -136,20 +233,50 @@ def get_host_stats(name):
range_end = int(app.request.GET.get('range_end', time.time()))
range_start = int(app.request.GET.get('range_start', range_end - (days * 86400)))

filters = {'type': 'SERVICE NOTIFICATION',
'command_name': {'$regex': 'notify-service-by-slack'},
'host_name': name}
if app.alignak:
# Restrictive filter on contact name
filters = {
'alignak.event': {'$in': ['HOST NOTIFICATION', 'SERVICE NOTIFICATION']},
'alignak.contact': 'notified',
'alignak.host_name': name
}

logs = list(app.logs_module.get_ui_logs(
range_start=range_start, range_end=range_end,
filters={'type': 'SERVICE NOTIFICATION',
'command_name': {'$regex': 'notify-service-by-slack'},
'host_name': name},
filters=filters,
limit=None))

hosts = Counter()
services = Counter()
for l in logs:
services[l['service_description']] += 1
return {'host': name, 'services': services, 'days': days}
# Alignak logstash parser....
if 'alignak' in l:
l = l['alignak']
if 'time' not in l:
l['time'] = int(time.mktime(l.pop('timestamp').timetuple()))

if 'service' in l:
l['service_description'] = l.pop('service')

hosts[l['host_name']] += 1
if 'service_description' in l:
services[l['service_description']] += 1
return {
'host': name,
'hosts': hosts,
'services': services,
'days': days
}


pages = {
get_alignak_stats: {
'name': 'AlignakStats', 'route': '/alignak/stats', 'view': 'stats'
},

get_global_stats: {
'name': 'GlobalStats', 'route': '/stats', 'view': 'stats'
},
Expand Down
9 changes: 9 additions & 0 deletions module/plugins/stats/views/stats.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,49 @@

<div class="col-lg-4">
<div class="panel panel-default">
%total = sum(hosts.values())
<div class="panel-heading"><h3 class="panel-title">{{ total }} host alerts</h3></div>
%if total:
<table class="table table-striped table-condensed">
%for l in hosts.most_common(15):
<tr><td width="160px">{{ l[1] }} ({{ round((l[1] / float(total)) * 100, 1) }}%)</td><td><a href="/stats/host/{{ l[0] }}?days={{ days }}">{{ l[0] }}</a></td></tr>
%end
%other = sum((h[1] for h in hosts.most_common()[15:]))
<tr><td>{{ other }} ({{ round((other / float(total)) * 100, 1) }}%)</td><td><strong>Others</strong></td></tr>
</table>
%end
</div>
</div>

<div class="col-lg-4">
<div class="panel panel-default">
%total = sum(services.values())
<div class="panel-heading"><h3 class="panel-title">{{ total }} services alerts</h3></div>
%if total:
<table class="table table-striped table-condensed">
%for l in services.most_common(15):
<tr><td width="160px">{{ l[1] }} ({{ round((l[1] / float(total)) * 100, 1) }}%)</td><td><a href="/stats/service/{{ l[0] }}?days={{ days }}">{{ l[0] }}</a></td></tr>
%end
%other = sum((s[1] for s in services.most_common()[15:]))
<tr><td>{{ other }} ({{ round((other / float(total)) * 100, 1) }}%)</td><td><strong>Others</strong></td></tr>
</table>
%end
</div>
</div>

<div class="col-lg-4">
<div class="panel panel-default">
%total = sum(hostsservices.values())
<div class="panel-heading"><h3 class="panel-title">{{ total }} hosts/services alerts</h3></div>
%if total:
<table class="table table-striped table-condensed">
%for l in hostsservices.most_common(15):
<tr><td width="160px">{{ l[1] }} ({{ round((l[1] / float(total)) * 100, 1) }}%)</td><td>{{ l[0] }}</td></tr>
%end
%other = sum((h[1] for h in hostsservices.most_common()[15:]))
<tr><td>{{ other }} ({{ round((other / float(total)) * 100, 1) }}%)</td><td><strong>Others</strong></td></tr>
</table>
%end
</div>
</div>

Expand Down
19 changes: 18 additions & 1 deletion module/plugins/stats/views/stats_host.tpl
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
%rebase("layout", css=['logs/css/logs.css'], js=['logs/js/history.js'], title='Alert Statistics on the last 30 days for ' + host)

%total = sum(services.values())
<div class="col-lg-4">
<div class="panel panel-default">
%total = sum(hosts.values())
<div class="panel-heading"><h3 class="panel-title">{{ total }} host alerts</h3></div>
%if total:
<table class="table table-striped table-condensed">
%for l in hosts.most_common(15):
<tr><td width="160px">{{ l[1] }} ({{ round((l[1] / float(total)) * 100, 1) }}%)</td><td><a href="/stats/host/{{ l[0] }}?days={{ days }}">{{ l[0] }}</a></td></tr>
%end
%other = sum((h[1] for h in hosts.most_common()[15:]))
<tr><td>{{ other }} ({{ round((other / float(total)) * 100, 1) }}%)</td><td><strong>Others</strong></td></tr>
</table>
%end
</div>
</div>

<div class="col-lg-4">
<div class="panel panel-default">
%total = sum(services.values())
<div class="panel-heading"><h3 class="panel-title">{{ total }} {{ host }} alerts</h3></div>
%if total:
<table class="table table-striped table-condensed">
%for l in services.most_common(15):
<tr><td>{{ l[1] }} ({{ round((l[1] / float(total)) * 100, 1) }}%)</td><td><a href="/stats/service/{{ l[0] }}">{{ l[0] }}</a></td></tr>
%end
%other = sum((h[1] for h in services.most_common()[15:]))
<tr><td>{{ other }} ({{ round((other / float(total)) * 100, 1) }}%)</td><td><strong>Others</strong></td></tr>
</table>
%end
</div>
</div>

Expand Down
2 changes: 2 additions & 0 deletions module/views/header_element.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@
&nbsp;Live state</a> </li>
<li> <a href="{{ app.get_url('AlignakEvents') }}"> <i class="fa fa-fw fa-th-list sidebar-icon"></i>
&nbsp;Events log</a> </li>
<li> <a href="{{ app.get_url('AlignakStats') }}"> <i class="fa fa-fw fa-th-list sidebar-icon"></i>
&nbsp;Events stats</a> </li>
%if app.logs_module.is_available():
<li> <a href="{{ app.get_url('History') }}"> <i class="fa fa-fw fa-th-list sidebar-icon"></i>
&nbsp;Mongo Logs </a> </li>
Expand Down

0 comments on commit fe47d22

Please sign in to comment.