1 |
57352
|
sandro.lab
|
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
|