Project

General

Profile

« Previous | Next » 

Revision 55992

added prometheus extension

View differences:

modules/dli-api/branches/2.0/requirements.txt
19 19
uvicorn==0.7.1
20 20
uvloop==0.12.2
21 21
websockets==7.0
22
prometheus-client==0.5.0
modules/dli-api/branches/2.0/eu/dnetlib/metricsMiddleWare.py
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
    "scholexplorerAPI_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
    "scholexplorerAPI_requests_processing_time_seconds",
16
    "Histogram of requests processing time by path (in seconds)",
17
    ["method", "path"],
18
)
19
EXCEPTIONS = Counter(
20
    "scholexplorerAPI_exceptions_total",
21
    "Histogram of exceptions raised by path and exception type",
22
    ["method", "path", "exception_type"],
23
)
24
REQUESTS_IN_PROGRESS = Gauge(
25
    "scholexplorerAPI_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
modules/dli-api/branches/2.0/eu/dnetlib/metrics_utils.py
1
import os
2

  
3
from prometheus_client import CONTENT_TYPE_LATEST, REGISTRY, CollectorRegistry, generate_latest
4
from prometheus_client.multiprocess import MultiProcessCollector
5
from starlette.requests import Request
6
from starlette.responses import Response
7

  
8

  
9
def metrics(request: Request) -> Response:
10
    if "prometheus_multiproc_dir" in os.environ:
11
        registry = CollectorRegistry()
12
        MultiProcessCollector(registry)
13
    else:
14
        registry = REGISTRY
15

  
16
    return Response(generate_latest(registry), media_type=CONTENT_TYPE_LATEST)
modules/dli-api/branches/2.0/main.py
3 3
from v1.api import subapi_v1
4 4
from pympler import muppy, summary
5 5
import logging
6
from eu.dnetlib.metrics_utils import metrics 
7
from eu.dnetlib.metricsMiddleWare import PrometheusMiddleware
6 8

  
7 9

  
10

  
8 11
app = FastAPI()
12

  
9 13
log = logging.getLogger("scholexplorer")
10 14
log.setLevel(logging.DEBUG)
11 15
fh = logging.FileHandler('api.log')
......
14 18
fh.setFormatter(formatter)
15 19
log.addHandler(fh)
16 20
log.info("Scholexplorer Api Restarted")
21

  
22

  
23

  
24
app.add_middleware(PrometheusMiddleware)
25
app.add_route("/metrics/", metrics)
17 26
app.mount("/v2", subapi_v2)
18 27
app.mount("/v1", subapi_v1)

Also available in: Unified diff