Skip to content

Commit 9a8767c

Browse files
authored
✨activate tracing in all fastapi apps (ITISFoundation#2591)
1 parent aa39182 commit 9a8767c

File tree

13 files changed

+83
-36
lines changed

13 files changed

+83
-36
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from fastapi import FastAPI
55
from fastapi.exceptions import RequestValidationError
66
from httpx import HTTPStatusError
7+
from servicelib.fastapi.tracing import setup_tracing
78
from servicelib.logging_utils import config_all_loggers
89
from starlette import status
910
from starlette.exceptions import HTTPException
@@ -65,6 +66,9 @@ def init_app(settings: Optional[AppSettings] = None) -> FastAPI:
6566
if settings.API_SERVER_DIRECTOR_V2:
6667
director_v2.setup(app, settings.API_SERVER_DIRECTOR_V2)
6768

69+
if settings.API_SERVER_TRACING:
70+
setup_tracing(app, settings.API_SERVER_TRACING)
71+
6872
# setup app
6973
app.add_event_handler("startup", create_start_app_handler(app))
7074
app.add_event_handler("shutdown", create_stop_app_handler(app))

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from settings_library.base import BaseCustomSettings
99
from settings_library.logging_utils import MixinLoggingSettings
1010
from settings_library.postgres import PostgresSettings
11+
from settings_library.tracing import TracingSettings
1112

1213
# SERVICES CLIENTS --------------------------------------------
1314

@@ -91,6 +92,7 @@ class AppSettings(BaseCustomSettings, MixinLoggingSettings):
9192
API_SERVER_CATALOG: Optional[CatalogSettings]
9293
API_SERVER_STORAGE: Optional[StorageSettings]
9394
API_SERVER_DIRECTOR_V2: Optional[DirectorV2Settings]
95+
API_SERVER_TRACING: Optional[TracingSettings]
9496

9597
API_SERVER_DEV_FEATURES_ENABLED: bool = Field(
9698
False, env=["API_SERVER_DEV_FEATURES_ENABLED", "FAKE_API_SERVER_ENABLED"]

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from fastapi import FastAPI
55
from models_library.basic_types import BootModeEnum
6+
from servicelib.fastapi.tracing import setup_tracing
67

78
from ..api.module_setup import setup_api
89
from ..meta import api_version, api_vtag
@@ -53,4 +54,7 @@ def create_app(settings: Optional[Settings] = None) -> FastAPI:
5354
if settings.PENNSIEVE.PENNSIEVE_ENABLED:
5455
pennsieve.setup(app, settings.PENNSIEVE)
5556

57+
if settings.DATCORE_ADAPTER_TRACING:
58+
setup_tracing(app, settings.DATCORE_ADAPTER_TRACING)
59+
5660
return app

services/datcore-adapter/src/simcore_service_datcore_adapter/utils/requests_decorators.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,21 @@
1515
async def _cancel_task_if_client_disconnected(
1616
request: Request, task: asyncio.Task, interval: float = _DEFAULT_CHECK_INTERVAL_S
1717
) -> None:
18-
with suppress(CancelledError):
18+
try:
1919
while True:
20+
if task.done():
21+
logger.debug("task %s is done", task)
22+
break
2023
if await request.is_disconnected():
2124
logger.warning("client %s disconnected!", request.client)
2225
task.cancel()
2326
break
2427
await asyncio.sleep(interval)
28+
except CancelledError:
29+
logger.debug("task was cancelled")
30+
raise
31+
finally:
32+
logger.debug("task completed")
2533

2634

2735
def cancellable_request(handler: Callable[..., Coroutine[Any, Any, Optional[Any]]]):
@@ -56,5 +64,7 @@ async def decorator(*args, **kwargs) -> Optional[Any]:
5664
return Response("Oh No!", status_code=499)
5765
finally:
5866
auto_cancel_task.cancel()
67+
with suppress(CancelledError):
68+
await auto_cancel_task
5969

6070
return decorator

services/datcore-adapter/tests/unit/conftest.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import pytest
1414
import respx
1515
import simcore_service_datcore_adapter
16+
from _pytest.monkeypatch import MonkeyPatch
1617
from asgi_lifespan import LifespanManager
1718
from fastapi.applications import FastAPI
1819
from simcore_service_datcore_adapter.modules.pennsieve import _create_pennsieve_client
@@ -68,8 +69,14 @@ def client(minimal_app: FastAPI) -> TestClient:
6869
return cli
6970

7071

72+
@pytest.fixture
73+
def app_envs(monkeypatch: MonkeyPatch):
74+
# disable tracing as together with LifespanManager, it does not remove itself nicely
75+
monkeypatch.setenv("DATCORE_ADAPTER_TRACING", "null")
76+
77+
7178
@pytest.fixture()
72-
async def initialized_app(minimal_app: FastAPI) -> Iterator[FastAPI]:
79+
async def initialized_app(app_envs: None, minimal_app: FastAPI) -> Iterator[FastAPI]:
7380
async with LifespanManager(minimal_app):
7481
yield minimal_app
7582

services/director-v2/src/simcore_service_director_v2/core/application.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from fastapi import FastAPI
55
from fastapi.exceptions import RequestValidationError
66
from servicelib.fastapi.openapi import override_fastapi_openapi_method
7+
from servicelib.fastapi.tracing import setup_tracing
78
from simcore_service_director_v2.modules import dask_client
89
from starlette import status
910
from starlette.exceptions import HTTPException
@@ -89,6 +90,9 @@ def init_app(settings: Optional[AppSettings] = None) -> FastAPI:
8990
):
9091
comp_scheduler.setup(app)
9192

93+
if settings.DIRECTOR_V2_TRACING:
94+
setup_tracing(app, settings.DIRECTOR_V2_TRACING)
95+
9296
# setup app --
9397
app.add_event_handler("startup", on_startup)
9498
app.add_event_handler("shutdown", on_shutdown)

services/director-v2/src/simcore_service_director_v2/modules/dask_client.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import contextlib
44
import functools
55
import logging
6+
import os
7+
import socket
68
from dataclasses import dataclass, field
79
from pprint import pformat
810
from typing import Any, Awaitable, Callable, Dict, Iterable, List, Tuple, Union
@@ -99,7 +101,7 @@ async def create(
99101
client=await dask.distributed.Client(
100102
f"tcp://{settings.DASK_SCHEDULER_HOST}:{settings.DASK_SCHEDULER_PORT}",
101103
asynchronous=True,
102-
name="director-v2-client",
104+
name=f"director-v2-client_{socket.gethostname()}_{os.getpid()}",
103105
), # type: ignore
104106
settings=settings,
105107
)
@@ -131,7 +133,7 @@ async def delete(self) -> None:
131133
async def reconnect_client(self):
132134
if self.client:
133135
await self.client.close() # type: ignore
134-
self.client = await dask.distributed.Client(
136+
self.client = await distributed.Client(
135137
f"tcp://{self.settings.DASK_SCHEDULER_HOST}:{self.settings.DASK_SCHEDULER_PORT}",
136138
asynchronous=True,
137139
name="director-v2-client",
@@ -149,10 +151,9 @@ def register_handlers(
149151
async def _dask_sub_handler(
150152
dask_sub_topic_name: str, handler: Callable[[str], Awaitable[None]]
151153
):
152-
dask_sub = distributed.Sub(dask_sub_topic_name)
153-
154154
while True:
155155
try:
156+
dask_sub = distributed.Sub(dask_sub_topic_name)
156157
async for event in dask_sub:
157158
logger.debug("received event %s", event)
158159
await handler(event)

services/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/scheduler/task.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -343,9 +343,10 @@ async def _run_scheduler_task(self) -> None:
343343

344344
await sleep(settings.DIRECTOR_V2_DYNAMIC_SCHEDULER_INTERVAL_SECONDS)
345345
except asyncio.CancelledError: # pragma: no cover
346-
break # pragma: no cover
347-
348-
logger.warning("Scheduler was shut down")
346+
logger.info("Stopped dynamic scheduler")
347+
raise
348+
except Exception: # pylint: disable=broad-except
349+
logger.error("Unexpected error in dynamic scheduler", exc_info=True)
349350

350351
async def _discover_running_services(self) -> None:
351352
"""discover all services which were started before and add them to the scheduler"""
@@ -395,6 +396,7 @@ async def shutdown(self):
395396

396397
if self._trigger_observation_queue_task is not None:
397398
await self._trigger_observation_queue.put(None)
399+
398400
self._trigger_observation_queue_task.cancel()
399401
with contextlib.suppress(asyncio.CancelledError):
400402
await self._trigger_observation_queue_task
@@ -405,7 +407,6 @@ async def shutdown(self):
405407
async def setup_scheduler(app: FastAPI):
406408
dynamic_sidecars_scheduler = DynamicSidecarsScheduler(app)
407409
app.state.dynamic_sidecar_scheduler = dynamic_sidecars_scheduler
408-
409410
settings: DynamicServicesSchedulerSettings = (
410411
app.state.settings.DYNAMIC_SERVICES.DYNAMIC_SCHEDULER
411412
)

services/director-v2/tests/conftest.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ def mock_env(monkeypatch: MonkeyPatch) -> None:
131131

132132
monkeypatch.setenv("SC_BOOT_MODE", "production")
133133

134+
# disable tracing as together with LifespanManager, it does not remove itself nicely
135+
monkeypatch.setenv("DIRECTOR_V2_TRACING", "null")
136+
134137

135138
@pytest.fixture(scope="function")
136139
def client(loop: asyncio.AbstractEventLoop, mock_env: None) -> Iterable[TestClient]:

services/director-v2/tests/integration/01/test_computation_api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ def mock_env(monkeypatch: MonkeyPatch, request) -> None:
6969
"DIRECTOR_V2_CELERY_SCHEDULER_ENABLED",
7070
"1" if request.param == "celery" else "0",
7171
)
72+
monkeypatch.setenv("DIRECTOR_V2_TRACING", "null")
7273
monkeypatch.setenv("SIMCORE_SERVICES_NETWORK_NAME", "test_swarm_network_name")
7374
monkeypatch.setenv("TRAEFIK_SIMCORE_ZONE", "test_mocked_simcore_zone")
7475
monkeypatch.setenv("SWARM_STACK_NAME", "test_mocked_stack_name")

0 commit comments

Comments
 (0)