Adding metrics for request timings. (#1190)

This commit is contained in:
kevgliss
2018-04-10 15:55:02 -07:00
committed by GitHub
parent a9baaf4da4
commit 12622d5847
7 changed files with 43 additions and 76 deletions

View File

@ -8,7 +8,8 @@
"""
from __future__ import absolute_import, division, print_function
import time
from flask import g, request
from lemur import factory
from lemur.extensions import metrics
@ -73,17 +74,6 @@ def configure_hook(app):
"""
from flask import jsonify
from werkzeug.exceptions import HTTPException
from lemur.decorators import crossdomain
if app.config.get('CORS'):
@app.after_request
@crossdomain(origin=u"http://localhost:3000", methods=['PUT', 'HEAD', 'GET', 'POST', 'OPTIONS', 'DELETE'])
def after(response):
return response
@app.after_request
def log_status(response):
metrics.send('status_code_{}'.format(response.status_code), 'counter', 1)
return response
@app.errorhandler(Exception)
def handle_error(e):
@ -93,3 +83,29 @@ def configure_hook(app):
app.logger.exception(e)
return jsonify(error=str(e)), code
@app.before_request
def before_request():
g.request_start_time = time.time()
@app.after_request
def after_request(response):
# Return early if we don't have the start time
if not hasattr(g, 'request_start_time'):
return response
# Get elapsed time in milliseconds
elapsed = time.time() - g.request_start_time
elapsed = int(round(1000 * elapsed))
# Collect request/response tags
tags = {
'endpoint': request.endpoint,
'request_method': request.method.lower(),
'status_code': response.status_code
}
# Record our response time metric
metrics.send('response_time', 'TIMER', elapsed, metric_tags=tags)
metrics.send('status_code_{}'.format(response.status_code), 'counter', 1)
return response

View File

@ -1,56 +0,0 @@
"""
.. module: lemur.decorators
:copyright: (c) 2015 by Netflix Inc., see AUTHORS for more
:license: Apache, see LICENSE for more details.
"""
from builtins import str
from datetime import timedelta
from flask import make_response, request, current_app
from functools import update_wrapper
# this is only used for dev
def crossdomain(origin=None, methods=None, headers=None,
max_age=21600, attach_to_all=True,
automatic_options=True): # pragma: no cover
if methods is not None:
methods = ', '.join(sorted(x.upper() for x in methods))
if headers is not None and not isinstance(headers, str):
headers = ', '.join(x.upper() for x in headers)
if not isinstance(origin, str):
origin = ', '.join(origin)
if isinstance(max_age, timedelta):
max_age = max_age.total_seconds()
def get_methods():
if methods is not None:
return methods
options_resp = current_app.make_default_options_response()
return options_resp.headers['allow']
def decorator(f):
def wrapped_function(*args, **kwargs):
if automatic_options and request.method == 'OPTIONS':
resp = current_app.make_default_options_response()
else:
resp = make_response(f(*args, **kwargs))
if not attach_to_all and request.method != 'OPTIONS':
return resp
h = resp.headers
h['Access-Control-Allow-Origin'] = origin
h['Access-Control-Allow-Methods'] = get_methods()
h['Access-Control-Max-Age'] = str(max_age)
h['Access-Control-Allow-Headers'] = "Origin, X-Requested-With, Content-Type, Accept, Authorization "
h['Access-Control-Allow-Credentials'] = 'true'
return resp
f.provide_automatic_options = False
return update_wrapper(wrapped_function, f)
return decorator

View File

@ -26,3 +26,6 @@ sentry = Sentry()
from blinker import Namespace
signals = Namespace()
from flask_cors import CORS
cors = CORS()

View File

@ -21,7 +21,7 @@ from flask import Flask
from lemur.certificates.hooks import activate_debug_dump
from lemur.common.health import mod as health
from lemur.extensions import db, migrate, principal, smtp_mail, metrics, sentry
from lemur.extensions import db, migrate, principal, smtp_mail, metrics, sentry, cors
DEFAULT_BLUEPRINTS = (
@ -124,6 +124,8 @@ def configure_extensions(app):
smtp_mail.init_app(app)
metrics.init_app(app)
sentry.init_app(app)
app.config['CORS_HEADERS'] = 'Content-Type'
cors.init_app(app, resources=r'/api/*', headers='Content-Type', origin='*', supports_credentials=True)
def configure_blueprints(app, blueprints):