Skip to content

Commit 33e2023

Browse files
committed
propagate tracing-data throughout fastapi apps
1 parent f9200ae commit 33e2023

File tree

24 files changed

+119
-36
lines changed

24 files changed

+119
-36
lines changed

packages/service-library/src/servicelib/fastapi/client_session.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import httpx
44
from fastapi import FastAPI
5+
from servicelib.tracing import TracingData
56
from settings_library.tracing import TracingSettings
67

78
from .tracing import setup_httpx_client_tracing
@@ -13,15 +14,16 @@ def setup_client_session(
1314
default_timeout: datetime.timedelta = datetime.timedelta(seconds=20),
1415
max_keepalive_connections: int = 20,
1516
tracing_settings: TracingSettings | None,
17+
tracing_data: TracingData | None
1618
) -> None:
1719
async def on_startup() -> None:
1820
session = httpx.AsyncClient(
1921
transport=httpx.AsyncHTTPTransport(http2=True),
2022
limits=httpx.Limits(max_keepalive_connections=max_keepalive_connections),
2123
timeout=default_timeout.total_seconds(),
2224
)
23-
if tracing_settings:
24-
setup_httpx_client_tracing(session)
25+
if tracing_settings and tracing_data:
26+
setup_httpx_client_tracing(session, tracing_data=tracing_data)
2527
app.state.aiohttp_client_session = session
2628

2729
async def on_shutdown() -> None:

