Emit messaging operation metrics (publish/receive duration) from Kafka instrumentation#19107
Emit messaging operation metrics (publish/receive duration) from Kafka instrumentation#19107maryantocinn wants to merge 3 commits into
Conversation
…a instrumentation
|
|
There was a problem hiding this comment.
Pull request overview
This PR makes the Kafka instrumentation emit the semantic-convention messaging operation metrics by registering the existing operation-metrics listeners in the shared KafkaInstrumenterFactory (kafka-clients-common-0.11). Because this factory is shared, the change covers the javaagent Kafka instrumentation, the kafka-clients-2.6 library (KafkaTelemetry, Spring Boot starter, manual users), and spring-kafka. It mirrors the existing Pulsar instrumentation, resolving #19094.
Changes:
- Register
MessagingProducerMetrics.get()on the producer instrumenter (emitsmessaging.publish.duration). - Register
MessagingConsumerMetrics.get()on the consumer receive instrumenter (emitsmessaging.receive.duration/messaging.receive.messages, gated bymessagingReceiveInstrumentationEnabled); the process instrumenter is intentionally left untouched. - Add metric assertions in the wrapper tests, with
isReceiveTelemetryEnabled()controlling whether the receive metrics are asserted.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
kafka-clients-common-0.11/.../KafkaInstrumenterFactory.java |
Adds addOperationMetrics(...) to the producer and consumer-receive instrumenters and the corresponding imports. |
kafka-clients-2.6/.../AbstractWrapperTest.java |
Adds assertMessagingMetrics() verifying the publish/receive metric name/unit/description; switches assertThat import to OpenTelemetryAssertions. |
kafka-clients-2.6/.../WrapperTest.java |
Overrides isReceiveTelemetryEnabled() to true and removes the now-redundant assertj assertThat import. |
|
I think we should add these for all messaging instrumentation (doing just kafka in this PR is fine, the rest can be handled separately). It is not ideal that we only have
@trask do you have any preference on how we should handle this? |
|
@laurit Thanks for the review! I'd go with the third option. One extra reason from my side: we run both Java and Go services in my org and we want the same messaging metrics from both, so following the current semconv names ( I'm willing to implement it. This is roughly what I have in mind:
I wouldn't touch the attributes for now, they'd stay the old ones ( If that sounds good I'll update the PR. |
It has downsides, but I'd lean towards continuing to follow https://github.com/open-telemetry/semantic-conventions/blob/main/docs/messaging/README.md, which basically says, emit the old semconv by default, and only emit new semconv under We could bump to latest (even before stable), but ideally only after we have implemented the same conventions consistently across all of our messaging instrumentations. It would probably be confusing for some of our messaging instrumentations to emit earlier semconv and some later semconv by default. |
The thing is that our messaging semconv don't really follow a particular version of the semconv. The version that is closest to how we emit spans doesn't define metrics at all. The messaging metrics are currently only enabled for pulsar so I'd say we can probably allow incompatible changes if we so desire since their usage is limited. |
You've convinced me 😅. But if we're going to do it, let's take the opportunity to sync them all up for 3.0: |
Pull request dashboard statusStatus last refreshed: 2026-07-26 21:34:24 UTC.
This automated status or its linked feedback items may be incorrect. If something looks wrong, please report it with the result you expected. |
|
@trask Sounds good from my end, agreed on aligning to v1.43 for 3.0. Once it's merged, I'll rebase and re-scope this PR to just the Kafka instrumentation on top of the shared contract. Happy to take that follow-up. |
Summary
Emits the semantic-convention messaging metrics from the Kafka instrumentation by registering the existing operation-metrics listeners on the producer and consumer instrumenters in
KafkaInstrumenterFactory(kafka-clients-common-0.11). This mirrors the Pulsar instrumentation, which already registersMessagingProducerMetrics/MessagingConsumerMetrics.Resolves #19094.
What changed
Added
.addOperationMetrics(...)to the producer and consumer receive instrumenters inKafkaInstrumenterFactory:MessagingProducerMetrics.get()MessagingConsumerMetrics.get()(gated bymessagingReceiveInstrumentationEnabledvia the builder'ssetEnabled(...))The consumer process instrumenter is intentionally left untouched, matching Pulsar:
MessagingConsumerMetricsemitsmessaging.receive.*, which is the wrong metric to record for aprocessoperation (and there is nomessaging.process.*listener ininstrumentation-api-incubator).Metrics added
MessagingProducerMetricsmessaging.publish.duration(histogram, s)MessagingConsumerMetricsmessaging.receive.duration(histogram, s),messaging.receive.messages(counter)Scope / impact
A single shared factory (
kafka-clients-common-0.11) is used by the javaagent Kafka instrumentation, thekafka-clients-2.6library (KafkaTelemetry, Spring Boot starter, manual users), andspring-kafka— so all paths get the metrics from one change.Design note for reviewers
Two points to confirm:
otel.instrumentation.messaging.experimental.receive-telemetry.enabled(off by default),messaging.receive.duration/messaging.receive.messagesonly emit when that flag is enabled. The listener is deliberately not added to the process instrumenter, sinceMessagingConsumerMetricsrecordsmessaging.receive.*and that would be the wrong metric for aprocessoperation. Let me know if you'd prefer the consumer metrics surfaced by default.Test plan
messaging.publish.duration(producer) andmessaging.receive.duration/messaging.receive.messages(receive, with receive telemetry enabled) are emitted with the expected attributes./gradlew spotlessApplyclean:instrumentation:kafka:...module tests pass