You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
FastStream OpenTelemetry, Prometheus and logging instruments attach only to the first broker #295
Split out of #293, which covers the same problem in the health check.
The FastStream instruments read config.application.broker, which FastStream defines as brokers[0]:
FastStreamOpenTelemetryInstrument adds opentelemetry_middleware_cls to that broker only.
FastStreamPrometheusInstrument adds prometheus_middleware_cls to that broker only.
FastStreamLoggingInstrument replaces the logger params storage on that broker only, and its teardown restores only that broker.
In an app with more than one broker (for example through add_broker in FastStream 0.7), messages handled by any broker after the first produce no spans and no metrics, and that broker keeps FastStream's default logger instead of structlog.
Open questions
Can one Prometheus middleware registry be shared across several brokers of different types, or do the metric names collide?
Brokers added with add_broker after bootstrap() would still be missed. Is documenting that enough?
Can one Prometheus registry serve brokers of different types? Yes. MetricsContainer.__init__ looks each metric name up in the registry and reuses an existing collector, so a second middleware instance does not hit a duplicate-registration error. Every metric carries a broker label ("kafka", "redis", ...), so brokers of different types write separate series under one name. The only condition is that every middleware on the registry uses the same metrics_prefix and custom label names, and lite-bootstrap sets neither.
OpenTelemetry behaves the same way: the SDK returns the existing instrument for an identical name, unit and description, without a conflict warning.
Brokers added after bootstrap()? Document it. In FastStream 0.7.8 add_broker only appends to brokers, and start() runs the on_startup hooks in order before starting brokers. A lite-bootstrap hook would miss brokers that later hooks add, which FastStream's own docstring suggests doing.
A third problem
FastStream middleware classes are tied to one broker type. KafkaTelemetryMiddleware and KafkaPrometheusMiddleware wire in Kafka's settings provider, which reads msg.raw_message.topic, and a Redis raw message is a dict. So applying the one configured class to every broker would fix apps with two Kafka brokers and break apps that mix Kafka and Redis.
Plan
opentelemetry_middleware_cls and prometheus_middleware_cls also accept a mapping from broker class to middleware class. Lookup walks the broker's MRO, so the most specific entry wins.
A single class keeps its current meaning: it goes on every broker of the first broker's type.
A broker with no matching class is skipped, with one warn_at_caller warning naming it.
The logging instrument replaces params_storage on every broker and restores each one on teardown.
Docs: the mapping form, and that brokers must be added before bootstrap().
Activity
lesnik512 commentedon Oct 24, 2026
Open questions
Can one Prometheus registry serve brokers of different types? Yes.
MetricsContainer.__init__looks each metric name up in the registry and reuses an existing collector, so a second middleware instance does not hit a duplicate-registration error. Every metric carries abrokerlabel ("kafka","redis", ...), so brokers of different types write separate series under one name. The only condition is that every middleware on the registry uses the samemetrics_prefixand custom label names, and lite-bootstrap sets neither.OpenTelemetry behaves the same way: the SDK returns the existing instrument for an identical name, unit and description, without a conflict warning.
Brokers added after
bootstrap()? Document it. In FastStream 0.7.8add_brokeronly appends tobrokers, andstart()runs theon_startuphooks in order before starting brokers. A lite-bootstrap hook would miss brokers that later hooks add, which FastStream's own docstring suggests doing.A third problem
FastStream middleware classes are tied to one broker type.
KafkaTelemetryMiddlewareandKafkaPrometheusMiddlewarewire in Kafka's settings provider, which readsmsg.raw_message.topic, and a Redis raw message is a dict. So applying the one configured class to every broker would fix apps with two Kafka brokers and break apps that mix Kafka and Redis.Plan
opentelemetry_middleware_clsandprometheus_middleware_clsalso accept a mapping from broker class to middleware class. Lookup walks the broker's MRO, so the most specific entry wins.warn_at_callerwarning naming it.params_storageon every broker and restores each one on teardown.bootstrap().