From 1b6f6f54830164ae23a4c35a8ac283ef5106de5c Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Sat, 19 Sep 2026 22:18:18 +0300 Subject: [PATCH] fix: build a TracerProvider on FastStream Closes #223 --- .../bootstrappers/faststream_bootstrapper.py | 1 + tests/test_faststream_bootstrap.py | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/lite_bootstrap/bootstrappers/faststream_bootstrapper.py b/lite_bootstrap/bootstrappers/faststream_bootstrapper.py index 079f15f..56cf1b5 100644 --- a/lite_bootstrap/bootstrappers/faststream_bootstrapper.py +++ b/lite_bootstrap/bootstrappers/faststream_bootstrapper.py @@ -150,6 +150,7 @@ def is_configured(cls, bootstrap_config: "FastStreamConfig") -> bool: # ty: ign return super().is_configured(bootstrap_config) and bool(bootstrap_config.opentelemetry_middleware_cls) def bootstrap(self) -> None: + super().bootstrap() config = self.bootstrap_config if config.opentelemetry_middleware_cls and config.application.broker: config.application.broker.add_middleware( diff --git a/tests/test_faststream_bootstrap.py b/tests/test_faststream_bootstrap.py index 1e00f76..83d8109 100644 --- a/tests/test_faststream_bootstrap.py +++ b/tests/test_faststream_bootstrap.py @@ -14,6 +14,8 @@ from faststream.redis import RedisBroker, TestRedisBroker from faststream.redis.opentelemetry import RedisTelemetryMiddleware from faststream.redis.prometheus import RedisPrometheusMiddleware +from opentelemetry.instrumentation.instrumentor import BaseInstrumentor +from opentelemetry.sdk import resources from starlette import status from starlette.testclient import TestClient @@ -315,3 +317,42 @@ def test_second_faststream_bootstrapper_bootstrap_raises(broker: RedisBroker) -> second.bootstrap() finally: first.teardown() + + +def test_faststream_bootstrap_builds_its_own_tracer_provider(broker: RedisBroker) -> None: + bootstrapper = FastStreamBootstrapper(bootstrap_config=build_faststream_config(broker=broker)) + bootstrapper.bootstrap() + try: + instruments = [one for one in bootstrapper.instruments if isinstance(one, FastStreamOpenTelemetryInstrument)] + assert len(instruments) == 1 + tracer_provider = instruments[0]._tracer_provider # noqa: SLF001 + assert tracer_provider is not None + assert tracer_provider.resource.attributes[resources.SERVICE_NAME] == "microservice" + finally: + bootstrapper.teardown() + + +def test_faststream_bootstrap_applies_opentelemetry_instrumentors(broker: RedisBroker) -> None: + recorded_tracer_providers: list[object] = [] + + class RecordingInstrumentor(BaseInstrumentor): + def instrumentation_dependencies(self) -> typing.Collection[str]: + return [] + + def _instrument(self, **kwargs: object) -> None: + recorded_tracer_providers.append(kwargs["tracer_provider"]) + + def _uninstrument(self, **_kwargs: object) -> None: ... + + bootstrap_config = dataclasses.replace( + build_faststream_config(broker=broker), + opentelemetry_instrumentors=[RecordingInstrumentor()], + ) + bootstrapper = FastStreamBootstrapper(bootstrap_config=bootstrap_config) + bootstrapper.bootstrap() + try: + instruments = [one for one in bootstrapper.instruments if isinstance(one, FastStreamOpenTelemetryInstrument)] + assert len(instruments) == 1 + assert recorded_tracer_providers == [instruments[0]._tracer_provider] # noqa: SLF001 + finally: + bootstrapper.teardown()