Skip to content

Commit 9b7bd1a

Browse files
committed
add lifespan management to tracing instrumentation in aiohttp
1 parent e7ae167 commit 9b7bd1a

File tree

3 files changed

+63
-20
lines changed

3 files changed

+63
-20
lines changed

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

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Adds aiohttp middleware for tracing using opentelemetry instrumentation."""
22

33
import logging
4+
from collections.abc import AsyncIterator, Callable
45

56
from aiohttp import web
67
from opentelemetry import trace
@@ -50,7 +51,7 @@
5051
HAS_AIO_PIKA = False
5152

5253

53-
def setup_tracing(
54+
def _startup(
5455
app: web.Application,
5556
tracing_settings: TracingSettings,
5657
service_name: str,
@@ -143,3 +144,43 @@ def setup_tracing(
143144
msg="Attempting to add aio_pika opentelemetry autoinstrumentation...",
144145
):
145146
AioPikaInstrumentor().instrument()
147+
148+
149+
def _shutdown() -> None:
150+
"""Uninstruments all opentelemetry instrumentors that were instrumented."""
151+
try:
152+
AioHttpClientInstrumentor().uninstrument()
153+
except Exception:
154+
_logger.exception("Failed to uninstrument AioHttpClientInstrumentor")
155+
if HAS_AIOPG:
156+
try:
157+
AiopgInstrumentor().uninstrument()
158+
except Exception:
159+
_logger.exception("Failed to uninstrument AiopgInstrumentor")
160+
if HAS_BOTOCORE:
161+
try:
162+
BotocoreInstrumentor().uninstrument()
163+
except Exception:
164+
_logger.exception("Failed to uninstrument BotocoreInstrumentor")
165+
if HAS_REQUESTS:
166+
try:
167+
RequestsInstrumentor().uninstrument()
168+
except Exception:
169+
_logger.exception("Failed to uninstrument RequestsInstrumentor")
170+
if HAS_AIO_PIKA:
171+
try:
172+
AioPikaInstrumentor().uninstrument()
173+
except Exception:
174+
_logger.exception("Failed to uninstrument AioPikaInstrumentor")
175+
176+
177+
def get_tracing_lifespan(
178+
app: web.Application, tracing_settings: TracingSettings, service_name: str
179+
) -> Callable[[web.Application], AsyncIterator]:
180+
_startup(app=app, tracing_settings=tracing_settings, service_name=service_name)
181+
182+
async def tracing_lifespan(app: web.Application):
183+
yield
184+
_shutdown()
185+
186+
return tracing_lifespan

packages/service-library/tests/aiohttp/test_tracing.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from aiohttp import web
1212
from aiohttp.test_utils import TestClient
1313
from pydantic import ValidationError
14-
from servicelib.aiohttp.tracing import setup_tracing
14+
from servicelib.aiohttp.tracing import get_tracing_lifespan
1515
from settings_library.tracing import TracingSettings
1616

1717

@@ -59,11 +59,10 @@ async def test_valid_tracing_settings(
5959
app = web.Application()
6060
service_name = "simcore_service_webserver"
6161
tracing_settings = TracingSettings()
62-
setup_tracing(
63-
app,
64-
service_name=service_name,
65-
tracing_settings=tracing_settings,
66-
)
62+
async for _ in get_tracing_lifespan(
63+
app, service_name=service_name, tracing_settings=tracing_settings
64+
)(app):
65+
pass
6766

6867

6968
@pytest.mark.parametrize(
@@ -137,14 +136,15 @@ async def test_tracing_setup_package_detection(
137136
app = web.Application()
138137
service_name = "simcore_service_webserver"
139138
tracing_settings = TracingSettings()
140-
setup_tracing(
141-
app,
142-
service_name=service_name,
143-
tracing_settings=tracing_settings,
144-
)
145-
# idempotency
146-
setup_tracing(
139+
async for _ in get_tracing_lifespan(
147140
app,
148141
service_name=service_name,
149142
tracing_settings=tracing_settings,
150-
)
143+
)(app):
144+
# idempotency
145+
async for _ in get_tracing_lifespan(
146+
app,
147+
service_name=service_name,
148+
tracing_settings=tracing_settings,
149+
)(app):
150+
pass

services/web/server/src/simcore_service_webserver/tracing.py

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

33
from aiohttp import web
44
from servicelib.aiohttp.application_setup import ModuleCategory, app_module_setup
5-
from servicelib.aiohttp.tracing import setup_tracing
5+
from servicelib.aiohttp.tracing import get_tracing_lifespan
66
from settings_library.tracing import TracingSettings
77

88
from ._meta import APP_NAME
@@ -23,8 +23,10 @@ def get_plugin_settings(app: web.Application) -> TracingSettings:
2323
)
2424
def setup_app_tracing(app: web.Application):
2525
tracing_settings: TracingSettings = get_plugin_settings(app)
26-
setup_tracing(
27-
app,
28-
tracing_settings=tracing_settings,
29-
service_name=APP_NAME,
26+
app.cleanup_ctx.append(
27+
get_tracing_lifespan(
28+
app,
29+
tracing_settings=tracing_settings,
30+
service_name=APP_NAME,
31+
)
3032
)

0 commit comments

Comments
 (0)