Project

General

Profile

1
import time
2

    
3
from prometheus_client import Counter, Gauge, Histogram
4
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
5
from starlette.requests import Request
6
from starlette.responses import Response
7

    
8
REQUESTS = Counter("starlette_requests_total", "Total count of requests by method and path.", ["method", "path"])
9
RESPONSES = Counter(
10
    "scholexplorerPortal_responses_total",
11
    "Total count of responses by method, path and status codes.",
12
    ["method", "path", "status_code"],
13
)
14
REQUESTS_PROCESSING_TIME = Histogram(
15
    "scholexplorerPortal_requests_processing_time_seconds",
16
    "Histogram of requests processing time by path (in seconds)",
17
    ["method", "path"],
18
)
19
EXCEPTIONS = Counter(
20
    "scholexplorerPortal_exceptions_total",
21
    "Histogram of exceptions raised by path and exception type",
22
    ["method", "path", "exception_type"],
23
)
24
REQUESTS_IN_PROGRESS = Gauge(
25
    "scholexplorerPortal_requests_in_progress",
26
    "Gauge of requests by method and path currently being processed",
27
    ["method", "path"],
28
)
29

    
30

    
31
class PrometheusMiddleware(BaseHTTPMiddleware):
32
    async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response:
33
        method = request.method
34
        path = request.url.path
35

    
36
        REQUESTS_IN_PROGRESS.labels(method=method, path=path).inc()
37
        REQUESTS.labels(method=method, path=path).inc()
38
        try:
39
            before_time = time.time()
40
            response = await call_next(request)
41
            after_time = time.time()
42
        except Exception as e:
43
            EXCEPTIONS.labels(method=method, path=path, exception_type=type(e).__name__).inc()
44
            raise e from None
45
        else:
46
            REQUESTS_PROCESSING_TIME.labels(method=method, path=path).observe(after_time - before_time)
47
            RESPONSES.labels(method=method, path=path, status_code=response.status_code).inc()
48
        finally:
49
            REQUESTS_IN_PROGRESS.labels(method=method, path=path).dec()
50

    
51
        return response
(3-3/5)