diff --git a/instrumentation-api-incubator/build.gradle.kts b/instrumentation-api-incubator/build.gradle.kts index 707fd2217c1b..7d62bb2cede8 100644 --- a/instrumentation-api-incubator/build.gradle.kts +++ b/instrumentation-api-incubator/build.gradle.kts @@ -42,11 +42,11 @@ tasks { } val testStableSemconv by registering(Test::class) { - jvmArgs("-Dotel.semconv-stability.opt-in=database,code") + jvmArgs("-Dotel.semconv-stability.opt-in=database,code,messaging") } val testBothSemconv by registering(Test::class) { - jvmArgs("-Dotel.semconv-stability.opt-in=database/dup,code/dup") + jvmArgs("-Dotel.semconv-stability.opt-in=database/dup,code/dup,messaging/dup") } check { diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessageOperation.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessageOperation.java index e7ef5c479ed0..cdbb2227da66 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessageOperation.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessageOperation.java @@ -9,20 +9,37 @@ /** * Represents type of operations + * href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/messaging/messaging-spans.md#operation-types">operations * that may be used in a messaging system. */ public enum MessageOperation { + @Deprecated PUBLISH, + RECEIVE, - PROCESS; + PROCESS, + CREATE, + SEND, + SETTLE; /** * Returns the operation name as defined in the * specification. + * + * @deprecated Use {@link #operationType} instead. */ + @Deprecated String operationName() { return name().toLowerCase(Locale.ROOT); } + + /** + * Returns the operation type as defined in the + * specification. + */ + String operationType() { + return name().toLowerCase(Locale.ROOT); + } } diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingAttributesExtractor.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingAttributesExtractor.java index bdf5ab879786..b8ca526ff2cc 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingAttributesExtractor.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingAttributesExtractor.java @@ -11,6 +11,7 @@ import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import io.opentelemetry.instrumentation.api.internal.SemconvStability; import io.opentelemetry.instrumentation.api.internal.SpanKey; import io.opentelemetry.instrumentation.api.internal.SpanKeyProvider; import java.util.List; @@ -27,35 +28,54 @@ public final class MessagingAttributesExtractor implements AttributesExtractor, SpanKeyProvider { - // copied from MessagingIncubatingAttributes + // copied from io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes (stable + // attributes) + private static final AttributeKey MESSAGING_OPERATION_NAME = + AttributeKey.stringKey("messaging.operation.name"); + private static final AttributeKey MESSAGING_SYSTEM = + AttributeKey.stringKey("messaging.system"); private static final AttributeKey MESSAGING_BATCH_MESSAGE_COUNT = AttributeKey.longKey("messaging.batch.message_count"); - private static final AttributeKey MESSAGING_CLIENT_ID = - AttributeKey.stringKey("messaging.client_id"); + // Messaging specific + private static final AttributeKey MESSAGING_CONSUMER_GROUP_NAME = + AttributeKey.stringKey("messaging.consumer.group.name"); private static final AttributeKey MESSAGING_DESTINATION_ANONYMOUS = AttributeKey.booleanKey("messaging.destination.anonymous"); private static final AttributeKey MESSAGING_DESTINATION_NAME = AttributeKey.stringKey("messaging.destination.name"); - private static final AttributeKey MESSAGING_DESTINATION_PARTITION_ID = - AttributeKey.stringKey("messaging.destination.partition.id"); + // Messaging specific + private static final AttributeKey MESSAGING_DESTINATION_SUBSCRIPTION_NAME = + AttributeKey.stringKey("messaging.destination.subscription.name"); private static final AttributeKey MESSAGING_DESTINATION_TEMPLATE = AttributeKey.stringKey("messaging.destination.template"); private static final AttributeKey MESSAGING_DESTINATION_TEMPORARY = AttributeKey.booleanKey("messaging.destination.temporary"); - private static final AttributeKey MESSAGING_MESSAGE_BODY_SIZE = - AttributeKey.longKey("messaging.message.body.size"); + private static final AttributeKey MESSAGING_OPERATION_TYPE = + AttributeKey.stringKey("messaging.operation.type"); + private static final AttributeKey MESSAGING_CLIENT_ID_STABLE = + AttributeKey.stringKey("messaging.client.id"); + private static final AttributeKey MESSAGING_DESTINATION_PARTITION_ID = + AttributeKey.stringKey("messaging.destination.partition.id"); private static final AttributeKey MESSAGING_MESSAGE_CONVERSATION_ID = AttributeKey.stringKey("messaging.message.conversation_id"); - private static final AttributeKey MESSAGING_MESSAGE_ENVELOPE_SIZE = - AttributeKey.longKey("messaging.message.envelope.size"); private static final AttributeKey MESSAGING_MESSAGE_ID = AttributeKey.stringKey("messaging.message.id"); + private static final AttributeKey MESSAGING_MESSAGE_BODY_SIZE = + AttributeKey.longKey("messaging.message.body.size"); + private static final AttributeKey MESSAGING_MESSAGE_ENVELOPE_SIZE = + AttributeKey.longKey("messaging.message.envelope.size"); + + // copied from MessagingIncubatingAttributes (old attributes) + @Deprecated + private static final AttributeKey MESSAGING_CLIENT_ID = + AttributeKey.stringKey("messaging.client_id"); + + @Deprecated private static final AttributeKey MESSAGING_OPERATION = AttributeKey.stringKey("messaging.operation"); - private static final AttributeKey MESSAGING_SYSTEM = - AttributeKey.stringKey("messaging.system"); static final String TEMP_DESTINATION_NAME = "(temporary)"; + static final String ANONYMOUS_DESTINATION_NAME = "(anonymous)"; /** * Creates the messaging attributes extractor for the given {@link MessageOperation operation} @@ -89,31 +109,60 @@ public static MessagingAttributesExtractorBuilder { - @Nullable String getSystem(REQUEST request); @Nullable - String getDestination(REQUEST request); + default Long getBatchMessageCount(REQUEST request, @Nullable RESPONSE response) { + return null; + } @Nullable - String getDestinationTemplate(REQUEST request); - - boolean isTemporaryDestination(REQUEST request); + default String getConsumerGroupName(REQUEST request) { + return null; + } boolean isAnonymousDestination(REQUEST request); @Nullable - String getConversationId(REQUEST request); + String getDestination(REQUEST request); @Nullable - @Deprecated - default Long getMessagePayloadSize(REQUEST request) { + default String getDestinationSubscriptionName(REQUEST request) { return null; } @Nullable - @Deprecated - default Long getMessagePayloadCompressedSize(REQUEST request) { + default String getDestinationTemplate(REQUEST request) { return null; } + boolean isTemporaryDestination(REQUEST request); + @Nullable - Long getMessageBodySize(REQUEST request); + default String getOperationName(REQUEST request, MessageOperation operation) { + return operation.operationType(); + } @Nullable - Long getMessageEnvelopeSize(REQUEST request); + String getClientId(REQUEST request); + + @Nullable + default String getDestinationPartitionId(REQUEST request) { + return null; + } + + @Nullable + default String getConversationId(REQUEST request) { + return null; + } @Nullable String getMessageId(REQUEST request, @Nullable RESPONSE response); @Nullable - String getClientId(REQUEST request); + Long getMessageBodySize(REQUEST request); @Nullable - Long getBatchMessageCount(REQUEST request, @Nullable RESPONSE response); + Long getMessageEnvelopeSize(REQUEST request); @Nullable - default String getDestinationPartitionId(REQUEST request) { + @Deprecated + default Long getMessagePayloadSize(REQUEST request) { + return null; + } + + @Nullable + @Deprecated + default Long getMessagePayloadCompressedSize(REQUEST request) { return null; } diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingSpanNameExtractor.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingSpanNameExtractor.java index 624d3b8e00bf..8362710bcd3b 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingSpanNameExtractor.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingSpanNameExtractor.java @@ -6,13 +6,16 @@ package io.opentelemetry.instrumentation.api.incubator.semconv.messaging; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.internal.SemconvStability; +import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesGetter; +import javax.annotation.Nullable; public final class MessagingSpanNameExtractor implements SpanNameExtractor { /** * Returns a {@link SpanNameExtractor} that constructs the span name according to - * messaging semantic conventions: {@code }. + * messaging semantic conventions: {@code }. * * @see MessagingAttributesGetter#getDestination(Object) used to extract {@code }. @@ -20,20 +23,50 @@ public final class MessagingSpanNameExtractor implements SpanNameExtrac */ public static SpanNameExtractor create( MessagingAttributesGetter getter, MessageOperation operation) { - return new MessagingSpanNameExtractor<>(getter, operation); + return new MessagingSpanNameExtractor<>(getter, operation, null); + } + + /** + * Returns a {@link SpanNameExtractor} that constructs the span name according to + * messaging semantic conventions: {@code }. + * + * @see MessagingAttributesGetter#getDestination(Object) used to extract {@code } + * and {@code }. + * @see MessageOperation used to extract {@code } (backwards compatibility with + * old conventions). + * @see ServerAttributesGetter used to extract data for {@code } + */ + public static SpanNameExtractor create( + MessagingAttributesGetter getter, + MessageOperation operation, + ServerAttributesGetter serverAttributesGetter) { + return new MessagingSpanNameExtractor<>(getter, operation, serverAttributesGetter); } private final MessagingAttributesGetter getter; + private final ServerAttributesGetter serverAttributesGetter; private final MessageOperation operation; private MessagingSpanNameExtractor( - MessagingAttributesGetter getter, MessageOperation operation) { + MessagingAttributesGetter getter, + MessageOperation operation, + @Nullable ServerAttributesGetter serverAttributesGetter) { this.getter = getter; + this.serverAttributesGetter = serverAttributesGetter; this.operation = operation; } @Override + @SuppressWarnings("deprecation") // using deprecated semconv public String extract(REQUEST request) { + if (SemconvStability.emitStableMessagingSemconv()) { + String destination = getDestination(request); + if (destination == null) { + return getter.getOperationName(request, this.operation); + } + return getter.getOperationName(request, this.operation) + " " + destination; + } String destinationName = getter.isTemporaryDestination(request) ? MessagingAttributesExtractor.TEMP_DESTINATION_NAME @@ -44,4 +77,28 @@ public String extract(REQUEST request) { return destinationName + " " + operation.operationName(); } + + @Nullable + private String getDestination(REQUEST request) { + String destination = null; + if (getter.getDestinationTemplate(request) != null) { + destination = getter.getDestinationTemplate(request); + } else if (getter.isTemporaryDestination(request)) { + destination = MessagingAttributesExtractor.TEMP_DESTINATION_NAME; + } else if (getter.isAnonymousDestination(request)) { + destination = MessagingAttributesExtractor.ANONYMOUS_DESTINATION_NAME; + } else if (getter.getDestination(request) != null) { + destination = getter.getDestination(request); + } else { + if (serverAttributesGetter != null + && serverAttributesGetter.getServerAddress(request) != null + && serverAttributesGetter.getServerPort(request) != null) { + destination = + serverAttributesGetter.getServerAddress(request) + + ":" + + serverAttributesGetter.getServerPort(request); + } + } + return destination; + } } diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/package-info.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/package-info.java new file mode 100644 index 000000000000..eb5bdf29b745 --- /dev/null +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/package-info.java @@ -0,0 +1,4 @@ +@ParametersAreNonnullByDefault +package io.opentelemetry.instrumentation.api.incubator.semconv.messaging; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingAttributesExtractorTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingAttributesExtractorTest.java index b395fe4a053e..a83025b1fe16 100644 --- a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingAttributesExtractorTest.java +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingAttributesExtractorTest.java @@ -13,6 +13,7 @@ import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import io.opentelemetry.instrumentation.api.internal.SemconvStability; import io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes; import java.util.ArrayList; import java.util.Collections; @@ -43,7 +44,7 @@ void shouldExtractAllAvailableAttributes( request.put("system", "myQueue"); request.put("destinationKind", "topic"); request.put("destination", destination); - request.put("destinationTemplate", destination); + request.put("destinationTemplate", destination + "-template"); if (temporary) { request.put("temporaryDestination", "y"); } @@ -56,6 +57,7 @@ void shouldExtractAllAvailableAttributes( request.put("envelopeSize", "120"); request.put("clientId", "43"); request.put("batchMessageCount", "2"); + request.put("operationName", "ack"); AttributesExtractor, String> underTest = MessagingAttributesExtractor.create(TestGetter.INSTANCE, operation); @@ -79,19 +81,31 @@ void shouldExtractAllAvailableAttributes( entry(MessagingIncubatingAttributes.MESSAGING_DESTINATION_TEMPORARY, true)); } else { expectedEntries.add( - entry(MessagingIncubatingAttributes.MESSAGING_DESTINATION_TEMPLATE, expectedDestination)); + entry( + MessagingIncubatingAttributes.MESSAGING_DESTINATION_TEMPLATE, + destination + "-template")); } if (anonymous) { expectedEntries.add( entry(MessagingIncubatingAttributes.MESSAGING_DESTINATION_ANONYMOUS, true)); } + + if (SemconvStability.emitOldMessagingSemconv()) { + expectedEntries.add(entry(AttributeKey.stringKey("messaging.client_id"), "43")); + expectedEntries.add( + entry(MessagingIncubatingAttributes.MESSAGING_OPERATION, operation.operationName())); + } + if (SemconvStability.emitStableMessagingSemconv()) { + expectedEntries.add(entry(MessagingIncubatingAttributes.MESSAGING_CLIENT_ID, "43")); + expectedEntries.add( + entry(MessagingIncubatingAttributes.MESSAGING_OPERATION_TYPE, operation.operationType())); + expectedEntries.add(entry(MessagingIncubatingAttributes.MESSAGING_OPERATION_NAME, "ack")); + } + expectedEntries.add( entry(MessagingIncubatingAttributes.MESSAGING_MESSAGE_CONVERSATION_ID, "42")); expectedEntries.add(entry(MessagingIncubatingAttributes.MESSAGING_MESSAGE_BODY_SIZE, 100L)); expectedEntries.add(entry(MessagingIncubatingAttributes.MESSAGING_MESSAGE_ENVELOPE_SIZE, 120L)); - expectedEntries.add(entry(AttributeKey.stringKey("messaging.client_id"), "43")); - expectedEntries.add( - entry(MessagingIncubatingAttributes.MESSAGING_OPERATION, operation.operationName())); @SuppressWarnings({"unchecked", "rawtypes"}) MapEntry, ?>[] expectedEntriesArr = @@ -107,14 +121,17 @@ void shouldExtractAllAvailableAttributes( static Stream destinations() { return Stream.of( Arguments.of(false, false, "destination", MessageOperation.RECEIVE, "destination"), - Arguments.of(true, true, null, MessageOperation.PROCESS, "(temporary)")); + Arguments.of(true, false, "destination", MessageOperation.PROCESS, "(temporary)"), + Arguments.of(false, true, "destination", MessageOperation.PROCESS, "(anonymous)"), + Arguments.of(true, true, "destination", MessageOperation.PROCESS, "(temporary)")); } @Test + @SuppressWarnings("deprecation") // using deprecated semconv void shouldExtractNoAttributesIfNoneAreAvailable() { // given AttributesExtractor, String> underTest = - MessagingAttributesExtractor.create(TestGetter.INSTANCE, null); + MessagingAttributesExtractor.create(TestGetter.INSTANCE, MessageOperation.CREATE); Context context = Context.root(); @@ -126,8 +143,25 @@ void shouldExtractNoAttributesIfNoneAreAvailable() { underTest.onEnd(endAttributes, context, Collections.emptyMap(), null, null); // then - assertThat(startAttributes.build().isEmpty()).isTrue(); + List, Object>> expectedEntries = new ArrayList<>(); + if (SemconvStability.emitOldMessagingSemconv()) { + expectedEntries.add( + entry( + MessagingIncubatingAttributes.MESSAGING_OPERATION, + MessageOperation.CREATE.operationName())); + } + if (SemconvStability.emitStableMessagingSemconv()) { + expectedEntries.add( + entry( + MessagingIncubatingAttributes.MESSAGING_OPERATION_TYPE, + MessageOperation.CREATE.operationType())); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + MapEntry, ?>[] expectedEntriesArr = + expectedEntries.toArray(new MapEntry[0]); + assertThat(startAttributes.build()).containsOnly(expectedEntriesArr); assertThat(endAttributes.build().isEmpty()).isTrue(); } @@ -196,5 +230,11 @@ public Long getBatchMessageCount(Map request, @Nullable String r String payloadSize = request.get("batchMessageCount"); return payloadSize == null ? null : Long.valueOf(payloadSize); } + + @Nullable + @Override + public String getOperationName(Map request, MessageOperation operation) { + return request.get("operationName"); + } } } diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingSpanNameExtractorTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingSpanNameExtractorTest.java index c5f8d6b70c30..6657b161ce34 100644 --- a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingSpanNameExtractorTest.java +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingSpanNameExtractorTest.java @@ -9,6 +9,8 @@ import static org.mockito.Mockito.when; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.internal.SemconvStability; +import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesGetter; import java.util.stream.Stream; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -20,25 +22,44 @@ @ExtendWith(MockitoExtension.class) class MessagingSpanNameExtractorTest { - @Mock MessagingAttributesGetter getter; + // This test is executed in 2 modes with old and new semantic conventions + // Due to that some methods are not invoked that ofter + // Mockito can complain about that in strict mode, Lenient mode helps to run both modes + @Mock(strictness = Mock.Strictness.LENIENT) + MessagingAttributesGetter getter; + + @Mock(strictness = Mock.Strictness.LENIENT) + ServerAttributesGetter serverAttributesGetter; @ParameterizedTest @MethodSource("spanNameParams") void shouldExtractSpanName( boolean isTemporaryQueue, + boolean isAnonymous, String destinationName, + String destinationTemplate, MessageOperation operation, String expectedSpanName) { // given Message message = new Message(); + when(getter.getDestinationTemplate(message)).thenReturn(destinationTemplate); + if (isAnonymous) { + when(getter.isAnonymousDestination(message)).thenReturn(true); + } + if (isTemporaryQueue) { when(getter.isTemporaryDestination(message)).thenReturn(true); } else { when(getter.getDestination(message)).thenReturn(destinationName); } + when(getter.getOperationName(message, operation)).thenReturn(operation.operationType()); - SpanNameExtractor underTest = MessagingSpanNameExtractor.create(getter, operation); + when(serverAttributesGetter.getServerPort(message)).thenReturn(1234); + when(serverAttributesGetter.getServerAddress(message)).thenReturn("127.0.0.1"); + + SpanNameExtractor underTest = + MessagingSpanNameExtractor.create(getter, operation, serverAttributesGetter); // when String spanName = underTest.extract(message); @@ -47,11 +68,43 @@ void shouldExtractSpanName( assertEquals(expectedSpanName, spanName); } + @SuppressWarnings("deprecation") // using deprecated semconv static Stream spanNameParams() { + if (SemconvStability.emitStableMessagingSemconv()) { + return Stream.of( + Arguments.of( + false, + false, + "destination/1", + "destination/{}", + MessageOperation.PUBLISH, + "publish destination/{}"), + Arguments.of( + false, + false, + "destination/1", + null, + MessageOperation.PUBLISH, + "publish destination/1"), + Arguments.of(true, false, null, "temp", MessageOperation.PROCESS, "process temp"), + Arguments.of(true, false, null, null, MessageOperation.PROCESS, "process (temporary)"), + Arguments.of(false, true, null, "anon", MessageOperation.PROCESS, "process anon"), + Arguments.of(false, true, null, null, MessageOperation.PROCESS, "process (anonymous)"), + Arguments.of(true, true, null, null, MessageOperation.PROCESS, "process (temporary)"), + Arguments.of( + false, false, null, null, MessageOperation.RECEIVE, "receive 127.0.0.1:1234")); + } return Stream.of( - Arguments.of(false, "destination", MessageOperation.PUBLISH, "destination publish"), - Arguments.of(true, null, MessageOperation.PROCESS, "(temporary) process"), - Arguments.of(false, null, MessageOperation.RECEIVE, "unknown receive")); + Arguments.of( + false, + false, + "destination", + "not used", + MessageOperation.PUBLISH, + "destination publish"), + Arguments.of( + true, false, null, "not used", MessageOperation.PROCESS, "(temporary) process"), + Arguments.of(false, false, null, "not used", MessageOperation.RECEIVE, "unknown receive")); } static class Message {} diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/SemconvStability.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/SemconvStability.java index e54a62530b67..4e8f5e6e47a3 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/SemconvStability.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/SemconvStability.java @@ -20,6 +20,8 @@ public final class SemconvStability { private static final boolean emitOldDatabaseSemconv; private static final boolean emitStableDatabaseSemconv; + private static final boolean emitOldMessagingSemconv; + private static final boolean emitStableMessagingSemconv; private static final boolean emitOldCodeSemconv; private static final boolean emitStableCodeSemconv; @@ -28,6 +30,9 @@ public final class SemconvStability { boolean oldDatabase = true; boolean stableDatabase = false; + boolean oldMessaging = true; + boolean stableMessaging = false; + boolean oldCode = true; boolean stableCode = false; @@ -46,7 +51,14 @@ public final class SemconvStability { oldDatabase = true; stableDatabase = true; } - + if (values.contains("messaging")) { + oldMessaging = false; + stableMessaging = true; + } + if (values.contains("messaging/dup")) { + oldMessaging = true; + stableMessaging = true; + } if (values.contains("code")) { oldCode = false; stableCode = true; @@ -60,6 +72,9 @@ public final class SemconvStability { emitOldDatabaseSemconv = oldDatabase; emitStableDatabaseSemconv = stableDatabase; + emitOldMessagingSemconv = oldMessaging; + emitStableMessagingSemconv = stableMessaging; + emitOldCodeSemconv = oldCode; emitStableCodeSemconv = stableCode; } @@ -72,6 +87,14 @@ public static boolean emitStableDatabaseSemconv() { return emitStableDatabaseSemconv; } + public static boolean emitOldMessagingSemconv() { + return emitOldMessagingSemconv; + } + + public static boolean emitStableMessagingSemconv() { + return emitStableMessagingSemconv; + } + private static final Map dbSystemNameMap = new HashMap<>(); static { diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/SpanKey.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/SpanKey.java index 0cf43cc6162a..c0716182ff23 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/SpanKey.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/SpanKey.java @@ -49,6 +49,8 @@ public final class SpanKey { ContextKey.named("opentelemetry-traces-span-key-consumer-receive"); private static final ContextKey CONSUMER_PROCESS_KEY = ContextKey.named("opentelemetry-traces-span-key-consumer-process"); + private static final ContextKey CONSUMER_SETTLE_KEY = + ContextKey.named("opentelemetry-traces-span-key-consumer-settle"); /* Span keys */ @@ -69,6 +71,7 @@ public final class SpanKey { public static final SpanKey PRODUCER = new SpanKey(PRODUCER_KEY); public static final SpanKey CONSUMER_RECEIVE = new SpanKey(CONSUMER_RECEIVE_KEY); public static final SpanKey CONSUMER_PROCESS = new SpanKey(CONSUMER_PROCESS_KEY); + public static final SpanKey CONSUMER_SETTLE = new SpanKey(CONSUMER_SETTLE_KEY); private final ContextKey key; diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsSdkInstrumenterFactory.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsSdkInstrumenterFactory.java index eb90b4488d63..fb1dbccdcd1c 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsSdkInstrumenterFactory.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsSdkInstrumenterFactory.java @@ -5,6 +5,7 @@ package io.opentelemetry.instrumentation.awssdk.v1_11; +import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableMessagingSemconv; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; @@ -25,6 +26,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.internal.SemconvStability; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; import java.util.ArrayList; import java.util.Arrays; @@ -117,7 +119,7 @@ Instrumenter> consumerReceiveInstrumenter() { SpanKindExtractor.alwaysConsumer(), toSqsRequestExtractors(attributesExtractors()), singletonList(messagingAttributeExtractor), - messagingReceiveInstrumentationEnabled); + messagingReceiveInstrumentationEnabled || SemconvStability.emitStableMessagingSemconv()); } Instrumenter> consumerProcessInstrumenter() { @@ -134,7 +136,7 @@ Instrumenter> consumerProcessInstrumenter() { .addAttributesExtractors(toSqsRequestExtractors(attributesExtractors())) .addAttributesExtractor(messagingAttributeExtractor); - if (messagingReceiveInstrumentationEnabled) { + if (messagingReceiveInstrumentationEnabled || SemconvStability.emitStableMessagingSemconv()) { builder.addSpanLinksExtractor( (spanLinks, parentContext, request) -> { Context extracted = @@ -173,8 +175,11 @@ public void onEnd( return result; } + @SuppressWarnings("deprecation") // using deprecated semconv Instrumenter, Response> producerInstrumenter() { - MessageOperation operation = MessageOperation.PUBLISH; + MessageOperation operation = + emitStableMessagingSemconv() ? MessageOperation.SEND : MessageOperation.PUBLISH; + SqsAttributesGetter getter = SqsAttributesGetter.INSTANCE; AttributesExtractor, Response> messagingAttributeExtractor = messagingAttributesExtractor(getter, operation); diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkInstrumenterFactory.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkInstrumenterFactory.java index b6e8cb44c867..b0feb8033203 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkInstrumenterFactory.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkInstrumenterFactory.java @@ -5,6 +5,7 @@ package io.opentelemetry.instrumentation.awssdk.v2_2.internal; +import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableMessagingSemconv; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; @@ -28,6 +29,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.internal.SemconvStability; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; import java.util.ArrayList; import java.util.Arrays; @@ -140,7 +142,7 @@ public Instrumenter consumerReceiveInstrumenter() { SpanKindExtractor.alwaysConsumer(), toSqsRequestExtractors(consumerAttributesExtractors()), singletonList(messagingAttributeExtractor), - messagingReceiveInstrumentationEnabled); + messagingReceiveInstrumentationEnabled || SemconvStability.emitStableMessagingSemconv()); } public Instrumenter consumerProcessInstrumenter() { @@ -155,7 +157,7 @@ public Instrumenter consumerProcessInstrumenter() { .addAttributesExtractors(toSqsRequestExtractors(consumerAttributesExtractors())) .addAttributesExtractor(messagingAttributesExtractor(getter, operation)); - if (messagingReceiveInstrumentationEnabled) { + if (messagingReceiveInstrumentationEnabled || SemconvStability.emitStableMessagingSemconv()) { builder.addSpanLinksExtractor( (spanLinks, parentContext, request) -> { Context extracted = @@ -195,8 +197,10 @@ public void onEnd( return result; } + @SuppressWarnings("deprecation") // using deprecated semconv public Instrumenter producerInstrumenter() { - MessageOperation operation = MessageOperation.PUBLISH; + MessageOperation operation = + emitStableMessagingSemconv() ? MessageOperation.SEND : MessageOperation.PUBLISH; SqsAttributesGetter getter = SqsAttributesGetter.INSTANCE; AttributesExtractor messagingAttributeExtractor = messagingAttributesExtractor(getter, operation); diff --git a/instrumentation/jms/jms-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/v1_1/JmsSingletons.java b/instrumentation/jms/jms-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/v1_1/JmsSingletons.java index d68de50afb9c..abac5dcdec0a 100644 --- a/instrumentation/jms/jms-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/v1_1/JmsSingletons.java +++ b/instrumentation/jms/jms-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/v1_1/JmsSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.jms.v1_1; +import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableMessagingSemconv; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; @@ -27,7 +29,8 @@ public final class JmsSingletons { PRODUCER_INSTRUMENTER = factory.createProducerInstrumenter(); CONSUMER_RECEIVE_INSTRUMENTER = factory.createConsumerReceiveInstrumenter(); - CONSUMER_PROCESS_INSTRUMENTER = factory.createConsumerProcessInstrumenter(false); + CONSUMER_PROCESS_INSTRUMENTER = + factory.createConsumerProcessInstrumenter(emitStableMessagingSemconv()); } public static Instrumenter producerInstrumenter() { diff --git a/instrumentation/jms/jms-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/v3_0/JmsSingletons.java b/instrumentation/jms/jms-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/v3_0/JmsSingletons.java index d5595e75899f..481e0c28b9f2 100644 --- a/instrumentation/jms/jms-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/v3_0/JmsSingletons.java +++ b/instrumentation/jms/jms-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/v3_0/JmsSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.jms.v3_0; +import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableMessagingSemconv; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; @@ -27,7 +29,8 @@ public final class JmsSingletons { PRODUCER_INSTRUMENTER = factory.createProducerInstrumenter(); CONSUMER_RECEIVE_INSTRUMENTER = factory.createConsumerReceiveInstrumenter(); - CONSUMER_PROCESS_INSTRUMENTER = factory.createConsumerProcessInstrumenter(false); + CONSUMER_PROCESS_INSTRUMENTER = + factory.createConsumerProcessInstrumenter(emitStableMessagingSemconv()); } public static Instrumenter producerInstrumenter() { diff --git a/instrumentation/jms/jms-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsInstrumenterFactory.java b/instrumentation/jms/jms-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsInstrumenterFactory.java index 31b80691c75d..6015107e3a3c 100644 --- a/instrumentation/jms/jms-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsInstrumenterFactory.java +++ b/instrumentation/jms/jms-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsInstrumenterFactory.java @@ -5,6 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.jms; +import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableMessagingSemconv; import static java.util.Collections.emptyList; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -46,9 +47,11 @@ public JmsInstrumenterFactory setMessagingReceiveInstrumentationEnabled( return this; } + @SuppressWarnings("deprecation") // using deprecated semconv public Instrumenter createProducerInstrumenter() { JmsMessageAttributesGetter getter = JmsMessageAttributesGetter.INSTANCE; - MessageOperation operation = MessageOperation.PUBLISH; + MessageOperation operation = + emitStableMessagingSemconv() ? MessageOperation.SEND : MessageOperation.PUBLISH; return Instrumenter.builder( openTelemetry, @@ -68,7 +71,7 @@ public Instrumenter createConsumerReceiveInstrumen instrumentationName, MessagingSpanNameExtractor.create(getter, operation)) .addAttributesExtractor(createMessagingAttributesExtractor(operation)); - if (messagingReceiveInstrumentationEnabled) { + if (messagingReceiveInstrumentationEnabled || emitStableMessagingSemconv()) { builder.addSpanLinksExtractor( new PropagatorBasedSpanLinksExtractor<>( openTelemetry.getPropagators().getTextMapPropagator(), @@ -88,7 +91,8 @@ public Instrumenter createConsumerProcessInstrumen instrumentationName, MessagingSpanNameExtractor.create(getter, operation)) .addAttributesExtractor(createMessagingAttributesExtractor(operation)); - if (canHaveReceiveInstrumentation && messagingReceiveInstrumentationEnabled) { + if (canHaveReceiveInstrumentation + && (messagingReceiveInstrumentationEnabled || emitStableMessagingSemconv())) { builder.addSpanLinksExtractor( new PropagatorBasedSpanLinksExtractor<>( openTelemetry.getPropagators().getTextMapPropagator(), diff --git a/instrumentation/jms/jms-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsReceiveSpanUtil.java b/instrumentation/jms/jms-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsReceiveSpanUtil.java index be0bbd88b243..a46c806367a9 100644 --- a/instrumentation/jms/jms-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsReceiveSpanUtil.java +++ b/instrumentation/jms/jms-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsReceiveSpanUtil.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.jms; +import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableMessagingSemconv; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.context.Context; import io.opentelemetry.context.propagation.ContextPropagators; @@ -26,7 +28,8 @@ public static void createReceiveSpan( Throwable throwable) { Context parentContext = Context.current(); // if receive instrumentation is not enabled we'll use the producer as parent - if (!receiveInstrumentationEnabled) { + // according to the stable convertions the production should only be linked not as parent + if (!receiveInstrumentationEnabled && !emitStableMessagingSemconv()) { parentContext = propagators .getTextMapPropagator() 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 989c2bd3ffe6..d0be6c4f7b99 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,7 @@ package io.opentelemetry.instrumentation.kafkaclients.common.v0_11.internal; +import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableMessagingSemconv; import static java.util.Collections.emptyList; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -73,6 +74,7 @@ public Instrumenter createProducerInstrume return createProducerInstrumenter(Collections.emptyList()); } + @SuppressWarnings("deprecation") // using deprecated semconv public Instrumenter createProducerInstrumenter( Iterable> extractors) { @@ -109,7 +111,7 @@ public Instrumenter createConsumerReceiveInstrumenter .addAttributesExtractor(KafkaReceiveAttributesExtractor.INSTANCE) .addAttributesExtractors(extractors) .setErrorCauseExtractor(errorCauseExtractor) - .setEnabled(messagingReceiveInstrumentationEnabled) + .setEnabled(messagingReceiveInstrumentationEnabled || emitStableMessagingSemconv()) .buildInstrumenter(SpanKindExtractor.alwaysConsumer()); } @@ -136,7 +138,7 @@ public Instrumenter createConsumerProcessInstrumenter builder.addAttributesExtractor(new KafkaConsumerExperimentalAttributesExtractor()); } - if (messagingReceiveInstrumentationEnabled) { + if (messagingReceiveInstrumentationEnabled || emitStableMessagingSemconv()) { builder.addSpanLinksExtractor( new PropagatorBasedSpanLinksExtractor<>( openTelemetry.getPropagators().getTextMapPropagator(), diff --git a/instrumentation/opentelemetry-instrumentation-api/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/testing/AgentSpanTestingInstrumenter.java b/instrumentation/opentelemetry-instrumentation-api/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/testing/AgentSpanTestingInstrumenter.java index 188f736a929f..cd6446f26087 100644 --- a/instrumentation/opentelemetry-instrumentation-api/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/testing/AgentSpanTestingInstrumenter.java +++ b/instrumentation/opentelemetry-instrumentation-api/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/testing/AgentSpanTestingInstrumenter.java @@ -75,6 +75,7 @@ private static SpanKey[] getAllSpanKeys() { SpanKey.PRODUCER, SpanKey.CONSUMER_RECEIVE, SpanKey.CONSUMER_PROCESS, + SpanKey.CONSUMER_SETTLE, }; } 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 c26022efea02..294a2d0ad5cb 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,8 @@ package io.opentelemetry.javaagent.instrumentation.pulsar.v2_8.telemetry; +import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableMessagingSemconv; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.context.Context; @@ -67,8 +69,7 @@ public static Instrumenter producerInstrumenter() { } private static Instrumenter createConsumerReceiveInstrumenter() { - MessagingAttributesGetter getter = - PulsarMessagingAttributesGetter.INSTANCE; + PulsarMessagingAttributesGetter getter = PulsarMessagingAttributesGetter.INSTANCE; InstrumenterBuilder instrumenterBuilder = Instrumenter.builder( @@ -81,7 +82,7 @@ private static Instrumenter createConsumerReceiveInstrument .addAttributesExtractor( ServerAttributesExtractor.create(new PulsarNetClientAttributesGetter())); - if (receiveInstrumentationEnabled) { + if (receiveInstrumentationEnabled || emitStableMessagingSemconv()) { return instrumenterBuilder .addSpanLinksExtractor( new PropagatorBasedSpanLinksExtractor<>(PROPAGATOR, MessageTextMapGetter.INSTANCE)) @@ -91,8 +92,7 @@ private static Instrumenter createConsumerReceiveInstrument } private static Instrumenter createConsumerBatchReceiveInstrumenter() { - MessagingAttributesGetter getter = - PulsarBatchMessagingAttributesGetter.INSTANCE; + PulsarBatchMessagingAttributesGetter getter = PulsarBatchMessagingAttributesGetter.INSTANCE; return Instrumenter.builder( TELEMETRY, @@ -108,8 +108,7 @@ private static Instrumenter createConsumerBatchReceive } private static Instrumenter createConsumerProcessInstrumenter() { - MessagingAttributesGetter getter = - PulsarMessagingAttributesGetter.INSTANCE; + PulsarMessagingAttributesGetter getter = PulsarMessagingAttributesGetter.INSTANCE; InstrumenterBuilder instrumenterBuilder = Instrumenter.builder( @@ -119,7 +118,7 @@ private static Instrumenter createConsumerProcessInstrument .addAttributesExtractor( createMessagingAttributesExtractor(getter, MessageOperation.PROCESS)); - if (receiveInstrumentationEnabled) { + if (receiveInstrumentationEnabled || emitStableMessagingSemconv()) { SpanLinksExtractor spanLinksExtractor = new PropagatorBasedSpanLinksExtractor<>(PROPAGATOR, MessageTextMapGetter.INSTANCE); instrumenterBuilder.addSpanLinksExtractor(spanLinksExtractor); @@ -128,17 +127,18 @@ private static Instrumenter createConsumerProcessInstrument return instrumenterBuilder.buildConsumerInstrumenter(MessageTextMapGetter.INSTANCE); } + @SuppressWarnings("deprecation") // using deprecated semconv private static Instrumenter createProducerInstrumenter() { - MessagingAttributesGetter getter = - PulsarMessagingAttributesGetter.INSTANCE; + PulsarMessagingAttributesGetter getter = PulsarMessagingAttributesGetter.INSTANCE; + MessageOperation operation = + emitStableMessagingSemconv() ? MessageOperation.SEND : MessageOperation.PUBLISH; InstrumenterBuilder builder = Instrumenter.builder( TELEMETRY, INSTRUMENTATION_NAME, - MessagingSpanNameExtractor.create(getter, MessageOperation.PUBLISH)) - .addAttributesExtractor( - createMessagingAttributesExtractor(getter, MessageOperation.PUBLISH)) + MessagingSpanNameExtractor.create(getter, operation)) + .addAttributesExtractor(createMessagingAttributesExtractor(getter, operation)) .addAttributesExtractor( ServerAttributesExtractor.create(new PulsarNetClientAttributesGetter())) .addOperationMetrics(MessagingProducerMetrics.get()); @@ -168,7 +168,7 @@ public static Context startAndEndConsumerReceive( if (!CONSUMER_RECEIVE_INSTRUMENTER.shouldStart(parent, request)) { return null; } - if (!receiveInstrumentationEnabled) { + if (!(receiveInstrumentationEnabled || emitStableMessagingSemconv())) { // suppress receive span when receive telemetry is not enabled and message is going to be // processed by a listener if (MessageListenerContext.isProcessing()) { @@ -238,7 +238,9 @@ public static CompletableFuture> wrap( // we create a "receive" span when receive telemetry is enabled or when we know that // this message will not be passed to a listener that would create the "process" span Context context = - receiveInstrumentationEnabled || !listenerContextActive + receiveInstrumentationEnabled + || emitStableMessagingSemconv() + || !listenerContextActive ? startAndEndConsumerReceive(parent, message, timer, consumer, throwable) : parent; runWithContext( diff --git a/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitSingletons.java b/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitSingletons.java index c8af3a8784d6..35ab3fc29180 100644 --- a/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitSingletons.java +++ b/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitSingletons.java @@ -56,6 +56,7 @@ static Instrumenter deliverInstrumenter() { return deliverInstrumenter; } + @SuppressWarnings("deprecation") // using deprecated semconv private static Instrumenter createChannelInstrumenter(boolean publish) { return Instrumenter.builder( GlobalOpenTelemetry.get(), instrumentationName, ChannelAndMethod::getMethod) diff --git a/instrumentation/rocketmq/rocketmq-client/rocketmq-client-4.8/library/src/main/java/io/opentelemetry/instrumentation/rocketmqclient/v4_8/RocketMqInstrumenterFactory.java b/instrumentation/rocketmq/rocketmq-client/rocketmq-client-4.8/library/src/main/java/io/opentelemetry/instrumentation/rocketmqclient/v4_8/RocketMqInstrumenterFactory.java index f01f9b3ead35..0560a651d611 100644 --- a/instrumentation/rocketmq/rocketmq-client/rocketmq-client-4.8/library/src/main/java/io/opentelemetry/instrumentation/rocketmqclient/v4_8/RocketMqInstrumenterFactory.java +++ b/instrumentation/rocketmq/rocketmq-client/rocketmq-client-4.8/library/src/main/java/io/opentelemetry/instrumentation/rocketmqclient/v4_8/RocketMqInstrumenterFactory.java @@ -6,6 +6,7 @@ package io.opentelemetry.instrumentation.rocketmqclient.v4_8; import static io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor.constant; +import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableMessagingSemconv; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.AttributeKey; @@ -33,13 +34,15 @@ class RocketMqInstrumenterFactory { private static final AttributeKey MESSAGING_SYSTEM = AttributeKey.stringKey("messaging.system"); + @SuppressWarnings("deprecation") // using deprecated semconv static Instrumenter createProducerInstrumenter( OpenTelemetry openTelemetry, List capturedHeaders, boolean captureExperimentalSpanAttributes) { RocketMqProducerAttributeGetter getter = RocketMqProducerAttributeGetter.INSTANCE; - MessageOperation operation = MessageOperation.PUBLISH; + MessageOperation operation = + emitStableMessagingSemconv() ? MessageOperation.CREATE : MessageOperation.PUBLISH; InstrumenterBuilder instrumenterBuilder = Instrumenter.builder( diff --git a/instrumentation/rocketmq/rocketmq-client/rocketmq-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rocketmqclient/v5_0/RocketMqInstrumenterFactory.java b/instrumentation/rocketmq/rocketmq-client/rocketmq-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rocketmqclient/v5_0/RocketMqInstrumenterFactory.java index 5164fc1dbeaa..04c3f8c32c80 100644 --- a/instrumentation/rocketmq/rocketmq-client/rocketmq-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rocketmqclient/v5_0/RocketMqInstrumenterFactory.java +++ b/instrumentation/rocketmq/rocketmq-client/rocketmq-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rocketmqclient/v5_0/RocketMqInstrumenterFactory.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.rocketmqclient.v5_0; +import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableMessagingSemconv; + import apache.rocketmq.v2.ReceiveMessageRequest; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.StatusCode; @@ -30,10 +32,13 @@ final class RocketMqInstrumenterFactory { private RocketMqInstrumenterFactory() {} + @SuppressWarnings("deprecation") // using deprecated semconv public static Instrumenter createProducerInstrumenter( OpenTelemetry openTelemetry, List capturedHeaders) { RocketMqProducerAttributeGetter getter = RocketMqProducerAttributeGetter.INSTANCE; - MessageOperation operation = MessageOperation.PUBLISH; + MessageOperation operation = + emitStableMessagingSemconv() ? MessageOperation.CREATE : MessageOperation.PUBLISH; + ; AttributesExtractor attributesExtractor = buildMessagingAttributesExtractor(getter, operation, capturedHeaders); 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 035385fa20cb..87642db73261 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,7 @@ package io.opentelemetry.instrumentation.spring.integration.v4_1; +import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableMessagingSemconv; import static java.util.Collections.emptyList; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -79,6 +80,7 @@ private static String producerSpanName(MessageWithChannel messageWithChannel) { * Returns a new {@link SpringIntegrationTelemetry} with the settings of this {@link * SpringIntegrationTelemetryBuilder}. */ + @SuppressWarnings("deprecation") // using deprecated semconv public SpringIntegrationTelemetry build() { Instrumenter consumerInstrumenter = Instrumenter.builder( @@ -102,7 +104,9 @@ public SpringIntegrationTelemetry build() { .addAttributesExtractor( buildMessagingAttributesExtractor( SpringMessagingAttributesGetter.INSTANCE, - MessageOperation.PUBLISH, + emitStableMessagingSemconv() + ? MessageOperation.CREATE + : MessageOperation.PUBLISH, capturedHeaders)) .buildInstrumenter(SpanKindExtractor.alwaysProducer()); return new SpringIntegrationTelemetry(