55
66package io .opentelemetry .instrumentation .api .incubator .semconv .messaging ;
77
8+ import static io .opentelemetry .instrumentation .api .internal .SemconvStability .emitOldMessagingSemconv ;
9+ import static io .opentelemetry .instrumentation .api .internal .SemconvStability .emitStableMessagingSemconv ;
10+ import static io .opentelemetry .semconv .ErrorAttributes .ERROR_TYPE ;
11+
812import io .opentelemetry .api .common .AttributeKey ;
913import io .opentelemetry .api .common .AttributesBuilder ;
1014import io .opentelemetry .context .Context ;
1721
1822/**
1923 * Extractor of <a
20- * href="https://github.com/open-telemetry/semantic-conventions/blob/main /docs/messaging/messaging-spans.md">messaging
24+ * href="https://github.com/open-telemetry/semantic-conventions/blob/v1.43.0 /docs/messaging/messaging-spans.md">messaging
2125 * attributes</a>.
2226 *
2327 * <p>This class delegates to a type-specific {@link MessagingAttributesGetter} for individual
@@ -29,8 +33,10 @@ public final class MessagingAttributesExtractor<REQUEST, RESPONSE>
2933 // copied from MessagingIncubatingAttributes
3034 private static final AttributeKey <Long > MESSAGING_BATCH_MESSAGE_COUNT =
3135 AttributeKey .longKey ("messaging.batch.message_count" );
32- private static final AttributeKey <String > MESSAGING_CLIENT_ID =
36+ private static final AttributeKey <String > MESSAGING_CLIENT_ID_OLD =
3337 AttributeKey .stringKey ("messaging.client_id" );
38+ private static final AttributeKey <String > MESSAGING_CLIENT_ID =
39+ AttributeKey .stringKey ("messaging.client.id" );
3440 private static final AttributeKey <Boolean > MESSAGING_DESTINATION_ANONYMOUS =
3541 AttributeKey .booleanKey ("messaging.destination.anonymous" );
3642 private static final AttributeKey <String > MESSAGING_DESTINATION_NAME =
@@ -51,64 +57,105 @@ public final class MessagingAttributesExtractor<REQUEST, RESPONSE>
5157 AttributeKey .stringKey ("messaging.message.id" );
5258 private static final AttributeKey <String > MESSAGING_OPERATION =
5359 AttributeKey .stringKey ("messaging.operation" );
60+ private static final AttributeKey <String > MESSAGING_OPERATION_NAME =
61+ AttributeKey .stringKey ("messaging.operation.name" );
62+ private static final AttributeKey <String > MESSAGING_OPERATION_TYPE =
63+ AttributeKey .stringKey ("messaging.operation.type" );
5464 private static final AttributeKey <String > MESSAGING_SYSTEM =
5565 AttributeKey .stringKey ("messaging.system" );
5666
5767 static final String TEMP_DESTINATION_NAME = "(temporary)" ;
5868
59- /**
60- * Creates the messaging attributes extractor for the given {@link MessageOperation operation}
61- * with default configuration.
62- */
69+ /** Creates the messaging attributes extractor for the given operation type. */
70+ public static <REQUEST , RESPONSE > AttributesExtractor <REQUEST , RESPONSE > createForOperationType (
71+ MessagingAttributesGetter <REQUEST , RESPONSE > getter ,
72+ @ Nullable MessagingOperationType operationType ) {
73+ return builderForOperationType (getter , operationType ).build ();
74+ }
75+
76+ /** Creates the messaging attributes extractor for the given operation. */
6377 public static <REQUEST , RESPONSE > AttributesExtractor <REQUEST , RESPONSE > create (
64- MessagingAttributesGetter <REQUEST , RESPONSE > getter , MessageOperation operation ) {
78+ MessagingAttributesGetter <REQUEST , RESPONSE > getter , @ Nullable MessageOperation operation ) {
6579 return builder (getter , operation ).build ();
6680 }
6781
6882 /**
69- * Returns a new {@link MessagingAttributesExtractorBuilder} for the given {@link MessageOperation
70- * operation} that can be used to configure the messaging attributes extractor .
83+ * Returns a new {@link MessagingAttributesExtractorBuilder} configured for the given operation
84+ * type .
7185 */
86+ public static <REQUEST , RESPONSE >
87+ MessagingAttributesExtractorBuilder <REQUEST , RESPONSE > builderForOperationType (
88+ MessagingAttributesGetter <REQUEST , RESPONSE > getter ,
89+ @ Nullable MessagingOperationType operationType ) {
90+ return new MessagingAttributesExtractorBuilder <>(getter , operationType , true );
91+ }
92+
93+ /** Returns a new messaging attributes extractor builder for the given operation. */
7294 public static <REQUEST , RESPONSE > MessagingAttributesExtractorBuilder <REQUEST , RESPONSE > builder (
73- MessagingAttributesGetter <REQUEST , RESPONSE > getter , MessageOperation operation ) {
74- return new MessagingAttributesExtractorBuilder <>(getter , operation );
95+ MessagingAttributesGetter <REQUEST , RESPONSE > getter , @ Nullable MessageOperation operation ) {
96+ return new MessagingAttributesExtractorBuilder <>(
97+ getter , operation == null ? null : operation .type (), false );
7598 }
7699
77100 private final MessagingAttributesGetter <REQUEST , RESPONSE > getter ;
78- private final MessageOperation operation ;
101+ @ Nullable private final MessagingOperationType operationType ;
102+ @ Nullable private final String operationName ;
103+ private final boolean supportsStableSemconv ;
79104 private final List <String > capturedHeaders ;
80105
81106 MessagingAttributesExtractor (
82107 MessagingAttributesGetter <REQUEST , RESPONSE > getter ,
83- MessageOperation operation ,
108+ @ Nullable MessagingOperationType operationType ,
109+ @ Nullable String operationName ,
110+ boolean supportsStableSemconv ,
84111 List <String > capturedHeaders ) {
85112 this .getter = getter ;
86- this .operation = operation ;
113+ this .operationType = operationType ;
114+ this .operationName = operationName ;
115+ this .supportsStableSemconv = supportsStableSemconv ;
87116 this .capturedHeaders = new ArrayList <>(capturedHeaders );
88117 }
89118
90119 @ Override
91120 public void onStart (AttributesBuilder attributes , Context parentContext , REQUEST request ) {
121+ boolean emitOldSemconv = !supportsStableSemconv || emitOldMessagingSemconv ();
122+ boolean emitStableSemconv = supportsStableSemconv && emitStableMessagingSemconv ();
92123 attributes .put (MESSAGING_SYSTEM , getter .getSystem (request ));
93124 boolean isTemporaryDestination = getter .isTemporaryDestination (request );
94125 if (isTemporaryDestination ) {
95126 attributes .put (MESSAGING_DESTINATION_TEMPORARY , true );
96- attributes .put (MESSAGING_DESTINATION_NAME , TEMP_DESTINATION_NAME );
127+ if (emitStableSemconv ) {
128+ attributes .put (MESSAGING_DESTINATION_NAME , getter .getDestination (request ));
129+ attributes .put (MESSAGING_DESTINATION_TEMPLATE , getter .getDestinationTemplate (request ));
130+ } else {
131+ attributes .put (MESSAGING_DESTINATION_NAME , TEMP_DESTINATION_NAME );
132+ }
97133 } else {
98134 attributes .put (MESSAGING_DESTINATION_NAME , getter .getDestination (request ));
99135 attributes .put (MESSAGING_DESTINATION_TEMPLATE , getter .getDestinationTemplate (request ));
100136 }
101137 attributes .put (MESSAGING_DESTINATION_PARTITION_ID , getter .getDestinationPartitionId (request ));
102138 boolean isAnonymousDestination = getter .isAnonymousDestination (request );
103- if (isAnonymousDestination ) {
139+ if (emitStableSemconv && isAnonymousDestination ) {
104140 attributes .put (MESSAGING_DESTINATION_ANONYMOUS , true );
105141 }
106142 attributes .put (MESSAGING_MESSAGE_CONVERSATION_ID , getter .getConversationId (request ));
107143 attributes .put (MESSAGING_MESSAGE_BODY_SIZE , getter .getMessageBodySize (request ));
108144 attributes .put (MESSAGING_MESSAGE_ENVELOPE_SIZE , getter .getMessageEnvelopeSize (request ));
109- attributes .put (MESSAGING_CLIENT_ID , getter .getClientId (request ));
110- if (operation != null ) {
111- attributes .put (MESSAGING_OPERATION , operation .operationName ());
145+ if (emitOldSemconv ) {
146+ attributes .put (MESSAGING_CLIENT_ID_OLD , getter .getClientId (request ));
147+ }
148+ if (emitStableSemconv ) {
149+ attributes .put (MESSAGING_CLIENT_ID , getter .getClientId (request ));
150+ }
151+ if (emitOldSemconv && operationType != null ) {
152+ attributes .put (MESSAGING_OPERATION , operationType .defaultOperationName ());
153+ }
154+ if (emitStableSemconv ) {
155+ attributes .put (MESSAGING_OPERATION_NAME , operationName );
156+ if (operationType != null ) {
157+ attributes .put (MESSAGING_OPERATION_TYPE , operationType .value ());
158+ }
112159 }
113160 }
114161
@@ -121,6 +168,13 @@ public void onEnd(
121168 @ Nullable Throwable error ) {
122169 attributes .put (MESSAGING_MESSAGE_ID , getter .getMessageId (request , response ));
123170 attributes .put (MESSAGING_BATCH_MESSAGE_COUNT , getter .getBatchMessageCount (request , response ));
171+ if (supportsStableSemconv && emitStableMessagingSemconv ()) {
172+ String errorType = getter .getErrorType (request , response , error );
173+ if (errorType == null && error != null ) {
174+ errorType = error .getClass ().getName ();
175+ }
176+ attributes .put (ERROR_TYPE , errorType );
177+ }
124178
125179 for (String name : capturedHeaders ) {
126180 List <String > values = getter .getMessageHeader (request , name );
@@ -137,17 +191,21 @@ public void onEnd(
137191 @ Override
138192 @ Nullable
139193 public SpanKey internalGetSpanKey () {
140- if (operation == null ) {
194+ if (operationType == null ) {
141195 return null ;
142196 }
143197
144- switch (operation ) {
145- case PUBLISH :
198+ switch (operationType ) {
199+ case CREATE :
200+ return SpanKey .PRODUCER_CREATE ;
201+ case SEND :
146202 return SpanKey .PRODUCER ;
147203 case RECEIVE :
148204 return SpanKey .CONSUMER_RECEIVE ;
149205 case PROCESS :
150206 return SpanKey .CONSUMER_PROCESS ;
207+ case SETTLE :
208+ return SpanKey .CONSUMER_SETTLE ;
151209 }
152210 throw new IllegalStateException ("Can't possibly happen" );
153211 }
0 commit comments