diff --git a/sdk/ai/azure-ai-inference/src/test/java/com/azure/ai/inference/ChatCompletionClientTracerTest.java b/sdk/ai/azure-ai-inference/src/test/java/com/azure/ai/inference/ChatCompletionClientTracerTest.java index 5fb8784b2a5e..db43bfa45196 100644 --- a/sdk/ai/azure-ai-inference/src/test/java/com/azure/ai/inference/ChatCompletionClientTracerTest.java +++ b/sdk/ai/azure-ai-inference/src/test/java/com/azure/ai/inference/ChatCompletionClientTracerTest.java @@ -60,6 +60,8 @@ public final class ChatCompletionClientTracerTest { private static final String AZ_NAMESPACE_NAME = "Microsoft.CognitiveServices"; private static final AttributeKey AZ_NAMESPACE = AttributeKey.stringKey("az.namespace"); + private static final AttributeKey AZURE_RESOURCE_PROVIDER_NAMESPACE + = AttributeKey.stringKey("azure.resource_provider.namespace"); private static final AttributeKey GEN_AI_SYSTEM = AttributeKey.stringKey("gen_ai.system"); private static final AttributeKey GEN_AI_OPERATION_NAME = AttributeKey.stringKey("gen_ai.operation.name"); private static final AttributeKey GEN_AI_REQUEST_TOP_P = AttributeKey.doubleKey("gen_ai.request.top_p"); @@ -181,6 +183,7 @@ static ReadableSpan getChatSpan(List spans, ChatCompletionsOptions static void assertChatSpanRequestAttributes(Attributes chatAttributes, ChatCompletionsOptions completionRequest) { assertEquals(AZ_NAMESPACE_NAME, chatAttributes.get(AZ_NAMESPACE)); + assertEquals(AZ_NAMESPACE_NAME, chatAttributes.get(AZURE_RESOURCE_PROVIDER_NAMESPACE)); assertEquals(INFERENCE_GEN_AI_SYSTEM_NAME, chatAttributes.get(GEN_AI_SYSTEM)); assertEquals(GEN_AI_CHAT_OPERATION_NAME, chatAttributes.get(GEN_AI_OPERATION_NAME)); final String modelId = completionRequest.getModel(); diff --git a/sdk/core/azure-core-tracing-opentelemetry/CHANGELOG.md b/sdk/core/azure-core-tracing-opentelemetry/CHANGELOG.md index 0f63536bbae6..75c68d828f2d 100644 --- a/sdk/core/azure-core-tracing-opentelemetry/CHANGELOG.md +++ b/sdk/core/azure-core-tracing-opentelemetry/CHANGELOG.md @@ -8,6 +8,12 @@ ### Bugs Fixed +- Added additional attributes according to OpenTelemetry semantic conventions changes: + - `az.namespace` -> `azure.resource_provider.namespace` + - `az.service_request_id` -> `azure.service.request.id` + These attributes are added in addition to the existing ones and will be reported together for now to allow users to + transition to the new attribute names. The old attributes will be removed in a future release. + ### Other Changes ## 1.0.0-beta.62 (2026-01-15) diff --git a/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryTracer.java b/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryTracer.java index 6514c7ae9cf6..e37a71511c6b 100644 --- a/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryTracer.java +++ b/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryTracer.java @@ -12,6 +12,7 @@ import com.azure.core.util.tracing.TracingLink; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.SpanContext; @@ -31,7 +32,7 @@ import java.util.function.BiConsumer; import java.util.function.Function; -import static java.util.Collections.singletonMap; +import static com.azure.core.tracing.opentelemetry.OpenTelemetryUtils.addAttribute; /** * Basic tracing implementation class for use with REST and AMQP Service Clients to create {@link Span} and in-process @@ -51,6 +52,7 @@ public class OpenTelemetryTracer implements com.azure.core.util.tracing.Tracer { private static final String SUPPRESSED_SPAN_FLAG = "suppressed-span-flag"; private static final String CLIENT_METHOD_CALL_FLAG = "client-method-call-flag"; private static final String AZ_TRACING_NAMESPACE_KEY = "az.namespace"; + private static final String AZURE_RESOURCE_PROVIDER_NAMESPACE = "azure.resource_provider.namespace"; private final Tracer tracer; private final boolean isEnabled; @@ -142,7 +144,7 @@ public Context start(String spanName, StartSpanOptions options, Context context) context = context.addData(CLIENT_METHOD_CALL_FLAG, true); } - io.opentelemetry.context.Context traceContext = getTraceContextOrDefault(context, null); + io.opentelemetry.context.Context traceContext = getTraceContextOrNull(context); SpanBuilder spanBuilder = createSpanBuilder(spanName, options, traceContext); @@ -152,9 +154,9 @@ public Context start(String spanName, StartSpanOptions options, Context context) String tracingNamespace = getAzNamespace(context); if (tracingNamespace != null) { - Attributes attributes - = OpenTelemetryUtils.convert(singletonMap(AZ_TRACING_NAMESPACE_KEY, tracingNamespace)); - spanBuilder.setAllAttributes(attributes); + AttributesBuilder builder = Attributes.builder(); + addAttribute(builder, AZ_TRACING_NAMESPACE_KEY, tracingNamespace); + spanBuilder.setAllAttributes(builder.build()); } Span span = spanBuilder.startSpan(); @@ -224,7 +226,7 @@ private SpanBuilder createSpanBuilder(String spanName, StartSpanOptions options, */ @Override public void injectContext(BiConsumer headerSetter, Context context) { - io.opentelemetry.context.Context otelContext = getTraceContextOrDefault(context, null); + io.opentelemetry.context.Context otelContext = getTraceContextOrNull(context); if (otelContext != null) { TRACE_CONTEXT_FORMAT.inject(otelContext, null, (ignored, key, value) -> headerSetter.accept(key, value)); } @@ -246,7 +248,7 @@ public void setAttribute(String key, long value, Context context) { } if (span.isRecording()) { - OpenTelemetryUtils.addAttribute(span, key, value); + addAttribute(span, key, value); } } @@ -272,7 +274,7 @@ public void setAttribute(String key, String value, Context context) { } if (span.isRecording()) { - OpenTelemetryUtils.addAttribute(span, key, value); + addAttribute(span, key, value); } } @@ -294,7 +296,7 @@ public void setAttribute(String key, Object value, Context context) { } if (span.isRecording()) { - OpenTelemetryUtils.addAttribute(span, key, value); + addAttribute(span, key, value); } } @@ -383,7 +385,7 @@ public AutoCloseable makeSpanCurrent(Context context) { return NOOP_CLOSEABLE; } - io.opentelemetry.context.Context traceContext = getTraceContextOrDefault(context, null); + io.opentelemetry.context.Context traceContext = getTraceContextOrNull(context); if (traceContext == null) { return NOOP_CLOSEABLE; } @@ -447,11 +449,10 @@ private static T getOrNull(Context context, String key, Class clazz) { * Returns OpenTelemetry trace context from given com.azure.core.Context under PARENT_TRACE_CONTEXT_KEY * or default value. */ - private static io.opentelemetry.context.Context getTraceContextOrDefault(Context azContext, - io.opentelemetry.context.Context defaultContext) { + private static io.opentelemetry.context.Context getTraceContextOrNull(Context azContext) { final Object data = azContext.getData(PARENT_TRACE_CONTEXT_KEY).orElse(null); if (data == null) { - return defaultContext; + return null; } if (data instanceof io.opentelemetry.context.Context) { @@ -474,7 +475,7 @@ private static io.opentelemetry.context.Context getTraceContextOrDefault(Context } } - return defaultContext; + return null; } /** @@ -485,7 +486,7 @@ private Span getSpanOrNull(Context azContext) { return null; } - io.opentelemetry.context.Context traceContext = getTraceContextOrDefault(azContext, null); + io.opentelemetry.context.Context traceContext = getTraceContextOrNull(azContext); return traceContext == null ? null : Span.fromContext(traceContext); } diff --git a/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryUtils.java b/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryUtils.java index 077d80eca2a5..3003d8c4f016 100644 --- a/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryUtils.java +++ b/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryUtils.java @@ -12,6 +12,7 @@ import java.util.Map; import java.util.Objects; +import java.util.function.Consumer; import static com.azure.core.tracing.opentelemetry.ExceptionUtils.unwrapError; import static com.azure.core.util.tracing.Tracer.ENTITY_PATH_KEY; @@ -21,6 +22,7 @@ class OpenTelemetryUtils { private static final ClientLogger LOGGER = new ClientLogger(OpenTelemetryUtils.class); static final String SERVICE_REQUEST_ID_ATTRIBUTE = "serviceRequestId"; + static final String AZ_SERVICE_REQUEST_ID_ATTRIBUTE = "az.service_request_id"; static final String CLIENT_REQUEST_ID_ATTRIBUTE = "requestId"; static final AttributeKey ERROR_TYPE_ATTRIBUTE = AttributeKey.stringKey("error.type"); @@ -35,36 +37,35 @@ public static Attributes convert(Map attributeMap) { continue; } - addAttribute(builder, mapAttributeName(kvp.getKey()), kvp.getValue()); + addAttribute(builder, kvp.getKey(), kvp.getValue()); } return builder.build(); } - private static String mapAttributeName(String name) { + private static void mapKeyAndConsume(String key, Consumer mappedKey) { // TODO (limolkova) remove all these mappings prior to plugin stability - if ("http.method".equals(name)) { - return "http.request.method"; - } - if ("http.status_code".equals(name)) { - return "http.response.status_code"; - } - if ("http.url".equals(name)) { - return "url.full"; - } - if (ENTITY_PATH_KEY.equals(name)) { - return "messaging.destination.name"; - } - if (HOST_NAME_KEY.equals(name)) { - return "server.address"; - } - if (CLIENT_REQUEST_ID_ATTRIBUTE.equals(name)) { - return "az.client_request_id"; - } - if (SERVICE_REQUEST_ID_ATTRIBUTE.equals(name)) { - return "az.service_request_id"; + if ("http.method".equals(key)) { + mappedKey.accept("http.request.method"); + } else if ("http.status_code".equals(key)) { + mappedKey.accept("http.response.status_code"); + } else if ("http.url".equals(key)) { + mappedKey.accept("url.full"); + } else if (ENTITY_PATH_KEY.equals(key)) { + mappedKey.accept("messaging.destination.name"); + } else if (HOST_NAME_KEY.equals(key)) { + mappedKey.accept("server.address"); + } else if (CLIENT_REQUEST_ID_ATTRIBUTE.equals(key)) { + mappedKey.accept("az.client_request_id"); + } else if (SERVICE_REQUEST_ID_ATTRIBUTE.equals(key) || AZ_SERVICE_REQUEST_ID_ATTRIBUTE.equals(key)) { + mappedKey.accept("az.service_request_id"); + mappedKey.accept("azure.service.request.id"); + } else if ("az.namespace".equals(key)) { + mappedKey.accept("az.namespace"); + mappedKey.accept("azure.resource_provider.namespace"); + } else { + mappedKey.accept(key); } - return name; } /** @@ -75,24 +76,28 @@ private static String mapAttributeName(String name) { * @param key key of the attribute to be added * @param value value of the attribute to be added */ - private static void addAttribute(AttributesBuilder attributesBuilder, String key, Object value) { + static void addAttribute(AttributesBuilder attributesBuilder, String key, Object value) { Objects.requireNonNull(key, "OpenTelemetry attribute name cannot be null."); if (value instanceof String) { - attributesBuilder.put(AttributeKey.stringKey(key), (String) value); + mapKeyAndConsume(key, + mappedKey -> attributesBuilder.put(AttributeKey.stringKey(mappedKey), (String) value)); } else if (value instanceof Long) { - attributesBuilder.put(AttributeKey.longKey(key), (Long) value); + mapKeyAndConsume(key, mappedKey -> attributesBuilder.put(AttributeKey.longKey(mappedKey), (Long) value)); } else if (value instanceof Integer) { - attributesBuilder.put(AttributeKey.longKey(key), (Integer) value); + mapKeyAndConsume(key, mappedKey -> attributesBuilder.put(AttributeKey.longKey(mappedKey), (Integer) value)); } else if (value instanceof Boolean) { - attributesBuilder.put(AttributeKey.booleanKey(key), (Boolean) value); + mapKeyAndConsume(key, + mappedKey -> attributesBuilder.put(AttributeKey.booleanKey(mappedKey), (Boolean) value)); } else if (value instanceof Double) { - attributesBuilder.put(AttributeKey.doubleKey(key), (Double) value); + mapKeyAndConsume(key, + mappedKey -> attributesBuilder.put(AttributeKey.doubleKey(mappedKey), (Double) value)); } else if (value instanceof Float) { - attributesBuilder.put(AttributeKey.doubleKey(key), ((Float) value).doubleValue()); + mapKeyAndConsume(key, + mappedKey -> attributesBuilder.put(AttributeKey.doubleKey(mappedKey), ((Float) value).doubleValue())); } else if (value instanceof Short) { - attributesBuilder.put(AttributeKey.longKey(key), (Short) value); + mapKeyAndConsume(key, mappedKey -> attributesBuilder.put(AttributeKey.longKey(mappedKey), (Short) value)); } else if (value instanceof Byte) { - attributesBuilder.put(AttributeKey.longKey(key), (Byte) value); + mapKeyAndConsume(key, mappedKey -> attributesBuilder.put(AttributeKey.longKey(mappedKey), (Byte) value)); } else { LOGGER.warning("Could not populate attribute with key '{}', type {} is not supported.", key, value.getClass().getName()); @@ -110,23 +115,23 @@ private static void addAttribute(AttributesBuilder attributesBuilder, String key static void addAttribute(Span span, String key, Object value) { Objects.requireNonNull(key, "OpenTelemetry attribute name cannot be null."); - key = mapAttributeName(key); if (value instanceof String) { - span.setAttribute(AttributeKey.stringKey(key), (String) value); + mapKeyAndConsume(key, mappedKey -> span.setAttribute(AttributeKey.stringKey(mappedKey), (String) value)); } else if (value instanceof Long) { - span.setAttribute(AttributeKey.longKey(key), (Long) value); + mapKeyAndConsume(key, mappedKey -> span.setAttribute(AttributeKey.longKey(mappedKey), (Long) value)); } else if (value instanceof Integer) { - span.setAttribute(AttributeKey.longKey(key), (Integer) value); + mapKeyAndConsume(key, mappedKey -> span.setAttribute(AttributeKey.longKey(mappedKey), (Integer) value)); } else if (value instanceof Boolean) { - span.setAttribute(AttributeKey.booleanKey(key), (Boolean) value); + mapKeyAndConsume(key, mappedKey -> span.setAttribute(AttributeKey.booleanKey(mappedKey), (Boolean) value)); } else if (value instanceof Double) { - span.setAttribute(AttributeKey.doubleKey(key), (Double) value); + mapKeyAndConsume(key, mappedKey -> span.setAttribute(AttributeKey.doubleKey(mappedKey), (Double) value)); } else if (value instanceof Float) { - span.setAttribute(AttributeKey.doubleKey(key), ((Float) value).doubleValue()); + mapKeyAndConsume(key, + mappedKey -> span.setAttribute(AttributeKey.doubleKey(mappedKey), ((Float) value).doubleValue())); } else if (value instanceof Short) { - span.setAttribute(AttributeKey.longKey(key), (Short) value); + mapKeyAndConsume(key, mappedKey -> span.setAttribute(AttributeKey.longKey(mappedKey), (Short) value)); } else if (value instanceof Byte) { - span.setAttribute(AttributeKey.longKey(key), (Byte) value); + mapKeyAndConsume(key, mappedKey -> span.setAttribute(AttributeKey.longKey(mappedKey), (Byte) value)); } else { LOGGER.warning("Could not populate attribute with key '{}', type {} is not supported.", key, value.getClass().getName()); diff --git a/sdk/core/azure-core-tracing-opentelemetry/src/test/java/com/azure/core/tracing/opentelemetry/CreateTracerTests.java b/sdk/core/azure-core-tracing-opentelemetry/src/test/java/com/azure/core/tracing/opentelemetry/CreateTracerTests.java index 9e63c176a62e..bcddd1ab9d22 100644 --- a/sdk/core/azure-core-tracing-opentelemetry/src/test/java/com/azure/core/tracing/opentelemetry/CreateTracerTests.java +++ b/sdk/core/azure-core-tracing-opentelemetry/src/test/java/com/azure/core/tracing/opentelemetry/CreateTracerTests.java @@ -31,6 +31,10 @@ public class CreateTracerTests { .addSpanProcessor(SimpleSpanProcessor.create(InMemorySpanExporter.create())) .build(); + private static final AttributeKey AZ_NAMESPACE = AttributeKey.stringKey("az.namespace"); + private static final AttributeKey AZURE_RESOURCE_PROVIDER_NAMESPACE + = AttributeKey.stringKey("azure.resource_provider.namespace"); + private final OpenTelemetry openTelemetry = OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).build(); @Test @@ -79,8 +83,9 @@ public void createTracerWithAzNamespace() { Context span = tracer.start("test", Context.NONE); SpanData data = getSpanData(span); - assertEquals(1, data.getAttributes().size()); - assertEquals("namespace", data.getAttributes().get(AttributeKey.stringKey("az.namespace"))); + assertEquals(2, data.getAttributes().size()); + assertEquals("namespace", data.getAttributes().get(AZ_NAMESPACE)); + assertEquals("namespace", data.getAttributes().get(AZURE_RESOURCE_PROVIDER_NAMESPACE)); } @Test @@ -89,10 +94,12 @@ public void createTracerWithAzNamespaceInContext() { Tracer tracer = TracerProvider.getDefaultProvider().createTracer("test", null, "namespace", options); - Context span = tracer.start("test", new Context("az.namespace", "another")); + Context span = tracer.start("test", new Context(AZ_NAMESPACE.getKey(), "another") + .addData(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey(), "andAnother")); SpanData data = getSpanData(span); - assertEquals(1, data.getAttributes().size()); - assertEquals("namespace", data.getAttributes().get(AttributeKey.stringKey("az.namespace"))); + assertEquals(2, data.getAttributes().size()); + assertEquals("namespace", data.getAttributes().get(AZ_NAMESPACE)); + assertEquals("namespace", data.getAttributes().get(AZURE_RESOURCE_PROVIDER_NAMESPACE)); } @Test @@ -151,7 +158,8 @@ public void testSdkOptions() { assertEquals("test", readableSpan.getInstrumentationScopeInfo().getName()); assertEquals("https://aka.ms/az/sdk/schema:1.42.0", readableSpan.getInstrumentationScopeInfo().getSchemaUrl()); assertEquals("1.2.3-beta.45", readableSpan.getInstrumentationScopeInfo().getVersion()); - assertEquals("namespace", readableSpan.getAttributes().get(AttributeKey.stringKey("az.namespace"))); + assertEquals("namespace", readableSpan.getAttributes().get(AZ_NAMESPACE)); + assertEquals("namespace", readableSpan.getAttributes().get(AZURE_RESOURCE_PROVIDER_NAMESPACE)); } private static SpanData getSpanData(Context context) { diff --git a/sdk/core/azure-core-tracing-opentelemetry/src/test/java/com/azure/core/tracing/opentelemetry/OpenTelemetryHttpPolicyTests.java b/sdk/core/azure-core-tracing-opentelemetry/src/test/java/com/azure/core/tracing/opentelemetry/OpenTelemetryHttpPolicyTests.java index 64c0d8ffc0b7..66ef6dd9256e 100644 --- a/sdk/core/azure-core-tracing-opentelemetry/src/test/java/com/azure/core/tracing/opentelemetry/OpenTelemetryHttpPolicyTests.java +++ b/sdk/core/azure-core-tracing-opentelemetry/src/test/java/com/azure/core/tracing/opentelemetry/OpenTelemetryHttpPolicyTests.java @@ -56,7 +56,6 @@ import java.nio.charset.Charset; import java.time.Duration; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -90,8 +89,10 @@ public class OpenTelemetryHttpPolicyTests { private static final String ORIGINAL_URL_NO_QUERY = "https://httpbin.org/hello"; private static final ClientOptions DEFAULT_CLIENT_OPTIONS = new ClientOptions(); private static final LibraryTelemetryOptions DEFAULT_TELEMETRY_OPTIONS = new LibraryTelemetryOptions("test"); + private static final AttributeKey AZ_NAMESPACE = AttributeKey.stringKey("az.namespace"); + private static final AttributeKey AZURE_RESOURCE_PROVIDER_NAMESPACE + = AttributeKey.stringKey("azure.resource_provider.namespace"); private InMemorySpanExporter exporter; - private SdkTracerProvider tracerProvider; private OpenTelemetry openTelemetry; private Tracer tracer; private com.azure.core.util.tracing.Tracer azTracer; @@ -101,7 +102,8 @@ public class OpenTelemetryHttpPolicyTests { @BeforeEach public void setUp(TestInfo testInfo) { exporter = InMemorySpanExporter.create(); - tracerProvider = SdkTracerProvider.builder().addSpanProcessor(SimpleSpanProcessor.create(exporter)).build(); + SdkTracerProvider tracerProvider + = SdkTracerProvider.builder().addSpanProcessor(SimpleSpanProcessor.create(exporter)).build(); openTelemetry = OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).build(); azTracer = new OpenTelemetryTracer(DEFAULT_TELEMETRY_OPTIONS, @@ -117,7 +119,7 @@ public void openTelemetryHttpPolicyTest() { // Add parent span to tracingContext Context tracingContext = new Context(PARENT_TRACE_CONTEXT_KEY, io.opentelemetry.context.Context.root().with(parentSpan)) - .addData("az.namespace", "foo"); + .addData(AZ_NAMESPACE.getKey(), "foo"); // Act HttpRequest request = new HttpRequest(HttpMethod.POST, ORIGINAL_URL_WITH_QUERY); @@ -125,8 +127,8 @@ public void openTelemetryHttpPolicyTest() { try (Scope scope = parentSpan.makeCurrent()) { createHttpPipeline(DEFAULT_CLIENT_OPTIONS, azTracer).send(request, tracingContext) - .block() - .getBodyAsBinaryData(); + .map(HttpResponse::getBodyAsBinaryData) + .block(); } // Assert List exportedSpans = exporter.getFinishedSpanItems(); @@ -142,14 +144,16 @@ public void openTelemetryHttpPolicyTest() { Map httpAttributes = getAttributes(httpSpan); - assertEquals(7, httpAttributes.size()); + assertEquals(9, httpAttributes.size()); assertEquals(EXPECTED_URL_REDACTED, httpAttributes.get("url.full")); assertEquals("httpbin.org", httpAttributes.get("server.address")); assertEquals(443L, httpAttributes.get("server.port")); assertEquals("POST", httpAttributes.get("http.request.method")); - assertEquals("foo", httpAttributes.get("az.namespace")); + assertEquals("foo", httpAttributes.get(AZ_NAMESPACE.getKey())); + assertEquals("foo", httpAttributes.get(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey())); assertEquals((long) RESPONSE_STATUS_CODE, httpAttributes.get("http.response.status_code")); assertEquals(X_MS_REQUEST_ID_1, httpAttributes.get("az.service_request_id")); + assertEquals(X_MS_REQUEST_ID_1, httpAttributes.get("azure.service.request.id")); } @ParameterizedTest @@ -163,7 +167,9 @@ public void urlSanitizationTests(String originalUrl, Set allowedQueryPar Span parentSpan = tracer.spanBuilder(SPAN_NAME).startSpan(); try (Scope scope = parentSpan.makeCurrent()) { - createHttpPipeline(options, azTracer).send(request, Context.NONE).block().getBodyAsBinaryData(); + createHttpPipeline(options, azTracer).send(request, Context.NONE) + .map(HttpResponse::getBodyAsBinaryData) + .block(); } // Assert @@ -207,6 +213,7 @@ public String getDescription() { new OpenTelemetryTracingOptions() .setOpenTelemetry(OpenTelemetrySdk.builder().setTracerProvider(providerWithSampler).build()))) .send(request) + .map(HttpResponse::getBodyAsByteArray) .block(); } // Assert @@ -219,29 +226,31 @@ public String getDescription() { public void clientRequestIdIsStamped() { try (Scope scope = tracer.spanBuilder("test").startSpan().makeCurrent()) { HttpRequest request = new HttpRequest(HttpMethod.PUT, ORIGINAL_URL_WITH_QUERY); - HttpResponse response - = createHttpPipeline(DEFAULT_CLIENT_OPTIONS, azTracer, new RequestIdPolicy()).send(request) - .flatMap(r -> r.getBodyAsByteArray().thenReturn(r)) - .block(); - - // Assert - List exportedSpans = exporter.getFinishedSpanItems(); - assertEquals(1, exportedSpans.size()); - - assertEquals("PUT", exportedSpans.get(0).getName()); - - Map httpAttributes = getAttributes(exportedSpans.get(0)); - assertEquals(7, httpAttributes.size()); - - assertEquals(response.getRequest().getHeaders().getValue(HttpHeaderName.X_MS_CLIENT_REQUEST_ID), - httpAttributes.get("az.client_request_id")); - assertEquals(X_MS_REQUEST_ID_1, httpAttributes.get("az.service_request_id")); - - assertEquals(EXPECTED_URL_REDACTED, httpAttributes.get("url.full")); - assertEquals("httpbin.org", httpAttributes.get("server.address")); - assertEquals(443L, httpAttributes.get("server.port")); - assertEquals("PUT", httpAttributes.get("http.request.method")); - assertEquals((long) RESPONSE_STATUS_CODE, httpAttributes.get("http.response.status_code")); + StepVerifier + .create(createHttpPipeline(DEFAULT_CLIENT_OPTIONS, azTracer, new RequestIdPolicy()).send(request) + .flatMap(r -> r.getBodyAsByteArray().thenReturn(r))) + .assertNext(response -> { + // Assert + List exportedSpans = exporter.getFinishedSpanItems(); + assertEquals(1, exportedSpans.size()); + + assertEquals("PUT", exportedSpans.get(0).getName()); + + Map httpAttributes = getAttributes(exportedSpans.get(0)); + assertEquals(8, httpAttributes.size()); + + assertEquals(response.getRequest().getHeaders().getValue(HttpHeaderName.X_MS_CLIENT_REQUEST_ID), + httpAttributes.get("az.client_request_id")); + assertEquals(X_MS_REQUEST_ID_1, httpAttributes.get("az.service_request_id")); + assertEquals(X_MS_REQUEST_ID_1, httpAttributes.get("azure.service.request.id")); + + assertEquals(EXPECTED_URL_REDACTED, httpAttributes.get("url.full")); + assertEquals("httpbin.org", httpAttributes.get("server.address")); + assertEquals(443L, httpAttributes.get("server.port")); + assertEquals("PUT", httpAttributes.get("http.request.method")); + assertEquals((long) RESPONSE_STATUS_CODE, httpAttributes.get("http.response.status_code")); + }) + .verifyComplete(); } } @@ -255,7 +264,8 @@ public void everyTryIsTraced() { com.azure.core.util.tracing.Tracer azTracer = new OpenTelemetryTracer(DEFAULT_TELEMETRY_OPTIONS, options); - List policies = new ArrayList<>(Arrays.asList(new RetryPolicy())); + List policies = new ArrayList<>(); + policies.add(new RetryPolicy()); HttpPolicyProviders.addAfterRetryPolicies(policies); HttpPipeline pipeline @@ -282,7 +292,7 @@ public void everyTryIsTraced() { Context tracingContext = new Context(PARENT_TRACE_CONTEXT_KEY, io.opentelemetry.context.Context.root().with(parentSpan)) - .addData("az.namespace", "foo"); + .addData(AZ_NAMESPACE.getKey(), "foo"); StepVerifier.create(pipeline.send(new HttpRequest(HttpMethod.GET, ORIGINAL_URL_NO_QUERY), tracingContext)) .assertNext(response -> { @@ -302,17 +312,23 @@ public void everyTryIsTraced() { assertEquals("GET", try503.getName()); Map httpAttributes503 = getAttributes(try503); - assertEquals(9, httpAttributes503.size()); + assertEquals(11, httpAttributes503.size()); assertEquals("503", httpAttributes503.get("error.type")); assertEquals(503L, httpAttributes503.get("http.response.status_code")); assertEquals(X_MS_REQUEST_ID_1, httpAttributes503.get("az.service_request_id")); + assertEquals(X_MS_REQUEST_ID_1, httpAttributes503.get("azure.service.request.id")); + assertEquals("foo", httpAttributes503.get(AZ_NAMESPACE.getKey())); + assertEquals("foo", httpAttributes503.get(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey())); assertEquals("GET", try503.getName()); Map httpAttributes200 = getAttributes(try200); - assertEquals(8, httpAttributes200.size()); + assertEquals(10, httpAttributes200.size()); assertEquals(2L, httpAttributes200.get("http.request.resend_count")); assertEquals(200L, httpAttributes200.get("http.response.status_code")); assertEquals(X_MS_REQUEST_ID_2, httpAttributes200.get("az.service_request_id")); + assertEquals(X_MS_REQUEST_ID_2, httpAttributes200.get("azure.service.request.id")); + assertEquals("foo", httpAttributes200.get(AZ_NAMESPACE.getKey())); + assertEquals("foo", httpAttributes200.get(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey())); } @ParameterizedTest @@ -382,7 +398,8 @@ public void timeoutIsTraced() { com.azure.core.util.tracing.Tracer azTracer = new OpenTelemetryTracer(DEFAULT_TELEMETRY_OPTIONS, options); - List policies = new ArrayList<>(Arrays.asList(new RetryPolicy())); + List policies = new ArrayList<>(); + policies.add(new RetryPolicy()); HttpPolicyProviders.addAfterRetryPolicies(policies); HttpPipeline pipeline @@ -404,12 +421,14 @@ public void timeoutIsTraced() { Context tracingContext = new Context(PARENT_TRACE_CONTEXT_KEY, io.opentelemetry.context.Context.root().with(parentSpan)) - .addData("az.namespace", "foo"); + .addData(AZ_NAMESPACE.getKey(), "foo") + .addData(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey(), "foo"); - StepVerifier.create(pipeline.send(new HttpRequest(HttpMethod.GET, ORIGINAL_URL_NO_QUERY), tracingContext) - .flatMap(r -> r.getBody().collectList().thenReturn(r))).assertNext(response -> { - assertEquals(200, response.getStatusCode()); - }).verifyComplete(); + StepVerifier + .create(pipeline.send(new HttpRequest(HttpMethod.GET, ORIGINAL_URL_NO_QUERY), tracingContext) + .flatMap(r -> r.getBody().collectList().thenReturn(r))) + .assertNext(response -> assertEquals(200, response.getStatusCode())) + .verifyComplete(); List exportedSpans = exporter.getFinishedSpanItems(); assertEquals(2, exportedSpans.size()); @@ -421,6 +440,8 @@ public void timeoutIsTraced() { assertEquals("timeout", tryTimeout.getStatus().getDescription()); assertEquals(TimeoutException.class.getName(), tryTimeout.getAttributes().get(AttributeKey.stringKey("error.type"))); + assertEquals("foo", tryTimeout.getAttributes().get(AZ_NAMESPACE)); + assertEquals("foo", tryTimeout.getAttributes().get(AZURE_RESOURCE_PROVIDER_NAMESPACE)); } @Test @@ -437,7 +458,7 @@ public void connectionErrorAfterResponseCodeIsTraced() { .build(); StepVerifier.create(pipeline.send(new HttpRequest(HttpMethod.GET, ORIGINAL_URL_NO_QUERY), Context.NONE) - .flatMap(response -> response.getBodyAsInputStream())).expectError(IOException.class).verify(); + .flatMap(HttpResponse::getBodyAsInputStream)).expectError(IOException.class).verify(); List exportedSpans = exporter.getFinishedSpanItems(); assertEquals(1, exportedSpans.size()); @@ -457,7 +478,8 @@ public void cancelIsTraced() { com.azure.core.util.tracing.Tracer azTracer = new OpenTelemetryTracer(DEFAULT_TELEMETRY_OPTIONS, options); - List policies = new ArrayList<>(Arrays.asList(new RetryPolicy())); + List policies = new ArrayList<>(); + policies.add(new RetryPolicy()); HttpPolicyProviders.addAfterRetryPolicies(policies); HttpPipeline pipeline = new HttpPipelineBuilder().policies(policies.toArray(new HttpPipelinePolicy[0])) @@ -485,8 +507,16 @@ private Map getAttributes(SpanData span) { } private static HttpPipeline createHttpPipeline(ClientOptions clientOptions, - com.azure.core.util.tracing.Tracer azTracer, HttpPipelinePolicy... beforeRetryPolicies) { - List policies = new ArrayList<>(Arrays.asList(beforeRetryPolicies)); + com.azure.core.util.tracing.Tracer azTracer) { + return createHttpPipeline(clientOptions, azTracer, null); + } + + private static HttpPipeline createHttpPipeline(ClientOptions clientOptions, + com.azure.core.util.tracing.Tracer azTracer, HttpPipelinePolicy beforeRetryPolicy) { + List policies = new ArrayList<>(); + if (beforeRetryPolicy != null) { + policies.add(beforeRetryPolicy); + } HttpPolicyProviders.addAfterRetryPolicies(policies); return new HttpPipelineBuilder().clientOptions(clientOptions) @@ -536,7 +566,7 @@ public Mono send(HttpRequest request) { } } - private class ThrowingHttpResponse extends MockHttpResponse { + private static class ThrowingHttpResponse extends MockHttpResponse { private final int throwAfterBytes; private final Throwable toThrow; @@ -580,7 +610,7 @@ public Mono getBodyAsString(Charset charset) { @Override public Mono getBodyAsInputStream() { - return BinaryData.fromFlux(getBody()).map(data -> data.toStream()); + return BinaryData.fromFlux(getBody()).map(BinaryData::toStream); } } } diff --git a/sdk/core/azure-core-tracing-opentelemetry/src/test/java/com/azure/core/tracing/opentelemetry/OpenTelemetryTracerTest.java b/sdk/core/azure-core-tracing-opentelemetry/src/test/java/com/azure/core/tracing/opentelemetry/OpenTelemetryTracerTest.java index f388b0493775..789b58a1125a 100644 --- a/sdk/core/azure-core-tracing-opentelemetry/src/test/java/com/azure/core/tracing/opentelemetry/OpenTelemetryTracerTest.java +++ b/sdk/core/azure-core-tracing-opentelemetry/src/test/java/com/azure/core/tracing/opentelemetry/OpenTelemetryTracerTest.java @@ -49,14 +49,13 @@ import java.time.ZoneOffset; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.stream.Stream; -import static com.azure.core.tracing.opentelemetry.OpenTelemetryTracer.MESSAGE_ENQUEUED_TIME; -import static com.azure.core.util.tracing.Tracer.AZ_TRACING_NAMESPACE_KEY; import static com.azure.core.util.tracing.Tracer.DIAGNOSTIC_ID_KEY; import static com.azure.core.util.tracing.Tracer.ENTITY_PATH_KEY; import static com.azure.core.util.tracing.Tracer.HOST_NAME_KEY; @@ -86,6 +85,10 @@ public class OpenTelemetryTracerTest { private static final String ENTITY_PATH_VALUE = "test"; private static final String AZ_NAMESPACE_VALUE = "Microsoft.Eventhub"; private static final Long MESSAGE_ENQUEUED_VALUE = Instant.ofEpochSecond(561639205).getEpochSecond(); + private static final AttributeKey AZ_NAMESPACE = AttributeKey.stringKey("az.namespace"); + private static final AttributeKey AZURE_RESOURCE_PROVIDER_NAMESPACE + = AttributeKey.stringKey("azure.resource_provider.namespace"); + private static final AttributeKey MESSAGE_ENQUEUED_TIME = AttributeKey.longKey("x-opt-enqueued-time"); private static final int TRACEPARENT_DELIMITER_SIZE = 1; private static final int TRACE_ID_HEX_SIZE = TraceId.getLength(); private static final int SPAN_ID_HEX_SIZE = SpanId.getLength(); @@ -95,25 +98,16 @@ public class OpenTelemetryTracerTest { private OpenTelemetryTracer openTelemetryTracer; private Tracer tracer; private InMemorySpanExporter testExporter; - private SpanProcessor spanProcessor; private Context tracingContext; private Span parentSpan; - private SdkTracerProvider tracerProvider; private OpenTelemetry openTelemetry; - - private final HashMap expectedAttributeMap = new HashMap() { - { - put("messaging.destination.name", ENTITY_PATH_VALUE); - put("server.address", HOSTNAME_VALUE); - put("az.namespace", AZ_NAMESPACE_VALUE); - } - }; + private HashMap expectedAttributeMap; @BeforeEach public void setUp() { testExporter = InMemorySpanExporter.create(); - spanProcessor = SimpleSpanProcessor.create(testExporter); - tracerProvider = SdkTracerProvider.builder().addSpanProcessor(spanProcessor).build(); + SpanProcessor spanProcessor = SimpleSpanProcessor.create(testExporter); + SdkTracerProvider tracerProvider = SdkTracerProvider.builder().addSpanProcessor(spanProcessor).build(); openTelemetry = OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).build(); @@ -127,6 +121,12 @@ public void setUp() { openTelemetryTracer = new OpenTelemetryTracer( new LibraryTelemetryOptions("test").setResourceProviderNamespace(AZ_NAMESPACE_VALUE), new OpenTelemetryTracingOptions().setOpenTelemetry(openTelemetry)); + + expectedAttributeMap = new LinkedHashMap<>(); + expectedAttributeMap.put("messaging.destination.name", ENTITY_PATH_VALUE); + expectedAttributeMap.put("server.address", HOSTNAME_VALUE); + expectedAttributeMap.put(AZ_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE); + expectedAttributeMap.put(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE); } @AfterEach @@ -154,7 +154,8 @@ public void startSpanParentContextFlowTest() { final SpanData spanData = assertSpanWithExplicitParent(span, parentSpanId).toSpanData(); assertEquals(SpanKind.INTERNAL, spanData.getKind()); final Attributes attributeMap = spanData.getAttributes(); - assertEquals(attributeMap.get(AttributeKey.stringKey("az.namespace")), AZ_NAMESPACE_VALUE); + assertEquals(AZ_NAMESPACE_VALUE, attributeMap.get(AZ_NAMESPACE)); + assertEquals(AZ_NAMESPACE_VALUE, attributeMap.get(AZURE_RESOURCE_PROVIDER_NAMESPACE)); } @Test @@ -179,7 +180,8 @@ public void startSharedBuilderAndSpanProcessKindSend() { // Add additional metadata to spans for SEND final Context traceContext = tracingContext.addData(ENTITY_PATH_KEY, ENTITY_PATH_VALUE) .addData(HOST_NAME_KEY, HOSTNAME_VALUE) - .addData("az.namespace", "ignored"); + .addData(AZ_NAMESPACE.getKey(), "ignored") + .addData(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey(), "ignored"); // Start user parent span. final Context withBuilder = openTelemetryTracer.getSharedSpanBuilder(METHOD_NAME, traceContext); @@ -228,12 +230,14 @@ public void fallbackToAzNamespaceFromContext() { new OpenTelemetryTracingOptions().setOpenTelemetry(openTelemetry)); // Act - final Context span = noAzTracer.start(METHOD_NAME, new Context("az.namespace", "foo")); + final Context span = noAzTracer.start(METHOD_NAME, + new Context(AZ_NAMESPACE.getKey(), "foo").addData(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey(), "foo")); // Assert SpanData spanData = getSpan(span).toSpanData(); - assertEquals(1, spanData.getAttributes().size()); - assertEquals("foo", spanData.getAttributes().get(AttributeKey.stringKey("az.namespace"))); + assertEquals(2, spanData.getAttributes().size()); + assertEquals("foo", spanData.getAttributes().get(AZ_NAMESPACE)); + assertEquals("foo", spanData.getAttributes().get(AZURE_RESOURCE_PROVIDER_NAMESPACE)); } @Test @@ -324,7 +328,8 @@ public void startSpanProcessKindSend() { final Context traceContext = tracingContext.addData(ENTITY_PATH_KEY, ENTITY_PATH_VALUE) .addData(HOST_NAME_KEY, HOSTNAME_VALUE) .addData(SPAN_BUILDER_KEY, spanBuilder) - .addData(AZ_TRACING_NAMESPACE_KEY, AZ_NAMESPACE_VALUE); + .addData(AZ_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE) + .addData(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE); // Act final Context updatedContext @@ -348,7 +353,8 @@ public void startSpanProcessKindMessage() { final String parentSpanId = parentSpan.getSpanContext().getSpanId(); final Context contextWithAttributes = tracingContext.addData(ENTITY_PATH_KEY, ENTITY_PATH_VALUE) .addData(HOST_NAME_KEY, HOSTNAME_VALUE) - .addData(AZ_TRACING_NAMESPACE_KEY, AZ_NAMESPACE_VALUE); + .addData(AZ_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE) + .addData(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE); // Act final Context updatedContext = openTelemetryTracer.start(METHOD_NAME, contextWithAttributes, @@ -375,8 +381,9 @@ public void startSpanProcessKindProcess() { // Add additional metadata to spans for PROCESS final Context traceContext = tracingContext.addData(ENTITY_PATH_KEY, ENTITY_PATH_VALUE) .addData(HOST_NAME_KEY, HOSTNAME_VALUE) - .addData(AZ_TRACING_NAMESPACE_KEY, AZ_NAMESPACE_VALUE) - .addData(MESSAGE_ENQUEUED_TIME, MESSAGE_ENQUEUED_VALUE); // only in PROCESS + .addData(AZ_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE) + .addData(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE) + .addData(MESSAGE_ENQUEUED_TIME.getKey(), MESSAGE_ENQUEUED_VALUE); // only in PROCESS // Act final Context updatedContext @@ -395,8 +402,9 @@ public void startSpanProcessKindProcess() { final Attributes attributeMap = recordEventsSpan.toSpanData().getAttributes(); // additional only in process spans. - expectedAttributeMap.put(MESSAGE_ENQUEUED_TIME, MESSAGE_ENQUEUED_VALUE); - expectedAttributeMap.put(AZ_TRACING_NAMESPACE_KEY, AZ_NAMESPACE_VALUE); + expectedAttributeMap.put(MESSAGE_ENQUEUED_TIME.getKey(), MESSAGE_ENQUEUED_VALUE); + expectedAttributeMap.put(AZ_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE); + expectedAttributeMap.put(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE); verifySpanAttributes(expectedAttributeMap, attributeMap); } @@ -440,7 +448,7 @@ public void startProcessSpanWithLinks() { openTelemetryTracer.addLink(spanBuilder.addData(SPAN_CONTEXT_KEY, link1.getSpanContext())); openTelemetryTracer.addLink(spanBuilder.addData(SPAN_CONTEXT_KEY, link2.getSpanContext()) - .addData(MESSAGE_ENQUEUED_TIME, MESSAGE_ENQUEUED_VALUE)); + .addData(MESSAGE_ENQUEUED_TIME.getKey(), MESSAGE_ENQUEUED_VALUE)); // Act final Context spanCtx @@ -459,7 +467,7 @@ public void startProcessSpanWithLinks() { assertEquals(link2.getSpanContext().getSpanId(), links.get(1).getSpanContext().getSpanId()); Attributes linkAttributes = links.get(1).getAttributes(); assertEquals(1, linkAttributes.size()); - assertEquals(MESSAGE_ENQUEUED_VALUE, linkAttributes.get(AttributeKey.longKey(MESSAGE_ENQUEUED_TIME))); + assertEquals(MESSAGE_ENQUEUED_VALUE, linkAttributes.get(MESSAGE_ENQUEUED_TIME)); } @Test @@ -481,7 +489,7 @@ public void startConsumeSpanWitStartTimeInContext() { // Assert ReadableSpan span = getSpan(spanCtx); assertEquals(1, span.toSpanData().getLinks().size()); - assertEquals(span.getLatencyNanos() / 1000_000_000d, 1000d, 10); + assertEquals(1000d, span.getLatencyNanos() / 1000_000_000d, 10); } @Test @@ -535,7 +543,7 @@ public void addLinkNoSpanContextTest() { // Assert // verify no links were added - assertEquals(span1.toSpanData().getLinks().size(), 0); + assertEquals(0, span1.toSpanData().getLinks().size()); } @Test @@ -550,7 +558,7 @@ public void addLinkNoSpanToLinkTest() { // Assert // verify no links were added - assertEquals(span1.toSpanData().getLinks().size(), 0); + assertEquals(0, span1.toSpanData().getLinks().size()); } @Test @@ -625,7 +633,7 @@ public void setAttributeTest() { // Assert final Attributes attributeMap = recordEventsSpan.toSpanData().getAttributes(); - assertEquals(attributeMap.get(AttributeKey.stringKey(firstKey)), firstKeyValue); + assertEquals(firstKeyValue, attributeMap.get(AttributeKey.stringKey(firstKey))); } @Test @@ -642,8 +650,9 @@ public void setAttributeNoSpanTest() { // Assert final Attributes attributeMap = readableSpan.toSpanData().getAttributes(); assertNull(attributeMap.get(AttributeKey.stringKey(firstKey))); - assertEquals(attributeMap.size(), 1); - assertEquals(AZ_NAMESPACE_VALUE, attributeMap.get(AttributeKey.stringKey("az.namespace"))); + assertEquals(2, attributeMap.size()); + assertEquals(AZ_NAMESPACE_VALUE, attributeMap.get(AZ_NAMESPACE)); + assertEquals(AZ_NAMESPACE_VALUE, attributeMap.get(AZURE_RESOURCE_PROVIDER_NAMESPACE)); } @Test @@ -707,22 +716,19 @@ public void addEventWithNonNullEventName() { public void addEventWithAttributes() { // Arrange final String eventName = "event-0"; - Map input = new HashMap() { - { - put("attr1", "value1"); - put("attr2", true); - put("attr3", 1L); - put("attr4", 2); - put("attr5", (short) 3); - put("attr6", (byte) 4); - put("attr7", 1.0); - put("attr8", 2F); - put("attr9", new double[] { 1.0, 2.0, 3.0 }); - put("attr10", new long[] { 1L, 2L, 3L }); - put("attr11", new boolean[] { true }); - put("attr12", null); - } - }; + Map input = new HashMap<>(); + input.put("attr1", "value1"); + input.put("attr2", true); + input.put("attr3", 1L); + input.put("attr4", 2); + input.put("attr5", (short) 3); + input.put("attr6", (byte) 4); + input.put("attr7", 1.0); + input.put("attr8", 2F); + input.put("attr9", new double[] { 1.0, 2.0, 3.0 }); + input.put("attr10", new long[] { 1L, 2L, 3L }); + input.put("attr11", new boolean[] { true }); + input.put("attr12", null); // Act openTelemetryTracer.addEvent(eventName, input, null, tracingContext); @@ -820,8 +826,9 @@ public void startSpanWithOptionsNameEmptyParent() { assertEquals(SpanKind.INTERNAL, span.getKind()); assertEquals("0000000000000000", spanData.getParentSpanId()); - assertEquals(1, spanData.getAttributes().size()); - assertEquals(AZ_NAMESPACE_VALUE, spanData.getAttributes().get(AttributeKey.stringKey("az.namespace"))); + assertEquals(2, spanData.getAttributes().size()); + assertEquals(AZ_NAMESPACE_VALUE, spanData.getAttributes().get(AZ_NAMESPACE)); + assertEquals(AZ_NAMESPACE_VALUE, spanData.getAttributes().get(AZURE_RESOURCE_PROVIDER_NAMESPACE)); } @Test @@ -894,7 +901,8 @@ public void startSpanWithAttributes() { .put("I", 1) .put("D", 0.1d) .put("B", true) - .put("az.namespace", AZ_NAMESPACE_VALUE) + .put(AZ_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE) + .put(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE) .build(); final StartSpanOptions options = new StartSpanOptions(com.azure.core.util.tracing.SpanKind.INTERNAL); @@ -927,7 +935,8 @@ public void spanAttributes() { .put("I", 1) .put("D", 0.1d) .put("B", true) - .put("az.namespace", AZ_NAMESPACE_VALUE) + .put(AZ_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE) + .put(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE) .build(); Context spanCtx = openTelemetryTracer.start(METHOD_NAME, tracingContext); @@ -1121,13 +1130,11 @@ public void suppressNestedClientSpanAttributes() { SpanData outerSpan = testExporter.getFinishedSpanItems().get(0); assertEquals("outer", outerSpan.getName()); - Map outerAttributesExpected = new HashMap() { - { - put("outer1", "foo"); - put("outer2", "bar"); - put("az.namespace", AZ_NAMESPACE_VALUE); - } - }; + Map outerAttributesExpected = new HashMap<>(); + outerAttributesExpected.put("outer1", "foo"); + outerAttributesExpected.put("outer2", "bar"); + outerAttributesExpected.put(AZ_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE); + outerAttributesExpected.put(AZURE_RESOURCE_PROVIDER_NAMESPACE.getKey(), AZ_NAMESPACE_VALUE); verifySpanAttributes(outerAttributesExpected, outerSpan.getAttributes()); } @@ -1336,7 +1343,7 @@ private static ReadableSpan assertSpanWithExplicitParent(Context context, String return span; } - private static ReadableSpan assertSpanWithRemoteParent(Context context, String parentSpanId) { + private static void assertSpanWithRemoteParent(Context context, String parentSpanId) { final ReadableSpan span = getSpan(context); assertEquals(METHOD_NAME, span.getName()); @@ -1345,7 +1352,6 @@ private static ReadableSpan assertSpanWithRemoteParent(Context context, String p // verify span started with remote parent assertTrue(span.toSpanData().getParentSpanContext().isRemote()); assertEquals(parentSpanId, span.toSpanData().getParentSpanId()); - return span; } private static void verifySpanAttributes(Map expectedMap, Attributes actualAttributeMap) { diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/TestSpanProcessor.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/TestSpanProcessor.java index 353ec7f5ec45..0e4e81f26c49 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/TestSpanProcessor.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/TestSpanProcessor.java @@ -91,6 +91,8 @@ public void onEnd(ReadableSpan readableSpan) { String messagingSystem = attributes.get(AttributeKey.stringKey("messaging.system")); if ("eventhubs".equals(messagingSystem)) { assertEquals("Microsoft.EventHub", attributes.get(AttributeKey.stringKey("az.namespace"))); + assertEquals("Microsoft.EventHub", + attributes.get(AttributeKey.stringKey("azure.resource_provider.namespace"))); assertEquals(entityName, attributes.get(AttributeKey.stringKey("messaging.destination.name"))); assertEquals(namespace, attributes.get(AttributeKey.stringKey("server.address"))); } diff --git a/sdk/servicebus/azure-messaging-servicebus/src/test/java/com/azure/messaging/servicebus/TracingIntegrationTests.java b/sdk/servicebus/azure-messaging-servicebus/src/test/java/com/azure/messaging/servicebus/TracingIntegrationTests.java index 408afbb6974d..532dd1647366 100644 --- a/sdk/servicebus/azure-messaging-servicebus/src/test/java/com/azure/messaging/servicebus/TracingIntegrationTests.java +++ b/sdk/servicebus/azure-messaging-servicebus/src/test/java/com/azure/messaging/servicebus/TracingIntegrationTests.java @@ -860,6 +860,8 @@ private OpenTelemetry configureOTel(String namespace, String entityName) { static class TestSpanProcessor implements SpanProcessor { private static final ClientLogger LOGGER = new ClientLogger(TestSpanProcessor.class); private static final AttributeKey AZ_NAMESPACE = AttributeKey.stringKey("az.namespace"); + private static final AttributeKey AZURE_RESOURCE_PROVIDER_NAMESPACE + = AttributeKey.stringKey("azure.resource_provider.namespace"); private static final AttributeKey MESSAGING_SYSTEM = AttributeKey.stringKey("messaging.system"); private static final AttributeKey MESSAGING_DESTINATION_NAME = AttributeKey.stringKey("messaging.destination.name"); @@ -894,6 +896,7 @@ public boolean isStartRequired() { public void onEnd(ReadableSpan readableSpan) { LOGGER.info(readableSpan.toString()); assertEquals("Microsoft.ServiceBus", readableSpan.getAttribute(AZ_NAMESPACE)); + assertEquals("Microsoft.ServiceBus", readableSpan.getAttribute(AZURE_RESOURCE_PROVIDER_NAMESPACE)); assertEquals("servicebus", readableSpan.getAttribute(MESSAGING_SYSTEM)); assertEquals(entityName, readableSpan.getAttribute(MESSAGING_DESTINATION_NAME));