packages/service-library/src/servicelib/fastapi/http_client_thin.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from common_library.errors_classes import OsparcErrorMixin
99
from httpx import AsyncClient, ConnectError, HTTPError, PoolTimeout, Response
1010
from httpx._types import TimeoutTypes, URLTypes
11+
from servicelib.tracing import TracingData
1112
from settings_library.tracing import TracingSettings
1213
from tenacity import RetryCallState
1314
from tenacity.asyncio import AsyncRetrying
@@ -201,6 +202,7 @@ def __init__(
201202
*,
202203
total_retry_interval: float,
203204
tracing_settings: TracingSettings | None,
205+
tracing_data: TracingData | None,
204206
base_url: URLTypes | None = None,
205207
default_http_client_timeout: TimeoutTypes | None = None,
206208
extra_allowed_method_names: set[str] | None = None,
@@ -224,8 +226,8 @@ def __init__(
224226
client_args["timeout"] = default_http_client_timeout
225227

226228
client = AsyncClient(**client_args)
227-
if tracing_settings:
228-
setup_httpx_client_tracing(client)
229+
if tracing_settings and tracing_data:
230+
setup_httpx_client_tracing(client, tracing_data=tracing_data)
229231
super().__init__(client=client)
230232

231233
async def __aenter__(self):

packages/service-library/src/servicelib/fastapi/tracing.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import logging
44
from collections.abc import AsyncIterator
5+
from typing import overload
56

67
from fastapi import FastAPI, Request
78
from fastapi_lifespan_manager import State
@@ -215,8 +216,12 @@ def initialize_fastapi_app_tracing(
215216
)
216217

217218

218-
def setup_httpx_client_tracing(client: AsyncClient | Client):
219-
HTTPXClientInstrumentor.instrument_client(client)
219+
def setup_httpx_client_tracing(
220+
client: AsyncClient | Client, tracing_data: TracingData
221+
) -> None:
222+
HTTPXClientInstrumentor.instrument_client(
223+
client, tracer_provider=tracing_data.tracer_provider
224+
)
220225

221226

222227
def setup_tracing(
@@ -228,10 +233,10 @@ def setup_tracing(
228233
tracing_settings=tracing_settings, service_name=service_name
229234
)
230235
app.state.tracing_data = tracing_data
231-
_startup(tracing_settings=tracing_settings, tracing_data=get_tracing_data(app))
236+
_startup(tracing_settings=tracing_settings, tracing_data=tracing_data)
232237

233238
def _on_shutdown() -> None:
234-
_shutdown(tracing_data=get_tracing_data(app))
239+
_shutdown(tracing_data=tracing_data)
235240

236241
app.add_event_handler("shutdown", _on_shutdown)
237242

@@ -264,6 +269,21 @@ async def dispatch(self, request: Request, call_next):
264269
return response
265270

266271

267-
def get_tracing_data(app: FastAPI) -> TracingData:
272+
@overload
273+
def get_tracing_data(
274+
app: FastAPI, tracing_settings: TracingSettings
275+
) -> TracingData: ...
276+
277+
278+
@overload
279+
def get_tracing_data(app: FastAPI, tracing_settings: None) -> None: ...
280+
281+
282+
def get_tracing_data(
283+
app: FastAPI, tracing_settings: TracingSettings | None
284+
) -> TracingData | None:
285+
if tracing_settings is None:
286+
return None
268287
assert hasattr(app.state, "tracing_data"), "Tracing not setup for this app" # nosec
288+
assert isinstance(app.state.tracing_data, TracingData)
269289
return app.state.tracing_data

packages/service-library/tests/fastapi/test_http_client_thin.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ async def test_retry_on_errors(
100100
caplog_info_level: pytest.LogCaptureFixture,
101101
) -> None:
102102
client = FakeThickClient(
103-
total_retry_interval=request_timeout, tracing_settings=None
103+
total_retry_interval=request_timeout, tracing_settings=None, tracing_data=None
104104
)
105105

106106
with pytest.raises(ClientHttpError):
@@ -125,7 +125,9 @@ async def raises_request_error(self) -> Response:
125125
request=Request(method="GET", url=test_url),
126126
)
127127

128-
client = ATestClient(total_retry_interval=request_timeout, tracing_settings=None)
128+
client = ATestClient(
129+
total_retry_interval=request_timeout, tracing_settings=None, tracing_data=None
130+
)
129131

130132
with pytest.raises(ClientHttpError):
131133
await client.raises_request_error()
@@ -151,7 +153,9 @@ async def raises_http_error(self) -> Response:
151153
msg = "mock_http_error"
152154
raise HTTPError(msg)
153155

154-
client = ATestClient(total_retry_interval=request_timeout, tracing_settings=None)
156+
client = ATestClient(
157+
total_retry_interval=request_timeout, tracing_settings=None, tracing_data=None
158+
)
155159

156160
with pytest.raises(ClientHttpError):
157161
await client.raises_http_error()
@@ -165,15 +169,19 @@ async def public_method_ok(self) -> Response: # type: ignore
165169
"""this method will be ok even if no code is used"""
166170

167171
# OK
168-
OKTestClient(total_retry_interval=request_timeout, tracing_settings=None)
172+
OKTestClient(
173+
total_retry_interval=request_timeout, tracing_settings=None, tracing_data=None
174+
)
169175

170176
class FailWrongAnnotationTestClient(BaseThinClient):
171177
async def public_method_wrong_annotation(self) -> None:
172178
"""this method will raise an error"""
173179

174180
with pytest.raises(AssertionError, match="should return an instance"):
175181
FailWrongAnnotationTestClient(
176-
total_retry_interval=request_timeout, tracing_settings=None
182+
total_retry_interval=request_timeout,
183+
tracing_settings=None,
184+
tracing_data=None,
177185
)
178186

179187
class FailNoAnnotationTestClient(BaseThinClient):
@@ -182,7 +190,9 @@ async def public_method_no_annotation(self):
182190

183191
with pytest.raises(AssertionError, match="should return an instance"):
184192
FailNoAnnotationTestClient(
185-
total_retry_interval=request_timeout, tracing_settings=None
193+
total_retry_interval=request_timeout,
194+
tracing_settings=None,
195+
tracing_data=None,
186196
)
187197

188198

@@ -208,7 +218,7 @@ async def get_wrong_state(self) -> Response:
208218
respx_mock.get(get_wrong_state).mock(return_value=Response(codes.OK))
209219

210220
test_client = ATestClient(
211-
total_retry_interval=request_timeout, tracing_settings=None
221+
total_retry_interval=request_timeout, tracing_settings=None, tracing_data=None
212222
)
213223

214224
# OK
@@ -231,7 +241,7 @@ async def test_retry_timeout_overwrite(
231241
caplog_info_level: pytest.LogCaptureFixture,
232242
) -> None:
233243
client = FakeThickClient(
234-
total_retry_interval=request_timeout, tracing_settings=None
244+
total_retry_interval=request_timeout, tracing_settings=None, tracing_data=None
235245
)
236246

237247
caplog_info_level.clear()

services/agent/src/simcore_service_agent/core/application.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ def create_app(settings: ApplicationSettings | None = None) -> FastAPI:
6363
setup_rpc_api_routes(app)
6464

6565
if settings.AGENT_TRACING:
66-
initialize_fastapi_app_tracing(app, tracing_data=get_tracing_data(app))
66+
initialize_fastapi_app_tracing(
67+
app, tracing_data=get_tracing_data(app, settings.AGENT_TRACING)
68+
)
6769

6870
async def _on_startup() -> None:
6971
print(APP_STARTED_BANNER_MSG, flush=True) # noqa: T201

services/api-server/src/simcore_service_api_server/core/application.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ def create_app(settings: ApplicationSettings | None = None) -> FastAPI:
9898

9999
if settings.API_SERVER_TRACING:
100100
initialize_fastapi_app_tracing(
101-
app, tracing_data=get_tracing_data(app), add_response_trace_id_header=True
101+
app,
102+
tracing_data=get_tracing_data(app, settings.API_SERVER_TRACING),
103+
add_response_trace_id_header=True,
102104
)
103105

104106
if settings.API_SERVER_WEBSERVER:

services/autoscaling/src/simcore_service_autoscaling/core/application.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,10 @@ def create_app(settings: ApplicationSettings) -> FastAPI:
6161
setup_ssm(app)
6262
setup_redis(app)
6363

64-
if app.state.settings.AUTOSCALING_TRACING:
65-
initialize_fastapi_app_tracing(app, tracing_data=get_tracing_data(app))
64+
if settings.AUTOSCALING_TRACING:
65+
initialize_fastapi_app_tracing(
66+
app, tracing_data=get_tracing_data(app, settings.AUTOSCALING_TRACING)
67+
)
6668

6769
setup_auto_scaler_background_task(app)
6870
setup_warm_buffer_machines_pool_task(app)

services/catalog/src/simcore_service_catalog/core/application.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ def create_app(
6666
setup_prometheus_instrumentation(app)
6767

6868
if settings.CATALOG_TRACING:
69-
initialize_fastapi_app_tracing(app, tracing_data=get_tracing_data(app))
69+
initialize_fastapi_app_tracing(
70+
app, tracing_data=get_tracing_data(app, settings.CATALOG_TRACING)
71+
)
7072

7173
if settings.SC_BOOT_MODE != BootModeEnum.PRODUCTION:
7274
# middleware to time requests (ONLY for development)

services/clusters-keeper/src/simcore_service_clusters_keeper/core/application.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ def create_app(settings: ApplicationSettings) -> FastAPI:
6565
setup_clusters_management(app)
6666

6767
if app.state.settings.CLUSTERS_KEEPER_TRACING:
68-
initialize_fastapi_app_tracing(app, tracing_data=get_tracing_data(app))
68+
initialize_fastapi_app_tracing(
69+
app, tracing_data=get_tracing_data(app, settings.CLUSTERS_KEEPER_TRACING)
70+
)
6971
# ERROR HANDLERS
7072

7173
# EVENTS

services/datcore-adapter/src/simcore_service_datcore_adapter/core/application.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,10 @@ def create_app(settings: ApplicationSettings) -> FastAPI:
6363
)
6464
app.add_middleware(GZipMiddleware)
6565

66-
if app.state.settings.DATCORE_ADAPTER_TRACING:
67-
initialize_fastapi_app_tracing(app, tracing_data=get_tracing_data(app))
66+
if settings.DATCORE_ADAPTER_TRACING:
67+
initialize_fastapi_app_tracing(
68+
app, tracing_data=get_tracing_data(app, settings.DATCORE_ADAPTER_TRACING)
69+
)
6870

6971
# events
7072
app.add_event_handler("startup", on_startup)

0 commit comments

Comments
 (0)