diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/internal/MessagingExceptionEventExtractors.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/internal/MessagingExceptionEventExtractors.java new file mode 100644 index 000000000000..75e96c7ac3df --- /dev/null +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/internal/MessagingExceptionEventExtractors.java @@ -0,0 +1,79 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal; + +import io.opentelemetry.api.logs.Severity; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; +import io.opentelemetry.instrumentation.api.internal.Experimental; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class MessagingExceptionEventExtractors { + + /** + * Configures the messaging create exception event name and severity. Only takes effect when + * emitting exceptions as logs is enabled via the {@code otel.semconv.exception.signal.preview} + * flag. + */ + public static void setMessagingCreateExceptionEventExtractor( + InstrumenterBuilder builder) { + setExceptionEventExtractor(builder, "messaging.create.exception", Severity.WARN); + } + + /** + * Configures the messaging send exception event name and severity. Only takes effect when + * emitting exceptions as logs is enabled via the {@code otel.semconv.exception.signal.preview} + * flag. + */ + public static void setMessagingSendExceptionEventExtractor( + InstrumenterBuilder builder) { + setExceptionEventExtractor(builder, "messaging.send.exception", Severity.WARN); + } + + /** + * Configures the messaging receive exception event name and severity. Only takes effect when + * emitting exceptions as logs is enabled via the {@code otel.semconv.exception.signal.preview} + * flag. + */ + public static void setMessagingReceiveExceptionEventExtractor( + InstrumenterBuilder builder) { + setExceptionEventExtractor(builder, "messaging.receive.exception", Severity.WARN); + } + + /** + * Configures the messaging settle exception event name and severity. Only takes effect when + * emitting exceptions as logs is enabled via the {@code otel.semconv.exception.signal.preview} + * flag. + */ + public static void setMessagingSettleExceptionEventExtractor( + InstrumenterBuilder builder) { + setExceptionEventExtractor(builder, "messaging.settle.exception", Severity.WARN); + } + + /** + * Configures the messaging process exception event name and severity. Only takes effect when + * emitting exceptions as logs is enabled via the {@code otel.semconv.exception.signal.preview} + * flag. + */ + public static void setMessagingProcessExceptionEventExtractor( + InstrumenterBuilder builder) { + setExceptionEventExtractor(builder, "messaging.process.exception", Severity.ERROR); + } + + private static void setExceptionEventExtractor( + InstrumenterBuilder builder, String eventName, Severity severity) { + Experimental.setExceptionEventExtractor( + builder, + (logRecordBuilder, context, request) -> { + logRecordBuilder.setEventName(eventName); + logRecordBuilder.setSeverity(severity); + }); + } + + private MessagingExceptionEventExtractors() {} +} diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/internal/MessagingExceptionEventExtractorsTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/internal/MessagingExceptionEventExtractorsTest.java new file mode 100644 index 000000000000..cdc87e665f80 --- /dev/null +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/internal/MessagingExceptionEventExtractorsTest.java @@ -0,0 +1,100 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal; + +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsLogs; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE; + +import io.opentelemetry.api.logs.Severity; +import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; +import io.opentelemetry.sdk.logs.data.LogRecordData; +import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension; +import java.util.List; +import java.util.function.Consumer; +import org.assertj.core.api.AbstractAssert; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +class MessagingExceptionEventExtractorsTest { + + @RegisterExtension + static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create(); + + @Test + void messagingCreateExceptionLog() { + assertExceptionLog( + MessagingExceptionEventExtractors::setMessagingCreateExceptionEventExtractor, + "messaging.create.exception", + Severity.WARN); + } + + @Test + void messagingSendExceptionLog() { + assertExceptionLog( + MessagingExceptionEventExtractors::setMessagingSendExceptionEventExtractor, + "messaging.send.exception", + Severity.WARN); + } + + @Test + void messagingReceiveExceptionLog() { + assertExceptionLog( + MessagingExceptionEventExtractors::setMessagingReceiveExceptionEventExtractor, + "messaging.receive.exception", + Severity.WARN); + } + + @Test + void messagingSettleExceptionLog() { + assertExceptionLog( + MessagingExceptionEventExtractors::setMessagingSettleExceptionEventExtractor, + "messaging.settle.exception", + Severity.WARN); + } + + @Test + void messagingProcessExceptionLog() { + assertExceptionLog( + MessagingExceptionEventExtractors::setMessagingProcessExceptionEventExtractor, + "messaging.process.exception", + Severity.ERROR); + } + + private static void assertExceptionLog( + Consumer> configure, + String expectedEventName, + Severity expectedSeverity) { + InstrumenterBuilder builder = + Instrumenter.builder(otelTesting.getOpenTelemetry(), "test", unused -> "span"); + configure.accept(builder); + Instrumenter instrumenter = builder.buildInstrumenter(); + + Context context = instrumenter.start(Context.root(), "request"); + IllegalStateException error = new IllegalStateException("test"); + instrumenter.end(context, "request", "response", error); + + List logs = otelTesting.getLogRecords(); + if (emitExceptionAsLogs()) { + assertThat(logs).hasSize(1); + assertThat(logs.get(0)) + .hasSeverity(expectedSeverity) + .hasEventName(expectedEventName) + .hasAttributesSatisfyingExactly( + equalTo(EXCEPTION_TYPE, "java.lang.IllegalStateException"), + equalTo(EXCEPTION_MESSAGE, "test"), + satisfies(EXCEPTION_STACKTRACE, AbstractAssert::isNotNull)); + } else { + assertThat(logs).isEmpty(); + } + } +} diff --git a/instrumentation/jms/jms-common-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/common/v1_1/JmsInstrumenterFactory.java b/instrumentation/jms/jms-common-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/common/v1_1/JmsInstrumenterFactory.java index cb20cbd09843..21cd1f4b198b 100644 --- a/instrumentation/jms/jms-common-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/common/v1_1/JmsInstrumenterFactory.java +++ b/instrumentation/jms/jms-common-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/common/v1_1/JmsInstrumenterFactory.java @@ -5,6 +5,9 @@ package io.opentelemetry.javaagent.instrumentation.jms.common.v1_1; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingProcessExceptionEventExtractor; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingReceiveExceptionEventExtractor; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingSendExceptionEventExtractor; import static java.util.Collections.emptyList; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -50,12 +53,14 @@ public Instrumenter createProducerInstrumenter() { JmsMessageAttributesGetter getter = new JmsMessageAttributesGetter(); MessageOperation operation = MessageOperation.PUBLISH; - return Instrumenter.builder( - openTelemetry, - instrumentationName, - MessagingSpanNameExtractor.create(getter, operation)) - .addAttributesExtractor(createMessagingAttributesExtractor(operation)) - .buildProducerInstrumenter(new MessagePropertySetter()); + InstrumenterBuilder builder = + Instrumenter.builder( + openTelemetry, + instrumentationName, + MessagingSpanNameExtractor.create(getter, operation)) + .addAttributesExtractor(createMessagingAttributesExtractor(operation)); + setMessagingSendExceptionEventExtractor(builder); + return builder.buildProducerInstrumenter(new MessagePropertySetter()); } public Instrumenter createConsumerReceiveInstrumenter() { @@ -68,6 +73,7 @@ public Instrumenter createConsumerReceiveInstrumen instrumentationName, MessagingSpanNameExtractor.create(getter, operation)) .addAttributesExtractor(createMessagingAttributesExtractor(operation)); + setMessagingReceiveExceptionEventExtractor(builder); if (messagingReceiveInstrumentationEnabled) { builder.addSpanLinksExtractor( new PropagatorBasedSpanLinksExtractor<>( @@ -88,6 +94,7 @@ public Instrumenter createConsumerProcessInstrumen instrumentationName, MessagingSpanNameExtractor.create(getter, operation)) .addAttributesExtractor(createMessagingAttributesExtractor(operation)); + setMessagingProcessExceptionEventExtractor(builder); if (canHaveReceiveInstrumentation && messagingReceiveInstrumentationEnabled) { builder.addSpanLinksExtractor( new PropagatorBasedSpanLinksExtractor<>( diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/build.gradle.kts b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/build.gradle.kts index 31d518aed909..05c370e0914d 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/build.gradle.kts +++ b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/build.gradle.kts @@ -17,11 +17,26 @@ dependencies { } tasks { - test { + withType().configureEach { usesService(gradle.sharedServices.registrations["testcontainersBuildService"].service) systemProperty("testLatestDeps", otelProps.testLatestDeps) systemProperty("collectMetadata", otelProps.collectMetadata) } + + val testExceptionSignalLogs by registering(Test::class) { + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + + filter { + includeTestsMatching("WrapperTest") + } + jvmArgs("-Dotel.semconv.exception.signal.preview=logs") + systemProperty("metadataConfig", "otel.semconv.exception.signal.preview=logs") + } + + check { + dependsOn(testExceptionSignalLogs) + } } // kafka 4.1 requires java 11 diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/test/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/WrapperTest.java b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/test/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/WrapperTest.java index f77656fb6bfe..c9f784651554 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/test/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/WrapperTest.java +++ b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/test/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/WrapperTest.java @@ -7,6 +7,9 @@ import static io.opentelemetry.api.common.AttributeKey.longKey; import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsLogs; +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsSpanEvents; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; import static io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes.MESSAGING_BATCH_MESSAGE_COUNT; @@ -25,6 +28,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import io.opentelemetry.api.logs.Severity; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.instrumentation.testing.junit.message.MessageHeaderUtil; @@ -169,10 +173,10 @@ void testConsumerError() { KafkaTelemetry telemetry = telemetryBuilder.build(); Consumer mockConsumer = mock(); - when(mockConsumer.poll(Duration.ofSeconds(10))).thenThrow(new IllegalStateException()); + IllegalStateException error = new IllegalStateException("test"); + when(mockConsumer.poll(Duration.ofSeconds(10))).thenThrow(error); Consumer wrappedConsumer = telemetry.wrap(mockConsumer); - assertThatThrownBy(() -> wrappedConsumer.poll(Duration.ofSeconds(10))) - .isInstanceOf(IllegalStateException.class); + assertThatThrownBy(() -> wrappedConsumer.poll(Duration.ofSeconds(10))).isSameAs(error); testing.waitAndAssertTraces( trace -> @@ -182,10 +186,20 @@ void testConsumerError() { .hasKind(SpanKind.CONSUMER) .hasNoParent() .hasStatus(StatusData.error()) - .hasException(new IllegalStateException()) + .hasException(emitExceptionAsSpanEvents() ? error : null) .hasAttributesSatisfyingExactly( equalTo(MESSAGING_SYSTEM, "kafka"), equalTo(MESSAGING_OPERATION, "receive"), equalTo(MESSAGING_BATCH_MESSAGE_COUNT, 0)))); + + if (emitExceptionAsLogs()) { + testing.waitAndAssertLogRecords( + logRecord -> + logRecord + .hasSeverity(Severity.WARN) + .hasEventName("messaging.receive.exception") + .hasException(error) + .hasTotalAttributeCount(3)); + } } } diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-common-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/common/v0_11/internal/KafkaInstrumenterFactory.java b/instrumentation/kafka/kafka-clients/kafka-clients-common-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/common/v0_11/internal/KafkaInstrumenterFactory.java index 7f2e88998da9..3a0654f4b34c 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-common-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/common/v0_11/internal/KafkaInstrumenterFactory.java +++ b/instrumentation/kafka/kafka-clients/kafka-clients-common-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/common/v0_11/internal/KafkaInstrumenterFactory.java @@ -5,6 +5,9 @@ package io.opentelemetry.instrumentation.kafkaclients.common.v0_11.internal; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingProcessExceptionEventExtractor; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingReceiveExceptionEventExtractor; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingSendExceptionEventExtractor; import static java.util.Collections.emptyList; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -91,6 +94,7 @@ public Instrumenter createProducerInstrume if (captureExperimentalSpanAttributes) { builder.addAttributesExtractor(new KafkaProducerExperimentalAttributesExtractor()); } + setMessagingSendExceptionEventExtractor(builder); return builder.buildInstrumenter(SpanKindExtractor.alwaysProducer()); } @@ -103,17 +107,19 @@ public Instrumenter createConsumerReceiveInstrumenter KafkaReceiveAttributesGetter getter = new KafkaReceiveAttributesGetter(); MessageOperation operation = MessageOperation.RECEIVE; - return Instrumenter.builder( - openTelemetry, - instrumentationName, - MessagingSpanNameExtractor.create(getter, operation)) - .addAttributesExtractor( - buildMessagingAttributesExtractor(getter, operation, capturedHeaders)) - .addAttributesExtractor(new KafkaReceiveAttributesExtractor()) - .addAttributesExtractors(extractors) - .setErrorCauseExtractor(errorCauseExtractor) - .setEnabled(messagingReceiveInstrumentationEnabled) - .buildInstrumenter(SpanKindExtractor.alwaysConsumer()); + InstrumenterBuilder builder = + Instrumenter.builder( + openTelemetry, + instrumentationName, + MessagingSpanNameExtractor.create(getter, operation)) + .addAttributesExtractor( + buildMessagingAttributesExtractor(getter, operation, capturedHeaders)) + .addAttributesExtractor(new KafkaReceiveAttributesExtractor()) + .addAttributesExtractors(extractors) + .setErrorCauseExtractor(errorCauseExtractor) + .setEnabled(messagingReceiveInstrumentationEnabled); + setMessagingReceiveExceptionEventExtractor(builder); + return builder.buildInstrumenter(SpanKindExtractor.alwaysConsumer()); } public Instrumenter createConsumerProcessInstrumenter() { @@ -138,6 +144,7 @@ public Instrumenter createConsumerProcessInstrumenter if (captureExperimentalSpanAttributes) { builder.addAttributesExtractor(new KafkaConsumerExperimentalAttributesExtractor()); } + setMessagingProcessExceptionEventExtractor(builder); if (messagingReceiveInstrumentationEnabled) { builder.addSpanLinksExtractor( @@ -154,18 +161,20 @@ public Instrumenter createBatchProcessInstrumenter() KafkaReceiveAttributesGetter getter = new KafkaReceiveAttributesGetter(); MessageOperation operation = MessageOperation.PROCESS; - return Instrumenter.builder( - openTelemetry, - instrumentationName, - MessagingSpanNameExtractor.create(getter, operation)) - .addAttributesExtractor( - buildMessagingAttributesExtractor(getter, operation, capturedHeaders)) - .addAttributesExtractor(new KafkaReceiveAttributesExtractor()) - .addSpanLinksExtractor( - new KafkaBatchProcessSpanLinksExtractor( - openTelemetry.getPropagators().getTextMapPropagator())) - .setErrorCauseExtractor(errorCauseExtractor) - .buildInstrumenter(SpanKindExtractor.alwaysConsumer()); + InstrumenterBuilder builder = + Instrumenter.builder( + openTelemetry, + instrumentationName, + MessagingSpanNameExtractor.create(getter, operation)) + .addAttributesExtractor( + buildMessagingAttributesExtractor(getter, operation, capturedHeaders)) + .addAttributesExtractor(new KafkaReceiveAttributesExtractor()) + .addSpanLinksExtractor( + new KafkaBatchProcessSpanLinksExtractor( + openTelemetry.getPropagators().getTextMapPropagator())) + .setErrorCauseExtractor(errorCauseExtractor); + setMessagingProcessExceptionEventExtractor(builder); + return builder.buildInstrumenter(SpanKindExtractor.alwaysConsumer()); } private static diff --git a/instrumentation/kafka/kafka-connect-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaconnect/v2_6/KafkaConnectSingletons.java b/instrumentation/kafka/kafka-connect-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaconnect/v2_6/KafkaConnectSingletons.java index 1d348e4b0b9e..21d1fa944a28 100644 --- a/instrumentation/kafka/kafka-connect-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaconnect/v2_6/KafkaConnectSingletons.java +++ b/instrumentation/kafka/kafka-connect-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaconnect/v2_6/KafkaConnectSingletons.java @@ -5,12 +5,15 @@ package io.opentelemetry.javaagent.instrumentation.kafkaconnect.v2_6; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingProcessExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.context.propagation.TextMapPropagator; import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessageOperation; import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessagingAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessagingSpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; public class KafkaConnectSingletons { @@ -25,7 +28,7 @@ public class KafkaConnectSingletons { KafkaConnectBatchProcessSpanLinksExtractor spanLinksExtractor = new KafkaConnectBatchProcessSpanLinksExtractor(propagator); - instrumenter = + InstrumenterBuilder builder = Instrumenter.builder( GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, @@ -35,8 +38,10 @@ public class KafkaConnectSingletons { MessagingAttributesExtractor.builder( new KafkaConnectAttributesGetter(), MessageOperation.PROCESS) .build()) - .addSpanLinksExtractor(spanLinksExtractor) - .buildInstrumenter(SpanKindExtractor.alwaysConsumer()); + .addSpanLinksExtractor(spanLinksExtractor); + setMessagingProcessExceptionEventExtractor(builder); + + instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysConsumer()); } public static Instrumenter instrumenter() { diff --git a/instrumentation/nats/nats-2.17/library/src/main/java/io/opentelemetry/instrumentation/nats/v2_17/internal/NatsInstrumenterFactory.java b/instrumentation/nats/nats-2.17/library/src/main/java/io/opentelemetry/instrumentation/nats/v2_17/internal/NatsInstrumenterFactory.java index 4037dd6c5e6b..3faa961994b5 100644 --- a/instrumentation/nats/nats-2.17/library/src/main/java/io/opentelemetry/instrumentation/nats/v2_17/internal/NatsInstrumenterFactory.java +++ b/instrumentation/nats/nats-2.17/library/src/main/java/io/opentelemetry/instrumentation/nats/v2_17/internal/NatsInstrumenterFactory.java @@ -5,6 +5,9 @@ package io.opentelemetry.instrumentation.nats.v2_17.internal; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingProcessExceptionEventExtractor; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingSendExceptionEventExtractor; + import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessageOperation; import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessagingAttributesExtractor; @@ -22,17 +25,19 @@ public final class NatsInstrumenterFactory { public static Instrumenter createProducerInstrumenter( OpenTelemetry openTelemetry, List capturedHeaders) { - return Instrumenter.builder( - openTelemetry, - INSTRUMENTATION_NAME, - MessagingSpanNameExtractor.create( - new NatsRequestMessagingAttributesGetter(), MessageOperation.PUBLISH)) - .addAttributesExtractor( - MessagingAttributesExtractor.builder( - new NatsRequestMessagingAttributesGetter(), MessageOperation.PUBLISH) - .setCapturedHeaders(capturedHeaders) - .build()) - .buildProducerInstrumenter(new NatsRequestTextMapSetter()); + InstrumenterBuilder builder = + Instrumenter.builder( + openTelemetry, + INSTRUMENTATION_NAME, + MessagingSpanNameExtractor.create( + new NatsRequestMessagingAttributesGetter(), MessageOperation.PUBLISH)) + .addAttributesExtractor( + MessagingAttributesExtractor.builder( + new NatsRequestMessagingAttributesGetter(), MessageOperation.PUBLISH) + .setCapturedHeaders(capturedHeaders) + .build()); + setMessagingSendExceptionEventExtractor(builder); + return builder.buildProducerInstrumenter(new NatsRequestTextMapSetter()); } public static Instrumenter createConsumerProcessInstrumenter( @@ -48,6 +53,7 @@ public static Instrumenter createConsumerProcessInstrumenter( new NatsRequestMessagingAttributesGetter(), MessageOperation.PROCESS) .setCapturedHeaders(capturedHeaders) .build()); + setMessagingProcessExceptionEventExtractor(builder); return builder.buildConsumerInstrumenter(new NatsRequestTextMapGetter()); } diff --git a/instrumentation/pulsar/pulsar-2.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pulsar/v2_8/telemetry/PulsarSingletons.java b/instrumentation/pulsar/pulsar-2.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pulsar/v2_8/telemetry/PulsarSingletons.java index 0a93492e2ac9..e3a9b50dc7c2 100644 --- a/instrumentation/pulsar/pulsar-2.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pulsar/v2_8/telemetry/PulsarSingletons.java +++ b/instrumentation/pulsar/pulsar-2.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pulsar/v2_8/telemetry/PulsarSingletons.java @@ -5,6 +5,10 @@ package io.opentelemetry.javaagent.instrumentation.pulsar.v2_8.telemetry; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingProcessExceptionEventExtractor; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingReceiveExceptionEventExtractor; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingSendExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.context.Context; @@ -77,6 +81,7 @@ private static Instrumenter createConsumerReceiveInstrument .addOperationMetrics(MessagingConsumerMetrics.get()) .addAttributesExtractor( ServerAttributesExtractor.create(new PulsarNetClientAttributesGetter())); + setMessagingReceiveExceptionEventExtractor(instrumenterBuilder); if (receiveInstrumentationEnabled) { return instrumenterBuilder @@ -91,17 +96,19 @@ private static Instrumenter createConsumerBatchReceive MessagingAttributesGetter getter = new PulsarBatchMessagingAttributesGetter(); - return Instrumenter.builder( - telemetry, - INSTRUMENTATION_NAME, - MessagingSpanNameExtractor.create(getter, MessageOperation.RECEIVE)) - .addAttributesExtractor( - createMessagingAttributesExtractor(getter, MessageOperation.RECEIVE)) - .addAttributesExtractor( - ServerAttributesExtractor.create(new PulsarNetClientAttributesGetter())) - .addSpanLinksExtractor(new PulsarBatchRequestSpanLinksExtractor(propagator)) - .addOperationMetrics(MessagingConsumerMetrics.get()) - .buildInstrumenter(SpanKindExtractor.alwaysConsumer()); + InstrumenterBuilder instrumenterBuilder = + Instrumenter.builder( + telemetry, + INSTRUMENTATION_NAME, + MessagingSpanNameExtractor.create(getter, MessageOperation.RECEIVE)) + .addAttributesExtractor( + createMessagingAttributesExtractor(getter, MessageOperation.RECEIVE)) + .addAttributesExtractor( + ServerAttributesExtractor.create(new PulsarNetClientAttributesGetter())) + .addSpanLinksExtractor(new PulsarBatchRequestSpanLinksExtractor(propagator)) + .addOperationMetrics(MessagingConsumerMetrics.get()); + setMessagingReceiveExceptionEventExtractor(instrumenterBuilder); + return instrumenterBuilder.buildInstrumenter(SpanKindExtractor.alwaysConsumer()); } private static Instrumenter createConsumerProcessInstrumenter() { @@ -114,6 +121,7 @@ private static Instrumenter createConsumerProcessInstrument MessagingSpanNameExtractor.create(getter, MessageOperation.PROCESS)) .addAttributesExtractor( createMessagingAttributesExtractor(getter, MessageOperation.PROCESS)); + setMessagingProcessExceptionEventExtractor(instrumenterBuilder); if (receiveInstrumentationEnabled) { SpanLinksExtractor spanLinksExtractor = @@ -142,6 +150,7 @@ private static Instrumenter createProducerInstrumenter() { .getBoolean("experimental_span_attributes/development", false)) { builder.addAttributesExtractor(new ExperimentalProducerAttributesExtractor()); } + setMessagingSendExceptionEventExtractor(builder); return builder.buildProducerInstrumenter(new MessageTextMapSetter()); } diff --git a/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/v2_7/RabbitSingletons.java b/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/v2_7/RabbitSingletons.java index dbd0e4c188ea..7664c4a358f4 100644 --- a/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/v2_7/RabbitSingletons.java +++ b/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/v2_7/RabbitSingletons.java @@ -7,6 +7,9 @@ import static io.opentelemetry.api.trace.SpanKind.CLIENT; import static io.opentelemetry.api.trace.SpanKind.PRODUCER; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingProcessExceptionEventExtractor; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingReceiveExceptionEventExtractor; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingSendExceptionEventExtractor; import com.rabbitmq.client.GetResponse; import io.opentelemetry.api.GlobalOpenTelemetry; @@ -16,6 +19,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessagingAttributesGetter; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.internal.PropagatorBasedSpanLinksExtractor; import io.opentelemetry.instrumentation.api.semconv.network.NetworkAttributesExtractor; @@ -54,17 +58,22 @@ static Instrumenter deliverInstrumenter() { } private static Instrumenter createChannelInstrumenter(boolean publish) { - return Instrumenter.builder( - GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, ChannelAndMethod::getMethod) - .addAttributesExtractor( - buildMessagingAttributesExtractor( - new RabbitChannelAttributesGetter(), publish ? MessageOperation.PUBLISH : null)) - .addAttributesExtractor( - NetworkAttributesExtractor.create(new RabbitChannelNetAttributesGetter())) - .addContextCustomizer( - (context, request, startAttributes) -> - context.with(CHANNEL_AND_METHOD_CONTEXT_KEY, new RabbitChannelAndMethodHolder())) - .buildInstrumenter(channelAndMethod -> publish ? PRODUCER : CLIENT); + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, ChannelAndMethod::getMethod) + .addAttributesExtractor( + buildMessagingAttributesExtractor( + new RabbitChannelAttributesGetter(), publish ? MessageOperation.PUBLISH : null)) + .addAttributesExtractor( + NetworkAttributesExtractor.create(new RabbitChannelNetAttributesGetter())) + .addContextCustomizer( + (context, request, startAttributes) -> + context.with( + CHANNEL_AND_METHOD_CONTEXT_KEY, new RabbitChannelAndMethodHolder())); + if (publish) { + setMessagingSendExceptionEventExtractor(builder); + } + return builder.buildInstrumenter(channelAndMethod -> publish ? PRODUCER : CLIENT); } private static Instrumenter createReceiveInstrumenter() { @@ -77,15 +86,17 @@ private static Instrumenter createReceiveInstrument extractors.add(new RabbitReceiveExperimentalAttributesExtractor()); } - return Instrumenter.builder( - GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, ReceiveRequest::spanName) - .addAttributesExtractors(extractors) - .setEnabled(ExperimentalConfig.get().messagingReceiveInstrumentationEnabled()) - .addSpanLinksExtractor( - new PropagatorBasedSpanLinksExtractor<>( - GlobalOpenTelemetry.getPropagators().getTextMapPropagator(), - new ReceiveRequestTextMapGetter())) - .buildInstrumenter(SpanKindExtractor.alwaysConsumer()); + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, ReceiveRequest::spanName) + .addAttributesExtractors(extractors) + .setEnabled(ExperimentalConfig.get().messagingReceiveInstrumentationEnabled()) + .addSpanLinksExtractor( + new PropagatorBasedSpanLinksExtractor<>( + GlobalOpenTelemetry.getPropagators().getTextMapPropagator(), + new ReceiveRequestTextMapGetter())); + setMessagingReceiveExceptionEventExtractor(builder); + return builder.buildInstrumenter(SpanKindExtractor.alwaysConsumer()); } private static Instrumenter createDeliverInstrumenter() { @@ -99,10 +110,12 @@ private static Instrumenter createDeliverInstrumenter() { extractors.add(new RabbitDeliveryExperimentalAttributesExtractor()); } - return Instrumenter.builder( - GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, DeliveryRequest::spanName) - .addAttributesExtractors(extractors) - .buildConsumerInstrumenter(new DeliveryRequestGetter()); + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, DeliveryRequest::spanName) + .addAttributesExtractors(extractors); + setMessagingProcessExceptionEventExtractor(builder); + return builder.buildConsumerInstrumenter(new DeliveryRequestGetter()); } private static AttributesExtractor buildMessagingAttributesExtractor( diff --git a/instrumentation/rocketmq/rocketmq-client-4.8/library/src/main/java/io/opentelemetry/instrumentation/rocketmqclient/v4_8/RocketMqInstrumenterFactory.java b/instrumentation/rocketmq/rocketmq-client-4.8/library/src/main/java/io/opentelemetry/instrumentation/rocketmqclient/v4_8/RocketMqInstrumenterFactory.java index ec5c425a0749..ef611cf66212 100644 --- a/instrumentation/rocketmq/rocketmq-client-4.8/library/src/main/java/io/opentelemetry/instrumentation/rocketmqclient/v4_8/RocketMqInstrumenterFactory.java +++ b/instrumentation/rocketmq/rocketmq-client-4.8/library/src/main/java/io/opentelemetry/instrumentation/rocketmqclient/v4_8/RocketMqInstrumenterFactory.java @@ -5,6 +5,8 @@ package io.opentelemetry.instrumentation.rocketmqclient.v4_8; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingProcessExceptionEventExtractor; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingSendExceptionEventExtractor; import static io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor.constant; import io.opentelemetry.api.OpenTelemetry; @@ -52,6 +54,7 @@ static Instrumenter createProducerInstrumenter( instrumenterBuilder.addAttributesExtractor( new RocketMqProducerExperimentalAttributeExtractor()); } + setMessagingSendExceptionEventExtractor(instrumenterBuilder); return instrumenterBuilder.buildProducerInstrumenter(new MapSetter()); } @@ -95,6 +98,7 @@ private static Instrumenter createProcessInstrumenter( if (captureExperimentalSpanAttributes) { builder.addAttributesExtractor(new RocketMqConsumerExperimentalAttributeExtractor()); } + setMessagingProcessExceptionEventExtractor(builder); if (batch) { SpanLinksExtractor spanLinksExtractor = diff --git a/instrumentation/rocketmq/rocketmq-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rocketmqclient/v5_0/RocketMqInstrumenterFactory.java b/instrumentation/rocketmq/rocketmq-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rocketmqclient/v5_0/RocketMqInstrumenterFactory.java index cd7edba46fc3..bb6ce5d1d276 100644 --- a/instrumentation/rocketmq/rocketmq-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rocketmqclient/v5_0/RocketMqInstrumenterFactory.java +++ b/instrumentation/rocketmq/rocketmq-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rocketmqclient/v5_0/RocketMqInstrumenterFactory.java @@ -5,6 +5,10 @@ package io.opentelemetry.javaagent.instrumentation.rocketmqclient.v5_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingProcessExceptionEventExtractor; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingReceiveExceptionEventExtractor; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingSendExceptionEventExtractor; + import apache.rocketmq.v2.ReceiveMessageRequest; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.StatusCode; @@ -45,6 +49,7 @@ public static Instrumenter createProduce MessagingSpanNameExtractor.create(getter, operation)) .addAttributesExtractor(attributesExtractor) .addAttributesExtractor(new RocketMqProducerAttributeExtractor()); + setMessagingSendExceptionEventExtractor(instrumenterBuilder); return instrumenterBuilder.buildProducerInstrumenter(new MessageMapSetter()); } @@ -65,6 +70,7 @@ public static Instrumenter createProduce .setEnabled(enabled) .addAttributesExtractor(attributesExtractor) .addAttributesExtractor(new RocketMqConsumerReceiveAttributeExtractor()); + setMessagingReceiveExceptionEventExtractor(instrumenterBuilder); return instrumenterBuilder.buildInstrumenter(SpanKindExtractor.alwaysConsumer()); } @@ -94,6 +100,7 @@ public static Instrumenter createConsumerProcessInst .extract(spanStatusBuilder, messageView, consumeResult, error); } }); + setMessagingProcessExceptionEventExtractor(instrumenterBuilder); if (receiveInstrumentationEnabled) { SpanLinksExtractor spanLinksExtractor = diff --git a/instrumentation/spring/spring-integration-4.1/library/src/main/java/io/opentelemetry/instrumentation/spring/integration/v4_1/SpringIntegrationTelemetryBuilder.java b/instrumentation/spring/spring-integration-4.1/library/src/main/java/io/opentelemetry/instrumentation/spring/integration/v4_1/SpringIntegrationTelemetryBuilder.java index e5ec2d41cb93..20dea3ca31f7 100644 --- a/instrumentation/spring/spring-integration-4.1/library/src/main/java/io/opentelemetry/instrumentation/spring/integration/v4_1/SpringIntegrationTelemetryBuilder.java +++ b/instrumentation/spring/spring-integration-4.1/library/src/main/java/io/opentelemetry/instrumentation/spring/integration/v4_1/SpringIntegrationTelemetryBuilder.java @@ -5,6 +5,8 @@ package io.opentelemetry.instrumentation.spring.integration.v4_1; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingProcessExceptionEventExtractor; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingSendExceptionEventExtractor; import static java.util.Collections.emptyList; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -15,6 +17,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessagingAttributesGetter; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import java.util.ArrayList; import java.util.Collection; @@ -72,7 +75,7 @@ public SpringIntegrationTelemetryBuilder setProducerSpanEnabled(boolean producer * SpringIntegrationTelemetryBuilder}. */ public SpringIntegrationTelemetry build() { - Instrumenter consumerInstrumenter = + InstrumenterBuilder consumerBuilder = Instrumenter.builder( openTelemetry, INSTRUMENTATION_NAME, @@ -82,10 +85,12 @@ public SpringIntegrationTelemetry build() { buildMessagingAttributesExtractor( new SpringMessagingAttributesGetter(), MessageOperation.PROCESS, - capturedHeaders)) - .buildConsumerInstrumenter(MessageHeadersGetter.INSTANCE); + capturedHeaders)); + setMessagingProcessExceptionEventExtractor(consumerBuilder); + Instrumenter consumerInstrumenter = + consumerBuilder.buildConsumerInstrumenter(MessageHeadersGetter.INSTANCE); - Instrumenter producerInstrumenter = + InstrumenterBuilder producerBuilder = Instrumenter.builder( openTelemetry, INSTRUMENTATION_NAME, @@ -95,8 +100,10 @@ public SpringIntegrationTelemetry build() { buildMessagingAttributesExtractor( new SpringMessagingAttributesGetter(), MessageOperation.PUBLISH, - capturedHeaders)) - .buildInstrumenter(SpanKindExtractor.alwaysProducer()); + capturedHeaders)); + setMessagingSendExceptionEventExtractor(producerBuilder); + Instrumenter producerInstrumenter = + producerBuilder.buildInstrumenter(SpanKindExtractor.alwaysProducer()); return new SpringIntegrationTelemetry( openTelemetry.getPropagators(), consumerInstrumenter, diff --git a/instrumentation/spring/spring-pulsar-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/pulsar/v1_0/SpringPulsarSingletons.java b/instrumentation/spring/spring-pulsar-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/pulsar/v1_0/SpringPulsarSingletons.java index 6edbb84a1a98..1f9db736d418 100644 --- a/instrumentation/spring/spring-pulsar-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/pulsar/v1_0/SpringPulsarSingletons.java +++ b/instrumentation/spring/spring-pulsar-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/pulsar/v1_0/SpringPulsarSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.spring.pulsar.v1_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingProcessExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessageOperation; @@ -37,6 +39,7 @@ public class SpringPulsarSingletons { MessagingAttributesExtractor.builder(getter, operation) .setCapturedHeaders(ExperimentalConfig.get().getMessagingHeaders()) .build()); + setMessagingProcessExceptionEventExtractor(builder); if (messagingReceiveInstrumentationEnabled) { builder.addSpanLinksExtractor( new PropagatorBasedSpanLinksExtractor<>( diff --git a/instrumentation/spring/spring-rabbit-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/rabbit/v1_0/SpringRabbitSingletons.java b/instrumentation/spring/spring-rabbit-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/rabbit/v1_0/SpringRabbitSingletons.java index 6abdf47f7348..0b1c73f8a742 100644 --- a/instrumentation/spring/spring-rabbit-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/rabbit/v1_0/SpringRabbitSingletons.java +++ b/instrumentation/spring/spring-rabbit-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/rabbit/v1_0/SpringRabbitSingletons.java @@ -5,11 +5,14 @@ package io.opentelemetry.javaagent.instrumentation.spring.rabbit.v1_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.messaging.internal.MessagingExceptionEventExtractors.setMessagingProcessExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessageOperation; import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessagingAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessagingSpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; import org.springframework.amqp.core.Message; @@ -23,7 +26,7 @@ public class SpringRabbitSingletons { SpringRabbitMessageAttributesGetter getter = new SpringRabbitMessageAttributesGetter(); MessageOperation operation = MessageOperation.PROCESS; - instrumenter = + InstrumenterBuilder builder = Instrumenter.builder( GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, @@ -31,8 +34,10 @@ public class SpringRabbitSingletons { .addAttributesExtractor( MessagingAttributesExtractor.builder(getter, operation) .setCapturedHeaders(ExperimentalConfig.get().getMessagingHeaders()) - .build()) - .buildConsumerInstrumenter(new MessageHeaderGetter()); + .build()); + setMessagingProcessExceptionEventExtractor(builder); + + instrumenter = builder.buildConsumerInstrumenter(new MessageHeaderGetter()); } public static Instrumenter instrumenter() {