Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show hourly, daily, weekly if no time range #325

Merged
merged 3 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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))
Loading