|
1 | 1 | from fastapi import FastAPI |
| 2 | +from fastapi.security import HTTPAuthorizationCredentials |
2 | 3 | import httpx |
3 | 4 | from importlib.metadata import version |
4 | 5 | import os |
| 6 | +import time |
5 | 7 |
|
6 | 8 | from cdislogging import get_logger |
7 | 9 | from gen3authz.client.arborist.async_client import ArboristClient |
8 | | - |
| 10 | +from fastapi import Request, HTTPException |
9 | 11 | from gen3workflow import logger |
10 | 12 | from gen3workflow.config import config |
| 13 | +from gen3workflow.metrics import Metrics |
11 | 14 | from gen3workflow.routes.ga4gh_tes import router as ga4gh_tes_router |
12 | 15 | from gen3workflow.routes.s3 import s3_root_router, s3_router |
13 | 16 | from gen3workflow.routes.storage import router as storage_router |
14 | 17 | from gen3workflow.routes.system import router as system_router |
| 18 | +from gen3workflow.auth import Auth |
15 | 19 |
|
16 | 20 |
|
17 | 21 | def get_app(httpx_client=None) -> FastAPI: |
@@ -55,6 +59,49 @@ def get_app(httpx_client=None) -> FastAPI: |
55 | 59 | logger=get_logger("gen3workflow.gen3authz", log_level=log_level), |
56 | 60 | ) |
57 | 61 |
|
| 62 | + app.metrics = Metrics( |
| 63 | + enabled=config["ENABLE_PROMETHEUS_METRICS"], |
| 64 | + prometheus_dir=config["PROMETHEUS_MULTIPROC_DIR"], |
| 65 | + ) |
| 66 | + |
| 67 | + if app.metrics.enabled: |
| 68 | + app.mount("/metrics", app.metrics.get_asgi_app()) |
| 69 | + |
| 70 | + @app.middleware("http") |
| 71 | + async def middleware_log_response_and_api_metric( |
| 72 | + request: Request, call_next |
| 73 | + ) -> None: |
| 74 | + """ |
| 75 | + This FastAPI middleware effectively allows pre and post logic to a request. |
| 76 | +
|
| 77 | + We are using this to log the response consistently across defined endpoints (including execution time). |
| 78 | +
|
| 79 | + Args: |
| 80 | + request (Request): the incoming HTTP request |
| 81 | + call_next (Callable): function to call (this is handled by FastAPI's middleware support) |
| 82 | + """ |
| 83 | + start_time = time.perf_counter() |
| 84 | + response = await call_next(request) |
| 85 | + response_time_seconds = time.perf_counter() - start_time |
| 86 | + |
| 87 | + path = request.url.path |
| 88 | + method = request.method |
| 89 | + |
| 90 | + # NOTE: If adding more endpoints to metrics, try making it configurable using a list of paths and methods in config. |
| 91 | + # For now, we are only interested in the "/ga4gh/tes/v1/tasks" endpoint for metrics. |
| 92 | + if method != "POST" or path != "/ga4gh/tes/v1/tasks": |
| 93 | + return response |
| 94 | + |
| 95 | + metrics = app.metrics |
| 96 | + metrics.add_create_task_api_interaction( |
| 97 | + method=method, |
| 98 | + path=path, |
| 99 | + response_time_seconds=response_time_seconds, |
| 100 | + status_code=response.status_code, |
| 101 | + ) |
| 102 | + |
| 103 | + return response |
| 104 | + |
58 | 105 | return app |
59 | 106 |
|
60 | 107 |
|
|
0 commit comments