Skip to content

Commit

Permalink
Show hourly, daily, weekly if no time range (#325)
Browse files Browse the repository at this point in the history
Keep the default of hourly, daily, weekly if the user does not submit a
time range instead of only showing the past 24 hours.
  • Loading branch information
kofrezo committed Jul 25, 2023
1 parent 035afe1 commit 0b41746
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 52 deletions.
4 changes: 2 additions & 2 deletions serveradmin/graphite/templates/graphite/graph_table.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ <h3>Graphs for {{ hostnames|join:", " }}</h3>
<div class="form-group row input-controls">
<label for="from" class="col-sm-1 col-form-label">From:</label>
<div class="col-sm-8">
<input id="from" name="from" type="text" value="{{ from }}" class="form-control form-control-sm" />
<input id="from" name="from" type="text" value="{{ from }}" placeholder="e.g. -24h" class="form-control form-control-sm" />
</div>
</div>
<div class="form-group row input-controls">
<label for="until" class="col-sm-1 col-form-label">Until:</label>
<div class="col-sm-8">
<input id="until" name="until" type="text" value="{{ until }}" class="form-control form-control-sm" />
<input id="until" name="until" type="text" value="{{ until }}" placeholder="e.g. now" class="form-control form-control-sm" />
</div>
</div>
{% for hostname in hostnames %}
Expand Down
107 changes: 57 additions & 50 deletions serveradmin/graphite/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@
from urllib.request import (
HTTPBasicAuthHandler,
HTTPPasswordMgrWithDefaultRealm,
build_opener
build_opener,
)

from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.http import (
HttpResponse, HttpResponseBadRequest, HttpResponseServerError
)
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseServerError
from django.template.response import TemplateResponse
from django.views.decorators.csrf import ensure_csrf_cookie

Expand All @@ -28,7 +26,7 @@
)


@login_required # NOQA: C901
@login_required # NOQA: C901
@ensure_csrf_cookie
def graph_table(request):
"""Generate graph table page
Expand All @@ -37,98 +35,109 @@ def graph_table(request):
:return:
"""

hostnames = [h.strip() for h in request.GET.getlist('hostname', []) if h]
object_ids = [o.strip() for o in request.GET.getlist('object_id', []) if o]
hostnames = [h.strip() for h in request.GET.getlist("hostname", []) if h]
object_ids = [o.strip() for o in request.GET.getlist("object_id", []) if o]

if len(hostnames) == 0 and len(object_ids) == 0:
return HttpResponseBadRequest('No hostname or object_id provided')
return HttpResponseBadRequest("No hostname or object_id provided")

# For convenience, we will cache the servers in a dictionary.
servers = {s['hostname']: s for s in
Query({'hostname': Any(*hostnames)}, None)}
servers.update({s['hostname']: s for s in
Query({'object_id': Any(*object_ids)}, None)})
servers = {s["hostname"]: s for s in Query({"hostname": Any(*hostnames)}, None)}
servers.update(
{s["hostname"]: s for s in Query({"object_id": Any(*object_ids)}, None)}
)

if len(servers) != len(hostnames) + len(object_ids):
messages.error(
request,
'One or more objects with hostname: {} or object_ids: {} does not '
'exist'.format(','.join(hostnames), ','.join(object_ids)))
"One or more objects with hostname: {} or object_ids: {} does not "
"exist".format(",".join(hostnames), ",".join(object_ids)),
)

# Find the collections which are related with all the hostnames.
# If there are two collections with same match, use only the one which
# is not an overview.
collections = []
for collection in Collection.objects.order_by('overview', 'sort_order'):
for collection in Collection.objects.order_by("overview", "sort_order"):
if any(collection.name == c.name for c in collections):
continue
for hostname in servers.keys():
if GRAPHITE_ATTRIBUTE_ID not in servers[hostname]:
break # The server hasn't got this attribute at all.
break # The server hasn't got this attribute at all.
value = servers[hostname][GRAPHITE_ATTRIBUTE_ID]
assert isinstance(value, MultiAttr)
if not any(collection.name == v for v in value):
break # The server hasn't got this attribute value.
break # The server hasn't got this attribute value.
else:
collections.append(collection)

