nav
nav copied to clipboard
[BUG] Ranked statistics does not handle Graphite response errors gracefully
Describe the bug
If the graphite-web API is unreachable from NAV's web process, the Ranked Statistics tool hard-crashes with a 500 error when generating a report, which in turn causes NAV's standard 500 handler to kick in. This isn't very informative to the end user (unless they know how to read the expandable traceback that is offered for potential bug reporters).
To Reproduce
Steps to reproduce the behavior in a dev environment:
- Shut down the
graphite
container - Browse Ranked Statistics from the NAV toolbox
- Select any report and click on the Show statistics button
- See error
Expected behavior
The Ranked Statics view should handle the GraphiteUnreachableError
and display a more friendly error message to the end user, explaining that the statistics report could not be fetched because of a problem with reaching the Graphite server. The user can be prompted to try again, or to contact their NAV admin to resolve the issue.
Screenshots
If applicable, add screenshots to help explain your problem.
Tracebacks
Environment:
Request Method: GET
Request URL: http://localhost/stats/?view=cpu_routers_highestmax&timeframe=day&rows=5&submit=Show+statistics&use_cache=on
Django Version: 3.2.13
Python Version: 3.9.2
Installed Applications:
('nav.models',
'nav.web',
'nav.django',
'django.contrib.staticfiles',
'django.contrib.sessions',
'django.contrib.humanize',
'django_filters',
'crispy_forms',
'crispy_forms_foundation',
'rest_framework',
'nav.auditlog',
'nav.web.macwatch',
'nav.web.geomap',
'nav.portadmin.napalm',
'nav.web.portadmin',
'django.contrib.postgres')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'nav.web.auth.AuthenticationMiddleware',
'nav.web.auth.AuthorizationMiddleware',
'nav.django.legacy.LegacyCleanupMiddleware',
'django.contrib.messages.middleware.MessageMiddleware')
Traceback (most recent call last):
File "/usr/lib/python3.9/urllib/request.py", line 1346, in do_open
h.request(req.get_method(), req.selector, req.data, headers,
File "/usr/lib/python3.9/http/client.py", line 1255, in request
self._send_request(method, url, body, headers, encode_chunked)
File "/usr/lib/python3.9/http/client.py", line 1301, in _send_request
self.endheaders(body, encode_chunked=encode_chunked)
File "/usr/lib/python3.9/http/client.py", line 1250, in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "/usr/lib/python3.9/http/client.py", line 1010, in _send_output
self.send(msg)
File "/usr/lib/python3.9/http/client.py", line 950, in send
self.connect()
File "/usr/lib/python3.9/http/client.py", line 921, in connect
self.sock = self._create_connection(
File "/usr/lib/python3.9/socket.py", line 843, in create_connection
raise err
File "/usr/lib/python3.9/socket.py", line 831, in create_connection
sock.connect(sa)
During handling of the above exception ([Errno 99] Cannot assign requested address), another exception occurred:
File "/source/python/nav/metrics/data.py", line 124, in get_metric_data
response = urlopen(req)
File "/usr/lib/python3.9/urllib/request.py", line 214, in urlopen
return opener.open(url, data, timeout)
File "/usr/lib/python3.9/urllib/request.py", line 517, in open
response = self._open(req, data)
File "/usr/lib/python3.9/urllib/request.py", line 534, in _open
result = self._call_chain(self.handle_open, protocol, protocol +
File "/usr/lib/python3.9/urllib/request.py", line 494, in _call_chain
result = func(*args)
File "/usr/lib/python3.9/urllib/request.py", line 1375, in http_open
return self.do_open(http.client.HTTPConnection, req)
File "/usr/lib/python3.9/urllib/request.py", line 1349, in do_open
raise URLError(err)
During handling of the above exception (<urlopen error [Errno 99] Cannot assign requested address>), another exception occurred:
File "/usr/local/lib/python3.9/dist-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/usr/local/lib/python3.9/dist-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/source/python/nav/web/sortedstats/views.py", line 44, in index
result = process_form(form)
File "/source/python/nav/web/sortedstats/views.py", line 70, in process_form
result = collect_result(view, timeframe, rows)
File "/source/python/nav/web/sortedstats/views.py", line 92, in collect_result
result.collect()
File "/source/python/nav/web/sortedstats/statmodules.py", line 55, in collect
self.data = self.get_sorted_data()
File "/source/python/nav/web/sortedstats/statmodules.py", line 63, in get_sorted_data
data = self.get_data()
File "/source/python/nav/web/sortedstats/statmodules.py", line 69, in get_data
data = get_metric_average(target, start=self.start, end=self.end)
File "/source/python/nav/metrics/data.py", line 50, in get_metric_average
data = get_metric_data(target, start, end)
File "/source/python/nav/metrics/data.py", line 137, in get_metric_data
raise errors.GraphiteUnreachableError("{0} is unreachable".format(base), err)
Exception Type: GraphiteUnreachableError at /stats/
Exception Value: http://localhost:9000/ is unreachable (<urlopen error [Errno 99] Cannot assign requested address>)
Environment (please complete the following information):
- NAV version installed: 5.4.0 and master