Skip to content

Commit 3ad20a7

Browse files
committed
Add middleware test
1 parent 42682d5 commit 3ad20a7

File tree

2 files changed

+47
-10
lines changed

2 files changed

+47
-10
lines changed

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212
from opentelemetry.instrumentation.aiohttp_client import ( # pylint:disable=no-name-in-module
1313
AioHttpClientInstrumentor,
1414
)
15-
from opentelemetry.instrumentation.aiohttp_server import ( # pylint:disable=no-name-in-module
16-
AioHttpServerInstrumentor,
17-
middleware,
15+
from opentelemetry.instrumentation.aiohttp_server import (
16+
middleware as aiohttp_server_opentelemetry_middleware, # pylint:disable=no-name-in-module
1817
)
1918
from opentelemetry.instrumentation.aiopg import ( # pylint:disable=no-name-in-module
2019
AiopgInstrumentor,
@@ -74,17 +73,16 @@ def setup_tracing(
7473
# Add the span processor to the tracer provider
7574
tracer_provider.add_span_processor(BatchSpanProcessor(otlp_exporter)) # type: ignore[attr-defined] # https://github.com/open-telemetry/opentelemetry-python/issues/3713
7675
# Instrument aiohttp server
77-
AioHttpServerInstrumentor().instrument()
78-
# Explanation for extra call DK 10/2024:
76+
# Explanation for custom middleware call DK 10/2024:
7977
# OpenTelemetry Aiohttp autoinstrumentation is meant to be used by only calling `AioHttpServerInstrumentor().instrument()`
80-
# But, the call `AioHttpServerInstrumentor().instrument()` monkeypatches the __init__() of aiohttp's web.application() to in
81-
# the init inject the tracing middleware.
82-
# In simcore, we want to switch tracing on or off and thus depend on the simcore-settings library when we call `AioHttpServerInstrumentor().instrument()`
78+
# The call `AioHttpServerInstrumentor().instrument()` monkeypatches the __init__() of aiohttp's web.application() to inject the tracing middleware, in it's `__init__()`.
79+
# In simcore, we want to switch tracing on or off using the simcore-settings-library.
8380
# The simcore-settings library in turn depends on the instance of web.application(), i.e. the aiohttp webserver, to exist. So here we face a hen-and-egg problem.
81+
# At the time when the instrumentation should be configured, the instance of web.application already exists and the overwrite to the __init__() is never called
8482
#
8583
# Since the code that is provided (monkeypatched) in the __init__ that the opentelemetry-autoinstrumentation-library provides is only 4 lines,
86-
# literally just adding a middleware, we are free to simply execute this "missed call" [since we can't call the monkeypatch'ed __init__()] in this following line:
87-
app.middlewares.append(middleware)
84+
# just adding a middleware, we are free to simply execute this "missed call" [since we can't call the monkeypatch'ed __init__()] in this following line:
85+
app.middlewares.insert(0, aiohttp_server_opentelemetry_middleware)
8886
# Code of the aiohttp server instrumentation: github.com/open-telemetry/opentelemetry-python-contrib/blob/eccb05c808a7d797ef5b6ecefed3590664426fbf/instrumentation/opentelemetry-instrumentation-aiohttp-server/src/opentelemetry/instrumentation/aiohttp_server/__init__.py#L246
8987
# For reference, the above statement was written for:
9088
# - osparc-simcore 1.77.x

services/web/server/tests/unit/isolated/test_application_settings.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@
88
import pytest
99
from aiohttp import web
1010
from models_library.utils.json_serialization import json_dumps
11+
from opentelemetry.instrumentation.aiohttp_server import (
12+
middleware as aiohttp_opentelemetry_middleware,
13+
)
1114
from pydantic import HttpUrl, parse_obj_as
1215
from pytest_simcore.helpers.monkeypatch_envs import (
1316
setenvs_from_dict,
1417
setenvs_from_envfile,
1518
)
1619
from pytest_simcore.helpers.typing_env import EnvVarsDict
20+
from simcore_service_webserver.application import create_application
1721
from simcore_service_webserver.application_settings import (
1822
APP_SETTINGS_KEY,
1923
ApplicationSettings,
@@ -251,3 +255,38 @@ def test_avoid_sensitive_info_in_public(app_settings: ApplicationSettings):
251255
assert not any("token" in key for key in app_settings.public_dict())
252256
assert not any("secret" in key for key in app_settings.public_dict())
253257
assert not any("private" in key for key in app_settings.public_dict())
258+
259+
260+
@pytest.fixture
261+
def tracing_settings_in(request):
262+
return request.param
263+
264+
265+
@pytest.mark.parametrize(
266+
"tracing_settings_in",
267+
[
268+
("http://opentelemetry-collector", 4318),
269+
],
270+
indirect=True,
271+
)
272+
async def test_middleware_restirctions_opentelemetry_is_second_middleware(
273+
mock_webserver_service_environment: EnvVarsDict,
274+
monkeypatch: pytest.MonkeyPatch,
275+
tracing_settings_in,
276+
):
277+
monkeypatch.setenv(
278+
"TRACING_OPENTELEMETRY_COLLECTOR_ENDPOINT", f"{tracing_settings_in[0]}"
279+
)
280+
monkeypatch.setenv(
281+
"TRACING_OPENTELEMETRY_COLLECTOR_PORT", f"{tracing_settings_in[1]}"
282+
)
283+
settings = ApplicationSettings.create_from_envs()
284+
assert settings.WEBSERVER_TRACING
285+
app = create_application()
286+
assert app.middlewares
287+
assert (
288+
app.middlewares[0].__middleware_name__
289+
== "servicelib.aiohttp.monitoring.monitor_simcore_service_webserver"
290+
)
291+
assert app.middlewares[1] == aiohttp_opentelemetry_middleware
292+
assert len(app.middlewares) > 1

0 commit comments

Comments
 (0)