-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathapp.py
More file actions
108 lines (89 loc) · 3.83 KB
/
app.py
File metadata and controls
108 lines (89 loc) · 3.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
from fastapi import FastAPI
from fastapi.security import HTTPAuthorizationCredentials
import httpx
from importlib.metadata import version
import os
import time
from cdislogging import get_logger
from gen3authz.client.arborist.async_client import ArboristClient
from fastapi import Request, HTTPException
from gen3workflow import logger
from gen3workflow.config import config
from gen3workflow.metrics import Metrics
from gen3workflow.routes.ga4gh_tes import router as ga4gh_tes_router
from gen3workflow.routes.s3 import router as s3_router
from gen3workflow.routes.storage import router as storage_router
from gen3workflow.routes.system import router as system_router
from gen3workflow.auth import Auth
def get_app(httpx_client=None) -> FastAPI:
logger.info("Initializing app")
config.validate()
debug = config["APP_DEBUG"]
log_level = "debug" if debug else "info"
app = FastAPI(
title="Gen3Workflow",
version=version("gen3workflow"),
debug=config["APP_DEBUG"],
root_path=config["DOCS_URL_PREFIX"],
)
app.async_client = httpx_client or httpx.AsyncClient()
app.include_router(ga4gh_tes_router, tags=["GA4GH TES"])
app.include_router(s3_router, tags=["S3"])
app.include_router(storage_router, tags=["Storage"])
app.include_router(system_router, tags=["System"])
# Following will update logger level, propagate, and handlers
get_logger("gen3workflow", log_level=log_level)
logger.info("Initializing Arborist client")
if config["MOCK_AUTH"]:
logger.warning(
"Mock authentication and authorization are enabled! 'MOCK_AUTH' should NOT be enabled in production!"
)
custom_arborist_url = os.environ.get("ARBORIST_URL", config["ARBORIST_URL"])
if custom_arborist_url:
app.arborist_client = ArboristClient(
arborist_base_url=custom_arborist_url,
authz_provider="gen3-workflow",
logger=get_logger("gen3workflow.gen3authz", log_level=log_level),
)
else:
app.arborist_client = ArboristClient(
authz_provider="gen3-workflow",
logger=get_logger("gen3workflow.gen3authz", log_level=log_level),
)
app.metrics = Metrics(
enabled=config["ENABLE_PROMETHEUS_METRICS"],
prometheus_dir=config["PROMETHEUS_MULTIPROC_DIR"],
)
if app.metrics.enabled:
app.mount("/metrics", app.metrics.get_asgi_app())
@app.middleware("http")
async def middleware_log_response_and_api_metric(
request: Request, call_next
) -> None:
"""
This FastAPI middleware effectively allows pre and post logic to a request.
We are using this to log the response consistently across defined endpoints (including execution time).
Args:
request (Request): the incoming HTTP request
call_next (Callable): function to call (this is handled by FastAPI's middleware support)
"""
start_time = time.perf_counter()
response = await call_next(request)
response_time_seconds = time.perf_counter() - start_time
path = request.url.path
method = request.method
# NOTE: If adding more endpoints to metrics, try making it configurable using a list of paths and methods in config.
# For now, we are only interested in the "/ga4gh/tes/v1/tasks" endpoint for metrics.
if method != "POST" or path != "/ga4gh/tes/v1/tasks":
return response
# TODO: Add user_id to this metric, currently we don't have access to fetch the user_id at the middleware level.
metrics = app.metrics
metrics.add_create_task_api_interaction(
method=method,
path=path,
response_time_seconds=response_time_seconds,
status_code=response.status_code,
)
return response
return app
app = get_app()