|
| 1 | +import time |
| 2 | +import logging |
| 3 | + |
| 4 | +from flask import Blueprint, Response, request |
| 5 | +from prometheus_client import Counter, Histogram, generate_latest |
| 6 | +from pyms.flask.services.driver import DriverService |
| 7 | + |
| 8 | +# Based on https://github.com/sbarratt/flask-prometheus |
| 9 | +# and https://github.com/korfuri/python-logging-prometheus/ |
| 10 | + |
| 11 | +FLASK_REQUEST_LATENCY = Histogram( |
| 12 | + "flask_request_latency_seconds", "Flask Request Latency", ["method", "endpoint"] |
| 13 | +) |
| 14 | +FLASK_REQUEST_COUNT = Counter( |
| 15 | + "flask_request_count", "Flask Request Count", ["method", "endpoint", "http_status"] |
| 16 | +) |
| 17 | + |
| 18 | +LOGGER_TOTAL_MESSAGES = Counter( |
| 19 | + "python_logging_messages_total", |
| 20 | + "Count of log entries by service and level.", |
| 21 | + ["service", "level"], |
| 22 | +) |
| 23 | + |
| 24 | + |
| 25 | +def before_request(): |
| 26 | + request.start_time = time.time() |
| 27 | + |
| 28 | + |
| 29 | +def after_request(response): |
| 30 | + request_latency = time.time() - request.start_time |
| 31 | + FLASK_REQUEST_LATENCY.labels(request.method, request.path).observe(request_latency) |
| 32 | + FLASK_REQUEST_COUNT.labels(request.method, request.path, response.status_code).inc() |
| 33 | + |
| 34 | + return response |
| 35 | + |
| 36 | + |
| 37 | +class Service(DriverService): |
| 38 | + service = "metrics" |
| 39 | + |
| 40 | + def __init__(self, service, *args, **kwargs): |
| 41 | + super().__init__(service, *args, **kwargs) |
| 42 | + self.metrics_blueprint = Blueprint("metrics", __name__) |
| 43 | + self.serve_metrics() |
| 44 | + |
| 45 | + def monitor(self, app): |
| 46 | + app.before_request(before_request) |
| 47 | + app.after_request(after_request) |
| 48 | + |
| 49 | + def serve_metrics(self): |
| 50 | + @self.metrics_blueprint.route("/metrics", methods=["GET"]) |
| 51 | + def metrics(): |
| 52 | + return Response( |
| 53 | + generate_latest(), |
| 54 | + mimetype="text/print()lain", |
| 55 | + content_type="text/plain; charset=utf-8", |
| 56 | + ) |
| 57 | + |
| 58 | + def add_logger_handler(self, logger, service_name): |
| 59 | + logger.addHandler(MetricsLogHandler(service_name)) |
| 60 | + return logger |
| 61 | + |
| 62 | + |
| 63 | +class MetricsLogHandler(logging.Handler): |
| 64 | + """A LogHandler that exports logging metrics for Prometheus.io.""" |
| 65 | + |
| 66 | + def __init__(self, app_name): |
| 67 | + super(MetricsLogHandler, self).__init__() |
| 68 | + self.app_name = app_name |
| 69 | + |
| 70 | + def emit(self, record): |
| 71 | + LOGGER_TOTAL_MESSAGES.labels(self.app_name, record.levelname).inc() |
0 commit comments