Skip to content
This repository has been archived by the owner on Jun 2, 2020. It is now read-only.

Commit

Permalink
Pep Fixes
Browse files Browse the repository at this point in the history
Adding timeouts to all requests per http://docs.python-requests.org/en/master/user/quickstart/#timeouts
Threading the filtering of data to speed things up with many DCs, and large amounts of data
Adding output for exceptions, such as wrong user/pass, which are difficult to debug without
Allowing requests timeout to be configurable
  • Loading branch information
naemono committed Jan 22, 2018
1 parent f7700b4 commit dc0e748
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 66 deletions.
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ Overview (DCs)

# faq

#### how can I filter by more than 1 value?
#### how can I filter by more than 1 value?

Amend the URL and add all the filters together as a comma-separated list, e.g.:
Amend the URL and add all the filters together as a comma-separated list, e.g.:
http://localhost:5000/filtered/aaa,bbb,ccc,ddd

#### what do the filters filter by ?
#### what do the filters filter by ?

They filter based on the hosts' subscriptions, except in the Events view where they filter on all properties of the check and the host.

Expand Down Expand Up @@ -85,7 +85,7 @@ Add via pip install or via your package management
```
useradd -r sensu-grid
```

## run as a service
Expand Down Expand Up @@ -121,10 +121,12 @@ dcs:
port: 4567
user: apiuser
password: apipassword
app:
refresh: 60
bg_color: #333333
# This is a python requests layer timeout, as by default, it does not timeout
requests_timeout: 10
```

## run locally / manually
Expand Down
1 change: 1 addition & 0 deletions gridcheck.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import requests
import re


def check_connection(dc):
url = 'http://{0}:{1}/info'.format(dc['url'], dc['port'])
try:
Expand Down
2 changes: 1 addition & 1 deletion gridconfig.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import yaml


class Config(object):
DEBUG = False
TESTING = False
Expand All @@ -25,4 +26,3 @@ class ProdConfig(Config):
class TestingConfig(Config):
TESTING = True
DEBUG = True

123 changes: 78 additions & 45 deletions griddata.py
Original file line number Diff line number Diff line change
@@ -1,95 +1,123 @@
from gridcheck import *
import requests
import six

from functools import partial
from multiprocessing.dummy import Pool as ThreadPool

def get_filter_data(dcs):
filter_data = []
data = None
from gridcheck import check_stash


def _filter_data(timeout, dc):
filter_data = list()
r = None
data = None
url = 'http://{0}:{1}/clients'.format(dc['url'], dc['port'])
try:
if 'user' and 'password' in dc:
r = requests.get(url, auth=(dc['user'], dc['password']), timeout=timeout)
else:
r = requests.get(url, timeout=timeout)
r.raise_for_status()
except Exception as ex:
print("Got exception while filtering on clients: {}".format(str(ex)))
pass
finally:
if r:
data = r.json()
r.close()
else:
print("no reponse")

if data:
for i in data:
for s in i['subscriptions']:
if s not in filter_data:
filter_data.append(s)
else:
print("No response data")
return filter_data

for dc in dcs:
url = 'http://{0}:{1}/clients'.format(dc['url'], dc['port'])
try:
if 'user' and 'password' in dc:
r = requests.get(url, auth=(dc['user'], dc['password']))
else:
r = requests.get(url)
except Exception:
pass
finally:
if r:
data = r.json()
r.close()

if data:
for i in data:
for s in i['subscriptions']:
if s not in filter_data:
filter_data.append(s)

if filter_data:
assert type(filter_data) == list
return filter_data

def get_filter_data(dcs, timeout):
aggregated = list()
pool = ThreadPool(len(dcs))
func = partial(_filter_data, timeout)
aggregated = pool.map(func, dcs)
if aggregated:
assert type(aggregated) == list
return aggregated

return []


def get_data(dc):
def get_data(dc, timeout):
url = 'http://{0}:{1}/results'.format(dc['url'], dc['port'])
data = None
r = None
try:
if 'user' and 'password' in dc:
r = requests.get(url, auth=(dc['user'], dc['password']))
r = requests.get(url, auth=(dc['user'], dc['password']), timeout=timeout)
else:
r = requests.get(url)

except Exception:
r = requests.get(url, timeout=timeout)
r.raise_for_status()
except Exception as ex:
print("Got exception while retrieving data for dc: {} ex: {}".format(dc, str(ex)))
pass
finally:
if r:
data = r.json()
r.close()
else:
print("no reponse")

return data


def get_clients(dc):
def get_clients(dc, timeout):
url = 'http://{0}:{1}/clients'.format(dc['url'], dc['port'])
data = None
r = None

try:
if 'user' and 'password' in dc:
r = requests.get(url, auth=(dc['user'], dc['password']))
r = requests.get(url, auth=(dc['user'], dc['password']), timeout=timeout)
r.raise_for_status()
data = r.json()
else:
r = requests.get(url)
r = requests.get(url, timeout=timeout)
data = r.json()
except Exception:
except Exception as ex:
print("Got exception while retrieving clients for dc: {} ex: {}".format(dc, str(ex)))
pass
finally:
if r:
r.close()
else:
print("no reponse")

return data


def get_stashes(dc):
def get_stashes(dc, timeout):
url = 'http://{0}:{1}/silenced'.format(dc['url'], dc['port'])
data = None
r = None
try:
if 'user' and 'password' in dc:
r = requests.get(url, auth=(dc['user'], dc['password']))
r = requests.get(url, auth=(dc['user'], dc['password']), timeout=timeout)
r.raise_for_status()
data = r.json()
else:
r = requests.get(url)
r = requests.get(url, timeout=timeout)
data = r.json()
except Exception:
except Exception as ex:
print("Got exception while retrieving stashes for dc: {} ex: {}".format(dc, str(ex)))
pass
finally:
if r:
r.close()
else:
print("no reponse")

return data

Expand All @@ -104,7 +132,7 @@ def filter_object(obj, search):
if filter_object(value, search):
return True
else:
return unicode(search) in unicode(obj)
return six.u(search) in six.u(obj)

return False

Expand All @@ -119,19 +147,23 @@ def filter_event(event):
return filter_event


def get_events(dc, filters=[]):
def get_events(dc, timeout, filters=[]):
url = 'http://{0}:{1}/events'.format(dc['url'], dc['port'])

data = []
r = None

try:
if 'user' and 'password' in dc:
r = requests.get(url, auth=(dc['user'], dc['password']))
r = requests.get(url, auth=(dc['user'], dc['password']), timeout=timeout)
r.raise_for_status()
data = r.json()
else:
r = requests.get(url)
r = requests.get(url, timeout=timeout)
data = r.json()
except Exception as ex:
print("Got exception while retrieving events for dc: {} ex: {}".format(dc, str(ex)))
pass
finally:
if r:
r.close()
Expand Down Expand Up @@ -186,7 +218,8 @@ def agg_data(dc, data, stashes, client_data=None, filters=None):

if i['check']['name'] == "keepalive" and i['check']['status'] == 2:
if not check_stash(stashes, i['client'], i['check']['name']):
# we cannot currently apply filters as keepalive checks do not have subscribers/subscriptions
# we cannot currently apply filters as keepalive checks do
# not have subscribers/subscriptions
down += 1
else:
ack += 1
Expand Down
9 changes: 5 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Flask
PyYAML
Flask==0.12.2
PyYAML==3.12
argparse
requests
gunicorn
requests==2.18.4
gunicorn==19.7.1
six==1.11.0
41 changes: 30 additions & 11 deletions sensugrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,17 @@
from flask import abort

from reverseproxied import ReverseProxied
from griddata import *
from gridconfig import *
from gridcheck import check_connection
from griddata import (
agg_data,
get_data,
agg_host_data,
get_stashes,
get_filter_data,
get_clients,
get_events
)
from gridconfig import DevConfig

from multiprocessing.dummy import Pool as ThreadPool
# https://stackoverflow.com/questions/2846653/how-to-use-threading-in-python
Expand All @@ -24,10 +33,16 @@
app.config.from_object(myconfig)
dcs = app.config['DCS']
appcfg = app.config['APPCFG']
timeout = appcfg.get('requests_timeout', 10)


# Python3 doesn't have cmp
def _cmp(x, y):
return (x > y) - (x < y)


def get_agg_data(dc):
r = agg_data(dc, get_data(dc), get_stashes(dc))
r = agg_data(dc, get_data(dc, timeout), get_stashes(dc, timeout))
return r


Expand All @@ -36,17 +51,18 @@ def root():
aggregated = list()
pool = ThreadPool(len(dcs))
aggregated = pool.map(get_agg_data, dcs)
return render_template('data.html', dcs=dcs, data=aggregated, filter_data=get_filter_data(dcs), appcfg=appcfg)
return render_template('data.html', dcs=dcs, data=aggregated, filter_data=get_filter_data(dcs, timeout), appcfg=appcfg)


@app.route('/filtered/<string:filters>', methods=['GET'])
def filtered(filters):
aggregated = []
for dc in dcs:
if check_connection(dc):
aggregated.append(agg_data(dc, get_data(dc), get_stashes(dc), get_clients(dc), filters))
aggregated.append(agg_data(dc, get_data(dc, timeout), get_stashes(
dc, timeout), get_clients(dc, timeout), filters))

return render_template('data.html', dcs=dcs, data=aggregated, filter_data=get_filter_data(dcs), appcfg=appcfg)
return render_template('data.html', dcs=dcs, data=aggregated, filter_data=get_filter_data(dcs, timeout), appcfg=appcfg)


@app.route('/show/<string:d>', methods=['GET'])
Expand All @@ -62,12 +78,13 @@ def showgrid(d, filters=None):
else:
clients = None

data_detail = agg_host_data(get_data(dc), get_stashes(dc), clients, filters)
data_detail = agg_host_data(get_data(dc, timeout),
get_stashes(dc, timeout), clients, filters)
if data_detail:
break
else:
abort(404)
return render_template('detail.html', dc=dc, data=data_detail, filter_data=get_filter_data(dcs), appcfg=appcfg)
return render_template('detail.html', dc=dc, data=data_detail, filter_data=get_filter_data(dcs, timeout), appcfg=appcfg)


@app.route('/events/<string:d>')
Expand All @@ -82,15 +99,16 @@ def events(d, filters=''):
if dc['name'] == d:
dc_found = True
if check_connection(dc):
results += get_events(dc, filters.split(','))
results += get_events(dc, timeout, filters.split(','))
break

if dc_found is False:
abort(404)

results = sorted(results, lambda x, y: cmp(x['check']['status'], y['check']['status']), reverse=True)
results = sorted(results, lambda x, y: _cmp(
x['check']['status'], y['check']['status']), reverse=True)

return render_template('events.html', dc=dc, data=results, filter_data=get_filter_data(dcs), appcfg=appcfg)
return render_template('events.html', dc=dc, data=results, filter_data=get_filter_data(dcs, timeout), appcfg=appcfg)


@app.route('/healthcheck', methods=['GET'])
Expand Down Expand Up @@ -147,6 +165,7 @@ def icon_for_event(event):

return 'question-circle'


if __name__ == '__main__':

app.run(host='0.0.0.0',
Expand Down

0 comments on commit dc0e748

Please sign in to comment.