From 94aacd64b8786ae9c7cd51371aac4d12d3b379f4 Mon Sep 17 00:00:00 2001 From: reqww Date: Thu, 13 Nov 2025 23:40:57 +0300 Subject: [PATCH 1/2] Add tracing to faststream asgi health-check --- microbootstrap/bootstrappers/faststream.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/microbootstrap/bootstrappers/faststream.py b/microbootstrap/bootstrappers/faststream.py index 7cd725e..660ea78 100644 --- a/microbootstrap/bootstrappers/faststream.py +++ b/microbootstrap/bootstrappers/faststream.py @@ -8,6 +8,7 @@ from faststream.asgi import AsgiFastStream, AsgiResponse from faststream.asgi import get as handle_get from faststream.specification import AsyncAPI +from opentelemetry import trace from microbootstrap.bootstrappers.base import ApplicationBootstrapper from microbootstrap.config.faststream import FastStreamConfig @@ -23,6 +24,9 @@ from microbootstrap.settings import FastStreamSettings +tracer: typing.Final = trace.get_tracer(__name__) + + class KwargsAsgiFastStream(AsgiFastStream): def __init__(self, **kwargs: typing.Any) -> None: # noqa: ANN401 # `broker` argument is positional-only @@ -107,6 +111,7 @@ def get_config_type(cls) -> type[FastStreamPrometheusConfig]: class FastStreamHealthChecksInstrument(HealthChecksInstrument): def bootstrap(self) -> None: ... def bootstrap_before(self) -> dict[str, typing.Any]: + @tracer.start_as_current_span(f"GET {self.instrument_config.health_checks_path}") @handle_get async def check_health(scope: typing.Any) -> AsgiResponse: # noqa: ANN401, ARG001 return ( From 9d101c1c24949fbc4e909500a162b264955f06ad Mon Sep 17 00:00:00 2001 From: reqww Date: Mon, 17 Nov 2025 19:29:37 +0300 Subject: [PATCH 2/2] Add cross-instrument parameter for health checks span generation --- microbootstrap/bootstrappers/faststream.py | 6 +++++- microbootstrap/instruments/health_checks_instrument.py | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/microbootstrap/bootstrappers/faststream.py b/microbootstrap/bootstrappers/faststream.py index 660ea78..a4fa7a1 100644 --- a/microbootstrap/bootstrappers/faststream.py +++ b/microbootstrap/bootstrappers/faststream.py @@ -111,7 +111,6 @@ def get_config_type(cls) -> type[FastStreamPrometheusConfig]: class FastStreamHealthChecksInstrument(HealthChecksInstrument): def bootstrap(self) -> None: ... def bootstrap_before(self) -> dict[str, typing.Any]: - @tracer.start_as_current_span(f"GET {self.instrument_config.health_checks_path}") @handle_get async def check_health(scope: typing.Any) -> AsgiResponse: # noqa: ANN401, ARG001 return ( @@ -124,6 +123,11 @@ async def check_health(scope: typing.Any) -> AsgiResponse: # noqa: ANN401, ARG0 else AsgiResponse(b"Service is unhealthy", 500, headers={"content-type": "application/json"}) ) + if self.instrument_config.opentelemetry_generate_health_check_spans: + check_health = tracer.start_as_current_span(f"GET {self.instrument_config.health_checks_path}")( + check_health, + ) + return {"asgi_routes": ((self.instrument_config.health_checks_path, check_health),)} async def define_health_status(self) -> bool: diff --git a/microbootstrap/instruments/health_checks_instrument.py b/microbootstrap/instruments/health_checks_instrument.py index 80fe33e..9b0ee3f 100644 --- a/microbootstrap/instruments/health_checks_instrument.py +++ b/microbootstrap/instruments/health_checks_instrument.py @@ -19,6 +19,9 @@ class HealthChecksConfig(BaseInstrumentConfig): health_checks_path: str = "/health/" health_checks_include_in_schema: bool = False + # Cross-instrument parameter, comes from opentelemetry + opentelemetry_generate_health_check_spans: bool = True + class HealthChecksInstrument(Instrument[HealthChecksConfig]): instrument_name = "Health checks"