# Prepare the graph descriptions
descriptions = []
for collection in collections:
for template in collection.template_set.all():
descriptions += (
[(template.name, template.description)] * len(servers.keys())
descriptions += [(template.name, template.description)] * len(
servers.keys()
)

# Prepare the graph tables for all hosts
graph_table = []
graph_tables = []
for hostname in servers.keys():
graph_table = []
if request.GET.get('action') == 'Submit':
host_graph_table = []

if request.GET.get("action") == "Submit" and (
request.GET.get("from") or request.GET.get("until")
):
custom_params = request.GET.urlencode()
for collection in collections:
column = collection.graph_column(
servers[hostname], custom_params
)
graph_table += [(k, [('Custom', v)]) for k, v in column]
column = collection.graph_column(servers[hostname], custom_params)
host_graph_table += [(k, [("Custom", v)]) for k, v in column]
else:
for collection in collections:
graph_table += collection.graph_table(servers[hostname])
graph_tables.append(graph_table)
host_graph_table += collection.graph_table(servers[hostname])

graph_tables.append(host_graph_table)

if len(servers) > 1:
# Add hostname to the titles
for order, hostname in enumerate(servers.keys()):
graph_tables[order] = [(k + ' on ' + hostname, v) for k, v in
graph_tables[order]]
graph_tables[order] = [
(k + " on " + hostname, v) for k, v in graph_tables[order]
]

# Combine them
graph_table = []
for combined_tables in zip(*graph_tables):
graph_table += list(combined_tables)
# Combine them
all_graph_tables = []
for combined_tables in zip(*graph_tables):
all_graph_tables += list(combined_tables)

# One can optionally specify a Grafana dashboard which has a parameter
# called SERVER that receives a coded hostname as alternative to the
# builtin graphs.
grafana_links = []
if hasattr(settings, 'GRAFANA_DASHBOARD'):
if hasattr(settings, "GRAFANA_DASHBOARD"):

def _get_grafana_link(hostname):
return settings.GRAFANA_DASHBOARD + '?' + urlencode(
{'var-SERVER': format_attribute_value(hostname)})
return (
settings.GRAFANA_DASHBOARD
+ "?"
+ urlencode({"var-SERVER": format_attribute_value(hostname)})
)

for hostname in servers.keys():
grafana_links.append((hostname, _get_grafana_link(hostname)))

return TemplateResponse(request, 'graphite/graph_table.html', {
'hostnames': servers.keys(),
'descriptions': descriptions,
'graph_table': graph_table,
'grafana_links': grafana_links,
'link': request.get_full_path(),
'from': request.GET.get('from', '-24h'),
'until': request.GET.get('until', 'now'),
})
return TemplateResponse(
request,
"graphite/graph_table.html",
{
"hostnames": servers.keys(),
"descriptions": descriptions,
"graph_table": all_graph_tables,
"grafana_links": grafana_links,
"link": request.get_full_path(),
"from": request.GET.get("from", ""),
"until": request.GET.get("until", ""),
},
)


@login_required
Expand All @@ -148,9 +157,7 @@ def graph(request):
settings.GRAPHITE_PASSWORD,
)
auth_handler = HTTPBasicAuthHandler(password_mgr)
url = '{0}/render?{1}'.format(
settings.GRAPHITE_URL, request.GET.urlencode()
)
url = "{0}/render?{1}".format(settings.GRAPHITE_URL, request.GET.urlencode())

# If the Graphite server fails, we would return proper server error
# to the user instead of failing. This is not really a matter for
Expand All @@ -160,6 +167,6 @@ def graph(request):
# empty result with 200 instead of proper error codes.
try:
with build_opener(auth_handler).open(url) as response:
return HttpResponse(response.read(), content_type='image/png')
return HttpResponse(response.read(), content_type="image/png")
except IOError as error:
return HttpResponseServerError(str(error))

0 comments on commit 0b41746

Please sign in to comment.