Adding metrics for request timings. (#1190)
This commit is contained in:
parent
a9baaf4da4
commit
12622d5847
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -26,3 +26,6 @@ sentry = Sentry()
|
|||
|
||||
from blinker import Namespace
|
||||
signals = Namespace()
|
||||
|
||||
from flask_cors import CORS
|
||||
cors = CORS()
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
asn1crypto==0.24.0 # via cryptography
|
||||
attrs==17.4.0 # via pytest
|
||||
aws-xray-sdk==0.95 # via moto
|
||||
boto3==1.7.2 # via moto
|
||||
boto3==1.7.3 # via moto
|
||||
boto==2.48.0 # via moto
|
||||
botocore==1.10.2 # via boto3, moto, s3transfer
|
||||
botocore==1.10.3 # via boto3, moto, s3transfer
|
||||
certifi==2018.1.18 # via requests
|
||||
cffi==1.11.5 # via cryptography
|
||||
chardet==3.0.4 # via requests
|
||||
|
@ -42,10 +42,10 @@ pyaml==17.12.1 # via moto
|
|||
pycparser==2.18 # via cffi
|
||||
pyflakes==1.6.0
|
||||
pytest-flask==0.10.0
|
||||
pytest-mock==1.8.0
|
||||
pytest-mock==1.9.0
|
||||
pytest==3.5.0
|
||||
python-dateutil==2.6.1 # via botocore, faker, freezegun, moto
|
||||
pytz==2018.3 # via moto
|
||||
pytz==2018.4 # via moto
|
||||
pyyaml==3.12 # via pyaml
|
||||
requests-mock==1.4.0
|
||||
requests==2.18.4 # via aws-xray-sdk, docker, moto, requests-mock
|
||||
|
|
|
@ -11,6 +11,7 @@ Flask-RESTful==0.3.6
|
|||
Flask-Script==2.0.6
|
||||
Flask-SQLAlchemy
|
||||
Flask==0.12
|
||||
Flask-Cors
|
||||
future
|
||||
gunicorn
|
||||
inflection
|
||||
|
|
|
@ -12,13 +12,14 @@ arrow==0.12.1
|
|||
asn1crypto==0.24.0 # via cryptography
|
||||
bcrypt==3.1.4 # via flask-bcrypt, paramiko
|
||||
blinker==1.4 # via flask-mail, flask-principal, raven
|
||||
boto3==1.7.2
|
||||
botocore==1.10.2 # via boto3, s3transfer
|
||||
boto3==1.7.3
|
||||
botocore==1.10.3 # via boto3, s3transfer
|
||||
cffi==1.11.5 # via bcrypt, cryptography, pynacl
|
||||
click==6.7 # via flask
|
||||
cryptography==2.2.2
|
||||
docutils==0.14 # via botocore
|
||||
flask-bcrypt==0.7.1
|
||||
flask-cors==3.0.3
|
||||
flask-mail==0.9.1
|
||||
flask-migrate==2.1.1
|
||||
flask-principal==0.4.0
|
||||
|
@ -55,7 +56,7 @@ pyrfc3339==1.0 # via acme
|
|||
python-dateutil==2.6.1 # via alembic, arrow, botocore
|
||||
python-editor==1.0.3 # via alembic
|
||||
python-ldap==3.0.0
|
||||
pytz==2018.3 # via acme, flask-restful, pyrfc3339
|
||||
pytz==2018.4 # via acme, flask-restful, pyrfc3339
|
||||
raven[flask]==6.6.0
|
||||
requests[security]==2.11.1
|
||||
retrying==1.3.3
|
||||
|
|
Loading…
Reference in New Issue