Skip to content

Commit

Permalink
Collect metrics even if the request handler function raises an except…
Browse files Browse the repository at this point in the history
…ion - Fixes #1
  • Loading branch information
rycus86 committed Dec 29, 2017
1 parent 240d8fd commit 9e3c9a6
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 7 deletions.
11 changes: 9 additions & 2 deletions prometheus_flask_exporter/__init__.py
Expand Up @@ -5,6 +5,7 @@

from flask import request, make_response
from flask import Flask, Response
from werkzeug.exceptions import HTTPException
from prometheus_client import Counter, Histogram, Gauge, Summary
from prometheus_client import generate_latest, CONTENT_TYPE_LATEST
from prometheus_client import REGISTRY as DEFAULT_REGISTRY
Expand Down Expand Up @@ -315,7 +316,13 @@ def func(*args, **kwargs):
metric = None

start_time = default_timer()
response = f(*args, **kwargs)
try:
response = f(*args, **kwargs)
except HTTPException as ex:
response = ex
except Exception as ex:
response = make_response('Exception: %s' % ex, 500)

total_time = max(default_timer() - start_time, 0)

if not metric:
Expand Down Expand Up @@ -407,4 +414,4 @@ def info(self, name, description, labelnames=None, labelvalues=None, **labels):
return gauge


__version__ = '0.1.1'
__version__ = '0.1.2'
4 changes: 2 additions & 2 deletions setup.py
Expand Up @@ -8,14 +8,14 @@
setup(
name='prometheus_flask_exporter',
packages=['prometheus_flask_exporter'],
version='0.1.1',
version='0.1.2',
description='Prometheus metrics exporter for Flask',
long_description=long_description,
license='MIT',
author='Viktor Adam',
author_email='rycus86@gmail.com',
url='https://github.com/rycus86/prometheus_flask_exporter',
download_url='https://github.com/rycus86/prometheus_flask_exporter/archive/0.1.1.tar.gz',
download_url='https://github.com/rycus86/prometheus_flask_exporter/archive/0.1.2.tar.gz',
keywords=['prometheus', 'flask', 'monitoring', 'exporter'],
classifiers=[
'Development Status :: 4 - Beta',
Expand Down
59 changes: 56 additions & 3 deletions tests/test_endpoint.py
@@ -1,17 +1,18 @@
from unittest_helper import BaseTestCase
from flask import request, abort

import time

try:
from urllib2 import urlopen
except:
except ImportError:
# Python 3
from urllib.request import urlopen


class EndpointTest(BaseTestCase):
def test_restricted(self):
metrics = self.metrics()
self.metrics()

@self.app.route('/test')
def test():
Expand Down Expand Up @@ -48,7 +49,7 @@ def test_http_server(self):
metrics.start_http_server(32001)
metrics.start_http_server(32002, endpoint='/test/metrics')
metrics.start_http_server(32003, host='127.0.0.1')

def wait_for_startup():
for _ in range(10):
try:
Expand Down Expand Up @@ -76,3 +77,55 @@ def wait_for_startup():
self.assertEqual(response.getcode(), 200)
self.assertIn('flask_exporter_info', str(response.read()))

def test_abort(self):
metrics = self.metrics()

@self.app.route('/error')
@metrics.summary('http_index_requests_by_status',
'Request latencies by status',
labels={'status': lambda r: r.status_code})
@metrics.histogram('http_index_requests_by_status_and_path',
'Index requests latencies by status and path',
labels={
'status': lambda r: r.status_code,
'path': lambda: request.path
})
def throw_error():
return abort(503)

self.client.get('/error')

self.assertMetric('http_index_requests_by_status_count', 1.0, ('status', 503))
self.assertMetric('http_index_requests_by_status_sum', '.', ('status', 503))

self.assertMetric(
'http_index_requests_by_status_and_path_count', 1.0,
('status', 503), ('path', '/error')
)
self.assertMetric(
'http_index_requests_by_status_and_path_sum', '.',
('status', 503), ('path', '/error')
)
self.assertMetric(
'http_index_requests_by_status_and_path_bucket', 1.0,
('status', 503), ('path', '/error'), ('le', 0.5)
)
self.assertMetric(
'http_index_requests_by_status_and_path_bucket', 1.0,
('status', 503), ('path', '/error'), ('le', 10.0)
)

def test_exception(self):
metrics = self.metrics()

@self.app.route('/exception')
@metrics.summary('http_with_exception',
'Tracks the method raising an exception',
labels={'status': lambda r: r.status_code})
def raise_exception():
raise NotImplementedError('On purpose')

self.client.get('/exception')

self.assertMetric('http_with_exception_count', 1.0, ('status', 500))
self.assertMetric('http_with_exception_sum', '.', ('status', 500))

0 comments on commit 9e3c9a6

Please sign in to comment.