diff --git a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/TracerProvider.java b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/TracerProvider.java index f21db781778d..6a80e4aefd04 100644 --- a/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/TracerProvider.java +++ b/sdk/core/azure-core-amqp/src/main/java/com/azure/core/amqp/implementation/TracerProvider.java @@ -3,7 +3,7 @@ package com.azure.core.amqp.implementation; import com.azure.core.amqp.exception.AmqpException; -import com.azure.core.implementation.tracing.ProcessKind; +import com.azure.core.util.tracing.ProcessKind; import com.azure.core.util.Context; import com.azure.core.util.logging.ClientLogger; import com.azure.core.util.tracing.Tracer; diff --git a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/TracerProviderTest.java b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/TracerProviderTest.java index c9be69a8a9db..9ba3876242c8 100644 --- a/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/TracerProviderTest.java +++ b/sdk/core/azure-core-amqp/src/test/java/com/azure/core/amqp/implementation/TracerProviderTest.java @@ -5,7 +5,7 @@ import com.azure.core.amqp.exception.AmqpException; import com.azure.core.amqp.exception.ErrorCondition; -import com.azure.core.implementation.tracing.ProcessKind; +import com.azure.core.util.tracing.ProcessKind; import com.azure.core.util.Context; import com.azure.core.util.tracing.Tracer; import org.junit.After; diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/tracing/ProcessKind.java b/sdk/core/azure-core/src/main/java/com/azure/core/util/tracing/ProcessKind.java similarity index 90% rename from sdk/core/azure-core/src/main/java/com/azure/core/implementation/tracing/ProcessKind.java rename to sdk/core/azure-core/src/main/java/com/azure/core/util/tracing/ProcessKind.java index 36525024c9e9..69f4f351e517 100644 --- a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/tracing/ProcessKind.java +++ b/sdk/core/azure-core/src/main/java/com/azure/core/util/tracing/ProcessKind.java @@ -1,6 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -package com.azure.core.implementation.tracing; +package com.azure.core.util.tracing; /** * Contains constants common AMQP protocol process calls. diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/tracing/Tracer.java b/sdk/core/azure-core/src/main/java/com/azure/core/util/tracing/Tracer.java index 96e3c19ef41d..80d90c1481d2 100644 --- a/sdk/core/azure-core/src/main/java/com/azure/core/util/tracing/Tracer.java +++ b/sdk/core/azure-core/src/main/java/com/azure/core/util/tracing/Tracer.java @@ -3,33 +3,31 @@ package com.azure.core.util.tracing; -import com.azure.core.implementation.tracing.ProcessKind; import com.azure.core.util.Context; /** * Contract that all tracers must implement to be plug-able into the SDK. + * */ public interface Tracer { /** * Key for {@link Context} which indicates that the context contains OpenCensus span data. This span will be used * as the parent span for all spans the SDK creates. - * - * If no span data is listed when the SDK creates its first span it will be used as the parent for all further spans - * it creates. + *

+ * If no span data is listed when the SDK creates its first span, this span key will be used as the parent span. */ String OPENCENSUS_SPAN_KEY = "opencensus-span"; /** * Key for {@link Context} which indicates that the context contains the name for the OpenCensus spans that are * created. - * + *

* If no span name is listed when the span is created it will default to using the calling method's name. */ String OPENCENSUS_SPAN_NAME_KEY = "opencensus-span-name"; /** - * Key for {@link Context} which indicates that the context contains the Entity Path, remote endpoint path. - * + * Key for {@link Context} which indicates that the context contains an entity path. */ String ENTITY_PATH = "entity-path"; @@ -40,61 +38,108 @@ public interface Tracer { String HOST_NAME = "hostname"; /** - * Key for {@link Context} which indicates that the context contains message Span Context. + * Key for {@link Context} which indicates that the context contains a message span context. * */ String SPAN_CONTEXT = "span-context"; /** - * Key for {@link Context} which indicates that the context contains the Diagnostic Id for the service call. + * Key for {@link Context} which indicates that the context contains a "Diagnostic Id" for the service call. * */ String DIAGNOSTIC_ID_KEY = "diagnostic-id"; /** * Creates a new tracing span. + *

+ * The {@code context} will be checked for containing information about a parent span. If a parent span is found, + * the new span will be added as a child. Otherwise the parent span will be created and added to the {@code context} + * and any downstream {@code start()} calls will use the created span as the parent. * - * The {@code context} will be checked for containing information about a parent span. If a parent span is found the - * new span will be added as a child, otherwise the span will be created and added to the context and any downstream - * start calls will use the created span as the parent. + *

Code samples

+ * + *

Starts a tracing span with provided method name and explicit parent span

+ * {@codesnippet com.azure.core.util.tracing.start#string-context} * * @param methodName Name of the method triggering the span creation. * @param context Additional metadata that is passed through the call stack. - * @return An updated context object. + * + * @return The updated {@link Context} object containing the returned span. + * @throws NullPointerException if {@code methodName} or {@code context} is {@code null}. */ Context start(String methodName, Context context); /** - * Creates a new tracing span. + * Creates a new tracing span for AMQP calls. * + *

* The {@code context} will be checked for containing information about a parent span. If a parent span is found the - * new span will be added as a child, otherwise the span will be created and added to the context and any downstream - * start calls will use the created span as the parent. + * new span will be added as a child. Otherwise the span will be created and added to the {@code context} and any + * downstream {@code start()} calls will use the created span as the parent. + * + *

+ * Sets additional request attributes on the created span when {@code processKind} is + * {@link ProcessKind#SEND ProcessKind.SEND}. + * + *

+ * Returns the diagnostic Id and span context of the returned span when {@code processKind} is + * {@link ProcessKind#RECEIVE ProcessKind.RECEIVE}. + * + *

+ * Creates a new tracing span with remote parent and returns that scope when the given when {@code processKind} + * is {@link ProcessKind#PROCESS ProcessKind.PROCESS}. + * + *

Code samples

+ * + *

Starts a tracing span with provided method name and AMQP operation SEND

+ * {@codesnippet com.azure.core.util.tracing.start#string-context-processKind-SEND} + * + *

Starts a tracing span with provided method name and AMQP operation RECEIVE

+ * {@codesnippet com.azure.core.util.tracing.start#string-context-processKind-RECEIVE} + * + *

Starts a tracing span with provided method name and AMQP operation PROCESS

+ * {@codesnippet com.azure.core.util.tracing.start#string-context-processKind-PROCESS} * * @param methodName Name of the method triggering the span creation. * @param context Additional metadata that is passed through the call stack. - * @param processKind AMQP message process kind. - * @return An updated context object. + * @param processKind AMQP operation kind. + * + * @return The updated {@link Context} object containing the returned span. + * @throws NullPointerException if {@code methodName} or {@code context} or {@code processKind} is {@code null}. */ Context start(String methodName, Context context, ProcessKind processKind); /** * Completes the current tracing span. * + *

Code samples

+ * + *

Completes the tracing span present in the context, with the corresponding OpenCensus status for the given + * response status code

+ * {@codesnippet com.azure.core.util.tracing.end#int-throwable-context} + * * @param responseCode Response status code if the span is in a HTTP call context. - * @param error Potential throwable that happened during the span. + * @param error {@link Throwable} that happened during the span or {@code null} if no exception occurred. * @param context Additional metadata that is passed through the call stack. + * @throws NullPointerException if {@code context} is {@code null}. */ void end(int responseCode, Throwable error, Context context); /** * Completes the current tracing span. * - * @param errorCondition the error message that occurred during the call. - * @param error Potential throwable that happened during the span. + *

Code samples

+ * + *

Completes the tracing span with the corresponding OpenCensus status for the given status message

+ * {@codesnippet com.azure.core.util.tracing.end#string-throwable-context} + * + * @param statusMessage the error or success message that occurred during the call, or {@code null} if no error + * occurred. + * @param error {@link Throwable} that happened during the span or {@code null} if no exception occurred. * @param context Additional metadata that is passed through the call stack. + * @throws NullPointerException if {@code context} is {@code null}. */ - void end(String errorCondition, Throwable error, Context context); + void end(String statusMessage, Throwable error, Context context); /** * Adds metadata to the current span. The {@code context} is checked for having span information, if no span @@ -103,62 +148,53 @@ public interface Tracer { * @param key Name of the metadata. * @param value Value of the metadata. * @param context Additional metadata that is passed through the call stack. + * @throws NullPointerException if {@code key} or {@code value} or {@code context} is {@code null}. */ void setAttribute(String key, String value, Context context); - /* - * Adds metadata to the current span. The {@code context} is checked for having span information, if no span - * information is found in the context no metadata is added. - * - * @param key Name of the metadata. - * @param value Value of the metadata. - * @param context Additional metadata that is passed through the call stack. - */ - // void setAttribute(String key, long value, Context context); - - /* - * Adds metadata to the current span. The {@code context} is checked for having span information, if no span - * information is found in the context no metadata is added. + /** + * Sets the name for spans that are created. * - * @param key Name of the metadata. - * @param value Value of the metadata. - * @param context Additional metadata that is passed through the call stack. - */ - // void setAttribute(String key, double value, Context context); - - /* - * Adds metadata to the current span. The {@code context} is checked for having span information, if no span - * information is found in the context no metadata is added. + *

Code samples

* - * @param key Name of the metadata. - * @param value Value of the metadata. - * @param context Additional metadata that is passed through the call stack. - */ - // void setAttribute(String key, boolean value, Context context); - - /** - * Configures the name for spans that are created. + *

Retrieve the span name of the returned span

+ * {@codesnippet com.azure.core.util.tracing.setSpanName#string-context} * * @param spanName Name to give the next span. * @param context Additional metadata that is passed through the call stack. - * @return An updated context object. + * + * @return The updated {@link Context} object containing the name of the returned span. + * @throws NullPointerException if {@code spanName} or {@code context} is {@code null}. */ Context setSpanName(String spanName, Context context); /** - * Adds a link to the tracing span. + * Provides a way to link multiple tracing spans. * Used in batching operations to relate multiple requests under a single batch. * + *

Code samples

+ * + *

Link multiple spans using their span context information

+ * {@codesnippet com.azure.core.util.tracing.addLink#context} + * * @param context Additional metadata that is passed through the call stack. + * @throws NullPointerException if {@code context} is {@code null}. */ void addLink(Context context); /** - * Extracts the span's {@link Context} from the given event's diagnostic id. + * Extracts the span's context as {@link Context} from upstream. + * + *

Code samples

+ * + *

Extracts the corresponding span context information from a valid diagnostic id

+ * {@codesnippet com.azure.core.util.tracing.extractContext#string-context} * * @param diagnosticId Unique identifier for the trace information of the span. * @param context Additional metadata that is passed through the call stack. - * @return An updated context object. + * + * @return The updated {@link Context} object containing the span context. + * @throws NullPointerException if {@code diagnosticId} or {@code context} is {@code null}. */ Context extractContext(String diagnosticId, Context context); } diff --git a/sdk/core/azure-core/src/main/java/module-info.java b/sdk/core/azure-core/src/main/java/module-info.java index 5235cc6236d9..6b0b06294e65 100644 --- a/sdk/core/azure-core/src/main/java/module-info.java +++ b/sdk/core/azure-core/src/main/java/module-info.java @@ -107,21 +107,6 @@ com.azure.storage.blob, // FIXME this should not be a long-term solution com.azure.storage.file, // FIXME this should not be a long-term solution com.azure.storage.queue; // FIXME this should not be a long-term solution - exports com.azure.core.implementation.tracing to - com.azure.core.management, // FIXME this should not be a long-term solution - com.azure.core.test, // FIXME this should not be a long-term solution - com.azure.core.amqp, // FIXME this should not be a long-term solution - com.azure.http.netty, // FIXME this should not be a long-term solution - com.azure.messaging.eventhubs, // FIXME this should not be a long-term solution - com.azure.messaging.eventhubs.checkpointstore.blob, // FIXME this should not be a long-term solution - com.azure.identity, // FIXME this should not be a long-term solution - com.azure.security.keyvault.keys, // FIXME this should not be a long-term solution - com.azure.security.keyvault.secrets, // FIXME this should not be a long-term solution - com.azure.storage.common, // FIXME this should not be a long-term solution - com.azure.core.tracing.opencensus, // FIXME this should not be a long-term solution - com.azure.storage.blob, // FIXME this should not be a long-term solution - com.azure.storage.file, // FIXME this should not be a long-term solution - com.azure.storage.queue; // FIXME this should not be a long-term solution exports com.azure.core.implementation.exception to com.azure.core.management, // FIXME this should not be a long-term solution com.azure.core.test, // FIXME this should not be a long-term solution diff --git a/sdk/core/azure-core/src/samples/java/com/azure/core/util/tracing/TracerJavaDocCodeSnippets.java b/sdk/core/azure-core/src/samples/java/com/azure/core/util/tracing/TracerJavaDocCodeSnippets.java new file mode 100644 index 000000000000..fab3db1a46b2 --- /dev/null +++ b/sdk/core/azure-core/src/samples/java/com/azure/core/util/tracing/TracerJavaDocCodeSnippets.java @@ -0,0 +1,164 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.core.util.tracing; + +import com.azure.core.util.Context; + +import static com.azure.core.util.tracing.Tracer.OPENCENSUS_SPAN_NAME_KEY; +import static com.azure.core.util.tracing.Tracer.ENTITY_PATH; +import static com.azure.core.util.tracing.Tracer.OPENCENSUS_SPAN_KEY; +import static com.azure.core.util.tracing.Tracer.HOST_NAME; +import static com.azure.core.util.tracing.Tracer.SPAN_CONTEXT; +import static com.azure.core.util.tracing.Tracer.DIAGNOSTIC_ID_KEY; + +/** + * Contains code snippets when generating javadocs through doclets for {@link Tracer}. + */ +public class TracerJavaDocCodeSnippets { + final Tracer tracer = new TracerImplementation(); + + /** + * Code snippet for {@link Tracer#start(String, Context, ProcessKind)} and {@link Tracer#start(String, Context)} + */ + public void startTracingSpan() { + // BEGIN: com.azure.core.util.tracing.start#string-context + // pass the current tracing span context to the calling method + Context traceContext = new Context(OPENCENSUS_SPAN_KEY, ""); + // start a new tracing span with the given method name and explicit parent span + Context updatedContext = tracer.start("azure.keyvault.secrets/setsecret", traceContext); + System.out.printf("Span returned in the context object: %s%n", + updatedContext.getData(OPENCENSUS_SPAN_KEY).get()); + // END: com.azure.core.util.tracing.start#string-context + + // BEGIN: com.azure.core.util.tracing.start#string-context-processKind-SEND + // pass the current tracing span and request metadata to the calling method + Context sendContext = new Context(OPENCENSUS_SPAN_KEY, "") + .addData(ENTITY_PATH, "entity-path").addData(HOST_NAME, "hostname"); + + // start a new tracing span with explicit parent, sets the request attributes on the span and sets the span + // kind to client when process kind SEND + Context updatedSendContext = tracer.start("azure.eventhubs.send", sendContext, ProcessKind.SEND); + System.out.printf("Span returned in the context object: %s%n", + updatedSendContext.getData(OPENCENSUS_SPAN_KEY).get()); + // END: com.azure.core.util.tracing.start#string-context-processKind-SEND + + // BEGIN: com.azure.core.util.tracing.start#string-context-processKind-RECEIVE + // start a new tracing span with explicit parent, sets the diagnostic Id (traceparent headers) on the current + // context when process kind RECEIVE + Context updatedReceiveContext = tracer.start("azure.eventhubs.receive", traceContext, + ProcessKind.RECEIVE); + System.out.printf("Diagnostic Id: %s%n", updatedReceiveContext.getData(DIAGNOSTIC_ID_KEY).get().toString()); + // END: com.azure.core.util.tracing.start#string-context-processKind-RECEIVE + + // BEGIN: com.azure.core.util.tracing.start#string-context-processKind-PROCESS + // start a new tracing span with remote parent and uses the span in the current context to return a scope + // when process kind PROCESS + Context processContext = new Context(OPENCENSUS_SPAN_KEY, "") + .addData(SPAN_CONTEXT, ""); + Context updatedProcessContext = tracer.start("azure.eventhubs.process", processContext, + ProcessKind.PROCESS); + System.out.printf("Scope: %s%n", updatedProcessContext.getData("scope").get()); + // END: com.azure.core.util.tracing.start#string-context-processKind-PROCESS + } + + /** + * Code snippet for {@link Tracer#end(int, Throwable, Context)} and {@link Tracer#end(String, Throwable, Context)} + */ + public void endTracingSpan() { + // BEGIN: com.azure.core.util.tracing.end#int-throwable-context + // context containing the current tracing span to end + Context traceContext = new Context(OPENCENSUS_SPAN_KEY, ""); + + // completes the tracing span with the passed response status code + tracer.end(200, null, traceContext); + // END: com.azure.core.util.tracing.end#int-throwable-context + + // BEGIN: com.azure.core.util.tracing.end#string-throwable-context + // context containing the current tracing span to end + // completes the tracing span with the passed status message + tracer.end("success", null, traceContext); + // END: com.azure.core.util.tracing.end#string-throwable-context + } + + /** + * Code snippet for {@link Tracer#setSpanName(String, Context)} + */ + public void setSpanName() { + // BEGIN: com.azure.core.util.tracing.setSpanName#string-context + // Sets the span name of the returned span on the context object, with key OPENCENSUS_SPAN_NAME_KEY + Context context = tracer.setSpanName("test-span-method", Context.NONE); + System.out.printf("Span name: %s%n", context.getData(OPENCENSUS_SPAN_NAME_KEY).get().toString()); + // END: com.azure.core.util.tracing.setSpanName#string-context + } + + /** + * Code snippet for {@link Tracer#addLink(Context)} + */ + public void addLink() { + // BEGIN: com.azure.core.util.tracing.addLink#context + // use the parent context containing the current tracing span to start a child span + Context parentContext = new Context(OPENCENSUS_SPAN_KEY, ""); + // use the returned span context information of the current tracing span to link + Context spanContext = tracer.start("test.method", parentContext, ProcessKind.RECEIVE); + + // Adds a link between multiple span's using the span context information of the Span + // For each event processed, add a link with the created spanContext + tracer.addLink(spanContext); + // END: com.azure.core.util.tracing.addLink#context + } + + /** + * Code snippet for {@link Tracer#extractContext(String, Context)} + */ + public void extractContext() { + // BEGIN: com.azure.core.util.tracing.extractContext#string-context + // Extracts the span context information from the passed diagnostic Id that can be used for linking spans. + Context spanContext = tracer.extractContext("valid-diagnostic-id", Context.NONE); + System.out.printf("Span context of the current tracing span: %s%n", spanContext.getData(SPAN_CONTEXT).get()); + // END: com.azure.core.util.tracing.extractContext#string-context + } + + //Noop Tracer + private static final class TracerImplementation implements Tracer { + @Override + public Context start(String methodName, Context context) { + return null; + } + + @Override + public Context start(String methodName, Context context, ProcessKind processKind) { + return null; + } + + @Override + public void end(int responseCode, Throwable error, Context context) { + + } + + @Override + public void end(String errorCondition, Throwable error, Context context) { + + } + + @Override + public void setAttribute(String key, String value, Context context) { + + } + + @Override + public Context setSpanName(String spanName, Context context) { + return null; + } + + @Override + public void addLink(Context context) { + + } + + @Override + public Context extractContext(String diagnosticId, Context context) { + return null; + } + } +} diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncProducer.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncProducer.java index 16c89abfdf89..21e641ef1f99 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncProducer.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncProducer.java @@ -11,7 +11,7 @@ import com.azure.core.amqp.implementation.MessageSerializer; import com.azure.core.amqp.implementation.TracerProvider; import com.azure.core.annotation.Immutable; -import com.azure.core.implementation.tracing.ProcessKind; +import com.azure.core.util.tracing.ProcessKind; import com.azure.core.implementation.util.ImplUtils; import com.azure.core.util.Context; import com.azure.core.util.logging.ClientLogger; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/implementation/PartitionPumpManager.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/implementation/PartitionPumpManager.java index 026c52bbfa64..c3e5adc00eec 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/implementation/PartitionPumpManager.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/implementation/PartitionPumpManager.java @@ -8,7 +8,7 @@ import com.azure.core.amqp.exception.AmqpException; import com.azure.core.amqp.implementation.TracerProvider; -import com.azure.core.implementation.tracing.ProcessKind; +import com.azure.core.util.tracing.ProcessKind; import com.azure.core.util.Context; import com.azure.core.util.logging.ClientLogger; import com.azure.messaging.eventhubs.CloseReason; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubAsyncProducerTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubAsyncProducerTest.java index 3e685cc0f5ff..bf53a5ae9055 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubAsyncProducerTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubAsyncProducerTest.java @@ -9,7 +9,7 @@ import com.azure.core.amqp.implementation.AmqpSendLink; import com.azure.core.amqp.implementation.MessageSerializer; import com.azure.core.amqp.implementation.TracerProvider; -import com.azure.core.implementation.tracing.ProcessKind; +import com.azure.core.util.tracing.ProcessKind; import com.azure.core.util.Context; import com.azure.core.util.tracing.Tracer; import com.azure.messaging.eventhubs.implementation.ClientConstants; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerTest.java index 6297f34fba7d..0072a183c799 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerTest.java @@ -10,7 +10,7 @@ import com.azure.core.amqp.implementation.AmqpSendLink; import com.azure.core.amqp.implementation.MessageSerializer; import com.azure.core.amqp.implementation.TracerProvider; -import com.azure.core.implementation.tracing.ProcessKind; +import com.azure.core.util.tracing.ProcessKind; import com.azure.core.util.Context; import com.azure.core.util.tracing.Tracer; import com.azure.messaging.eventhubs.implementation.ClientConstants; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorTest.java index 576992d7b826..5ab168148e45 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorTest.java @@ -22,7 +22,7 @@ import static org.mockito.Mockito.when; import com.azure.core.amqp.implementation.TracerProvider; -import com.azure.core.implementation.tracing.ProcessKind; +import com.azure.core.util.tracing.ProcessKind; import com.azure.core.util.Context; import com.azure.core.util.tracing.Tracer; import com.azure.messaging.eventhubs.models.EventHubConsumerOptions; diff --git a/sdk/tracing/azure-core-tracing-opencensus/CHANGELOG.md b/sdk/tracing/azure-core-tracing-opencensus/CHANGELOG.md index b23006fe5f56..98a9a77ed70d 100644 --- a/sdk/tracing/azure-core-tracing-opencensus/CHANGELOG.md +++ b/sdk/tracing/azure-core-tracing-opencensus/CHANGELOG.md @@ -1,5 +1,19 @@ -## Version 1.0.0-preview.1: +# Release History +## Version 1.0.0-preview.3 (2019-10-07) +For details on the Azure SDK for Java (October 2019 Preview) release refer to the [release announcement](https://aka.ms/azure-sdk-preview3-java). + +Version 1.0.0-preview.3 added tracing support for AMQP client libraries across different languages and platforms as possible. +See this package's + [documentation](https://github.com/Azure/azure-sdk-for-java/tree/master/sdk/tracing/azure-core-tracing-opencensus/README.md) and + [samples](https://github.com/Azure/azure-sdk-for-java/tree/master/sdk/tracing/azure-core-tracing-opencensus/src/samples/java/com/azure/core/tracing/opencensus) demonstrate the new API. + +## Version 1.0.0-preview.2 (2019-09-09) +For details on the Azure SDK for Java (August 2019 Preview) release refer to the [release announcement](https://aka.ms/azure-sdk-preview2-java). + +Version 1.0.0-preview.2 added tracing support to all of the HTTP based Azure SDK Java libraries. + +## Version 1.0.0-preview.1 Version 1.0.0-preview.1 is the first preview of our efforts to provide low level interfaces and helper methods to support tracing for Java client libraries. This library includes [OpenTelemetry](https://opentelemetry.io/) implementation of the interface, For more information about this, and preview releases of other Azure SDK libraries, please visit https://aka.ms/azure-sdk-preview2-java. diff --git a/sdk/tracing/azure-core-tracing-opencensus/pom.xml b/sdk/tracing/azure-core-tracing-opencensus/pom.xml index 5642787fc404..ea3266750f80 100644 --- a/sdk/tracing/azure-core-tracing-opencensus/pom.xml +++ b/sdk/tracing/azure-core-tracing-opencensus/pom.xml @@ -48,6 +48,11 @@ 0.20.0 test + + junit + junit + test + com.azure azure-storage-queue diff --git a/sdk/tracing/azure-core-tracing-opencensus/src/main/java/com/azure/core/tracing/opencensus/OpenCensusTracer.java b/sdk/tracing/azure-core-tracing-opencensus/src/main/java/com/azure/core/tracing/opencensus/OpenCensusTracer.java index 63a186ced860..acde457e5583 100644 --- a/sdk/tracing/azure-core-tracing-opencensus/src/main/java/com/azure/core/tracing/opencensus/OpenCensusTracer.java +++ b/sdk/tracing/azure-core-tracing-opencensus/src/main/java/com/azure/core/tracing/opencensus/OpenCensusTracer.java @@ -3,7 +3,7 @@ package com.azure.core.tracing.opencensus; -import com.azure.core.implementation.tracing.ProcessKind; +import com.azure.core.util.tracing.ProcessKind; import com.azure.core.implementation.util.ImplUtils; import com.azure.core.tracing.opencensus.implementation.AmqpPropagationFormatUtil; import com.azure.core.tracing.opencensus.implementation.AmqpTraceUtil; @@ -19,52 +19,69 @@ import io.opencensus.trace.Tracer; import io.opencensus.trace.Tracing; +import java.util.Objects; import java.util.Optional; import static io.opencensus.trace.Link.Type.PARENT_LINKED_SPAN; /** - * OpenCensus span + * Basic tracing implementation class for use with REST and AMQP Service Clients to create {@link Span} and in-process + * context propagation. + * + *

+ * This helper class supports W3C distributed tracing protocol and injects SpanContext into the outgoing HTTP + * and AMQP requests. */ public class OpenCensusTracer implements com.azure.core.util.tracing.Tracer { // Singleton OpenCensus tracer capable of starting and exporting spans. private static final Tracer TRACER = Tracing.getTracer(); - // standard attributes with AMQP call information + // standard attributes with AMQP request private static final String COMPONENT = "component"; private static final String MESSAGE_BUS_DESTINATION = "message_bus.destination"; private static final String PEER_ENDPOINT = "peer.address"; private final ClientLogger logger = new ClientLogger(OpenCensusTracer.class); + /** + * {@inheritDoc} + */ @Override public Context start(String methodName, Context context) { - Span parentSpan = (Span) context.getData(OPENCENSUS_SPAN_KEY).orElse(TRACER.getCurrentSpan()); - String spanName = (String) context.getData(OPENCENSUS_SPAN_NAME_KEY).orElse(methodName); + Objects.requireNonNull(methodName, "'methodName' cannot be null."); + Objects.requireNonNull(context, "'context' cannot be null."); - SpanBuilder spanBuilder = TRACER.spanBuilderWithExplicitParent(spanName, parentSpan); + SpanBuilder spanBuilder = getSpanBuilder(methodName, context); Span span = spanBuilder.startSpan(); return context.addData(OPENCENSUS_SPAN_KEY, span); } + /** + * {@inheritDoc} + */ @Override public Context start(String spanName, Context context, ProcessKind processKind) { + Objects.requireNonNull(spanName, "'methodName' cannot be null."); + Objects.requireNonNull(context, "'context' cannot be null."); + Objects.requireNonNull(processKind, "'processKind' cannot be null."); + Span span; SpanBuilder spanBuilder; + switch (processKind) { case SEND: - spanBuilder = startSpanWithExplicitParent(spanName, context); + spanBuilder = getSpanBuilder(spanName, context); span = spanBuilder.setSpanKind(Span.Kind.CLIENT).startSpan(); if (span.getOptions().contains(Span.Options.RECORD_EVENTS)) { - // If span is sampled in, add additional TRACING attributes + // If span is sampled in, add additional request attributes addSpanRequestAttributes(span, context, spanName); } return context.addData(OPENCENSUS_SPAN_KEY, span); case RECEIVE: - spanBuilder = startSpanWithExplicitParent(spanName, context); + spanBuilder = getSpanBuilder(spanName, context); span = spanBuilder.startSpan(); - // Add diagnostic Id to Context + // Add diagnostic Id and traceheaders to Context context = setContextData(span); return context.addData(OPENCENSUS_SPAN_KEY, span); case PROCESS: @@ -74,8 +91,12 @@ public Context start(String spanName, Context context, ProcessKind processKind) } } + /** + * {@inheritDoc} + */ @Override public void end(int responseCode, Throwable throwable, Context context) { + Objects.requireNonNull(context, "'context' cannot be null"); final Span span = getSpan(context); if (span == null) { return; @@ -88,6 +109,9 @@ public void end(int responseCode, Throwable throwable, Context context) { span.end(); } + /** + * {@inheritDoc} + */ @Override public void setAttribute(String key, String value, Context context) { if (ImplUtils.isNullOrEmpty(value)) { @@ -103,11 +127,17 @@ public void setAttribute(String key, String value, Context context) { } } + /** + * {@inheritDoc} + */ @Override public Context setSpanName(String spanName, Context context) { return context.addData(OPENCENSUS_SPAN_NAME_KEY, spanName); } + /** + * {@inheritDoc} + */ @Override public void end(String statusMessage, Throwable throwable, Context context) { final Span span = getSpan(context); @@ -123,103 +153,140 @@ public void end(String statusMessage, Throwable throwable, Context context) { span.end(); } + /** + * {@inheritDoc} + */ @Override - public void addLink(Context eventContext) { - final Span span = getSpan(eventContext); + public void addLink(Context context) { + final Span span = getSpan(context); if (span == null) { logger.warning("Failed to find span to link it."); return; } - final Optional spanContextOptional = eventContext.getData(SPAN_CONTEXT); - if (!spanContextOptional.isPresent()) { - logger.warning("Failed to find Span context to link it."); - return; - } else if (!(spanContextOptional.get() instanceof SpanContext)) { - logger.warning("Context in event is not of type SpanContext. Actual: {}", - spanContextOptional.get().getClass()); + final SpanContext spanContext = getSpanContext(context); + if (spanContext == null) { + logger.warning("Failed to find span context to link it."); return; } - - final SpanContext spanContext = (SpanContext) spanContextOptional.get(); - // TODO: Needs to be updated with Open Telemetry support to addLink using Span Context before span is started // and no link type is needed. span.addLink(Link.fromSpanContext(spanContext, PARENT_LINKED_SPAN)); } + /** + * {@inheritDoc} + */ @Override public Context extractContext(String diagnosticId, Context context) { return AmqpPropagationFormatUtil.extractContext(diagnosticId, context); } + /** + * Starts a new child {@link Span} with parent being the remote and uses the {@link Span} is in the current Context, + * to return an object that represents that scope. + *

The scope is exited when the returned object is closed.

+ * + * @param spanName The name of the returned Span. + * @param context The {@link Context} containing the {@link SpanContext}. + * @return The returned {@link Span} and the scope in a {@link Context} object. + */ private Context startScopedSpan(String spanName, Context context) { + Objects.requireNonNull(spanName, "'spanName' cannot be null."); + Objects.requireNonNull(context, "'context' cannot be null."); Span span; - Optional optionalSpanContext = context.getData(SPAN_CONTEXT); - if (optionalSpanContext.isPresent() && optionalSpanContext.get() instanceof SpanContext) { - span = startSpanWithRemoteParent(spanName, (SpanContext) optionalSpanContext.get()); + SpanContext spanContext = getSpanContext(context); + if (spanContext != null) { + span = startSpanWithRemoteParent(spanName, spanContext); } else { - SpanBuilder spanBuilder = startSpanWithExplicitParent(spanName, context); + SpanBuilder spanBuilder = getSpanBuilder(spanName, context); span = spanBuilder.setSpanKind(Span.Kind.SERVER).startSpan(); } return context.addData(OPENCENSUS_SPAN_KEY, span).addData("scope", TRACER.withSpan(span)); } - private SpanBuilder startSpanWithExplicitParent(String spanName, Context context) { - Optional optionalSpanKey = context.getData(OPENCENSUS_SPAN_KEY); - Optional optionalSpanNameKey = context.getData(OPENCENSUS_SPAN_NAME_KEY); - Span parentSpan = null; - String spanNameKey = null; - - if (!optionalSpanNameKey.isPresent()) { - spanNameKey = spanName; - } else if (optionalSpanKey.isPresent() && optionalSpanNameKey.get() instanceof String) { - spanNameKey = (String) optionalSpanNameKey.get(); - } else { - logger.warning("Span name type is not of type String, but type: {}. Failed to add span links.", - optionalSpanNameKey.get() != null ? optionalSpanNameKey.get().getClass() : "null"); - } - - if (optionalSpanKey.get() instanceof Span) { - parentSpan = (Span) context.getData(OPENCENSUS_SPAN_KEY).orElse(TRACER.getCurrentSpan()); - } else { - logger.warning("Parent span type is not of type Span, but type: {}. Failed to add span links.", - optionalSpanKey.get() != null ? optionalSpanKey.get().getClass() : "null"); - } - - SpanBuilder spanBuilder = TRACER.spanBuilderWithExplicitParent(spanNameKey, parentSpan); - return spanBuilder; - } - + /** + * Creates a {@link SpanBuilder} to create and start a new child {@link Span} with parent being the remote and + * designated by the {@link SpanContext}. + * + * @param spanName The name of the returned Span. + * @param spanContext The remote parent context of the returned Span. + * @return A {@link Span} with parent being the remote {@link Span} designated by the {@link SpanContext}. + */ private Span startSpanWithRemoteParent(String spanName, SpanContext spanContext) { SpanBuilder spanBuilder = TRACER.spanBuilderWithRemoteParent(spanName, spanContext); spanBuilder.setSpanKind(Span.Kind.SERVER); return spanBuilder.startSpan(); - } + /** + * Extracts the {@link SpanContext trace identifiers} and the {@link SpanContext} of the current tracing span as + * text and returns in a {@link Context} object. + * + * @param span The current tracing span. + * @return The {@link Context} containing the {@link SpanContext} and traceparent of the current span. + */ private Context setContextData(Span span) { - final String traceparent = AmqpPropagationFormatUtil.getDiagnosticId(span.getContext()); - Context parentContext = new Context(DIAGNOSTIC_ID_KEY, traceparent).addData(SPAN_CONTEXT, span.getContext()); - return parentContext; + SpanContext spanContext = span.getContext(); + final String traceparent = AmqpPropagationFormatUtil.getDiagnosticId(spanContext); + return new Context(DIAGNOSTIC_ID_KEY, traceparent).addData(SPAN_CONTEXT, spanContext); } - private static void addSpanRequestAttributes(Span span, Context context, String spanName) { - if (context.getData(ENTITY_PATH).isPresent() && context.getData(HOST_NAME).isPresent()) { - span.putAttribute(COMPONENT, AttributeValue.stringAttributeValue(parseComponentValue(spanName))); - span.putAttribute( - MESSAGE_BUS_DESTINATION, - AttributeValue.stringAttributeValue(context.getData(ENTITY_PATH).get().toString())); - span.putAttribute( - PEER_ENDPOINT, - AttributeValue.stringAttributeValue(context.getData(HOST_NAME).get().toString())); - } + /** + * Extracts request attributes from the given {@code context} and adds it to the started span. + * + * @param span The span to which request attributes are to be added. + * @param context The context containing the request attributes. + * @param spanName The name of the returned Span containing the component value. + */ + private void addSpanRequestAttributes(Span span, Context context, String spanName) { + Objects.requireNonNull(span, "'span' cannot be null."); + + span.putAttribute(COMPONENT, AttributeValue.stringAttributeValue(parseComponentValue(spanName))); + span.putAttribute( + MESSAGE_BUS_DESTINATION, + AttributeValue.stringAttributeValue(getRequestKeyAttribute(context, ENTITY_PATH))); + span.putAttribute( + PEER_ENDPOINT, + AttributeValue.stringAttributeValue(getRequestKeyAttribute(context, HOST_NAME))); } + /** + * Extracts component name from the given span name. + * + * @param spanName The spanName containing the component name. + * @return The component name contained in the context. + */ private static String parseComponentValue(String spanName) { return spanName.substring(spanName.indexOf(".") + 1, spanName.lastIndexOf(".")); } + /** + * Extracts request attributes from the given {@code context} and provided key. + * + * @param context The context containing the entity path. + * @param key The name of the attribute that needs to be extracted from the {@code Context}. + * @return The value for the provided key contained in the context. + */ + private String getRequestKeyAttribute(Context context, String key) { + final Optional optionalObject = context.getData(key); + + if (!optionalObject.isPresent()) { + logger.warning("Failed to find {} in the context.", key); + return ""; + } + + final Object value = optionalObject.get(); + if (!(value instanceof String)) { + logger.warning("Could not extract {}. Data is not of type String. Actual class: {}", + key, + value.getClass()); + return ""; + } + + return value.toString(); + } + /** * Extracts a {@link Span} from the given {@code context}. * @@ -243,4 +310,66 @@ private Span getSpan(Context context) { return (Span) value; } + + /** + * Extracts the span name from the given {@code context}. + * + * @param context The context containing the span name. + * @return The span name contained in the context, and {@code null} if it does not. + */ + private String getSpanName(Context context) { + final Optional spanNameOptional = context.getData(OPENCENSUS_SPAN_NAME_KEY); + if (!spanNameOptional.isPresent()) { + logger.warning("Failed to find span name in the context."); + return null; + } + + final Object value = spanNameOptional.get(); + if (!(value instanceof String)) { + logger.warning("Could not extract span name. Data in {} is not of type String. Actual class: {}", + OPENCENSUS_SPAN_NAME_KEY, + value.getClass()); + return null; + } + + return value.toString(); + } + + /** + * Extracts a {@link SpanContext} from the given {@code context}. + * + * @param context The context containing the span context. + * @return The {@link SpanContext} contained in the context, and {@code null} if it does not. + */ + private SpanContext getSpanContext(Context context) { + final Optional spanContextOptional = context.getData(SPAN_CONTEXT); + if (!spanContextOptional.isPresent()) { + logger.warning("Failed to find span context in the context."); + return null; + } + + final Object value = spanContextOptional.get(); + if (!(value instanceof SpanContext)) { + logger.warning("Could not extract span context. Data is not of type SpanContext. Actual class: {}", + value.getClass()); + return null; + } + + return (SpanContext) value; + } + + /** + * Returns a {@link SpanBuilder} to create and start a new child {@link Span} with parent being the designated + * {@code Span}. + * + * @param spanName The name of the returned Span. + * @param context The context containing the span and the span name. + * @return A {@code SpanBuilder} to create and start a new {@code Span}. + */ + private SpanBuilder getSpanBuilder(String spanName, Context context) { + Span parentSpan = getSpan(context) == null ? TRACER.getCurrentSpan() : getSpan(context); + String spanNameKey = getSpanName(context) == null ? spanName : getSpanName(context); + SpanBuilder spanBuilder = TRACER.spanBuilderWithExplicitParent(spanNameKey, parentSpan); + return spanBuilder; + } } diff --git a/sdk/tracing/azure-core-tracing-opencensus/src/main/java/com/azure/core/tracing/opencensus/implementation/AmqpPropagationFormatUtil.java b/sdk/tracing/azure-core-tracing-opencensus/src/main/java/com/azure/core/tracing/opencensus/implementation/AmqpPropagationFormatUtil.java index 7f8e99c77524..4c54407e5849 100644 --- a/sdk/tracing/azure-core-tracing-opencensus/src/main/java/com/azure/core/tracing/opencensus/implementation/AmqpPropagationFormatUtil.java +++ b/sdk/tracing/azure-core-tracing-opencensus/src/main/java/com/azure/core/tracing/opencensus/implementation/AmqpPropagationFormatUtil.java @@ -11,6 +11,8 @@ import io.opencensus.trace.TraceOptions; import io.opencensus.trace.Tracestate; +import java.util.Objects; + public class AmqpPropagationFormatUtil { private AmqpPropagationFormatUtil() { } @@ -33,11 +35,13 @@ public static Context extractContext(String diagnosticId, Context context) { * for more information on the conversion of these fields to Span Context format. * * @param spanContext is a specification defines an agreed-upon format for the exchange of trace context propagation - * data - * @retrun The dignostic Id providing an unique identifier for individual traces and requests, + * data. + * @return The dignostic Id providing an unique identifier for individual traces and requests, * allowing trace data of multiple providers to be linked together. + * @throws NullPointerException if {@code spanContext} is {@code null}. */ public static String getDiagnosticId(SpanContext spanContext) { + Objects.requireNonNull(spanContext, "'spanContext' cannot be null"); char[] chars = new char[55]; chars[0] = '0'; chars[1] = '0'; diff --git a/sdk/tracing/azure-core-tracing-opencensus/src/test/java/com/azure/core/tracing/opencensus/OpenCensusTracerTest.java b/sdk/tracing/azure-core-tracing-opencensus/src/test/java/com/azure/core/tracing/opencensus/OpenCensusTracerTest.java new file mode 100644 index 000000000000..823cc5397f56 --- /dev/null +++ b/sdk/tracing/azure-core-tracing-opencensus/src/test/java/com/azure/core/tracing/opencensus/OpenCensusTracerTest.java @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.core.tracing.opencensus; + +import com.azure.core.util.tracing.ProcessKind; +import com.azure.core.tracing.opencensus.implementation.AmqpPropagationFormatUtil; +import com.azure.core.util.Context; +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanContext; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static com.azure.core.util.tracing.Tracer.DIAGNOSTIC_ID_KEY; +import static com.azure.core.util.tracing.Tracer.OPENCENSUS_SPAN_KEY; +import static com.azure.core.util.tracing.Tracer.SPAN_CONTEXT; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNotNull; +import static junit.framework.TestCase.assertTrue; + +// TODO: samvaity - Need to add integration test - https://github.com/Azure/azure-sdk-for-java/issues/5156 +public class OpenCensusTracerTest { + private static final String METHOD_NAME = "Azure.eventhubs.send"; + private OpenCensusTracer openCensusTracer; + + @Before + public void setup() { + openCensusTracer = new OpenCensusTracer(); + } + + @Test(expected = NullPointerException.class) + public void startSpanNullPointerException() { + // Act + openCensusTracer.start("", null); + } + + @Test + public void startSpanReturnsNewSpanTest() { + // Act + final Context updatedContext = openCensusTracer.start(METHOD_NAME, Context.NONE); + + // Assert + Assert.assertNotNull(updatedContext.getData(OPENCENSUS_SPAN_KEY)); + assertTrue(updatedContext.getData(OPENCENSUS_SPAN_KEY).get() instanceof Span); + } + + @Test(expected = NullPointerException.class) + public void startSpanOverloadNullPointerException() { + // Act + openCensusTracer.start("", Context.NONE, null); + } + + @Test + public void startSpanSendOperation() { + // Act + final Context updatedContext = openCensusTracer.start(METHOD_NAME, Context.NONE, ProcessKind.SEND); + + // Assert + assertTrue(updatedContext.getData(OPENCENSUS_SPAN_KEY).get() instanceof Span); + } + + @Test + public void startSpanReceiveOperation() { + // Act + final Context returnedContext = openCensusTracer.start(METHOD_NAME, Context.NONE, ProcessKind.RECEIVE); + + // Assert + assertTrue(returnedContext.getData(OPENCENSUS_SPAN_KEY).get() instanceof Span); + assertNotNull(returnedContext.getData(DIAGNOSTIC_ID_KEY)); + assertNotNull(returnedContext.getData(SPAN_CONTEXT)); + String diagnosticId = (String) returnedContext.getData(DIAGNOSTIC_ID_KEY).get(); + SpanContext returnedSpanContext = (SpanContext) returnedContext.getData(SPAN_CONTEXT).get(); + // validate the span context and diagnostic Id are the same + assertEquals(diagnosticId, AmqpPropagationFormatUtil.getDiagnosticId(returnedSpanContext)); + } +} diff --git a/sdk/tracing/azure-core-tracing-opencensus/src/test/java/com/azure/core/tracing/opencensus/implementation/AmqpPropagationFormatUtilTest.java b/sdk/tracing/azure-core-tracing-opencensus/src/test/java/com/azure/core/tracing/opencensus/implementation/AmqpPropagationFormatUtilTest.java new file mode 100644 index 000000000000..6e8017d223d0 --- /dev/null +++ b/sdk/tracing/azure-core-tracing-opencensus/src/test/java/com/azure/core/tracing/opencensus/implementation/AmqpPropagationFormatUtilTest.java @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.core.tracing.opencensus.implementation; + +import com.azure.core.util.Context; +import io.opencensus.trace.*; +import org.junit.Assert; +import org.junit.Test; + +import static com.azure.core.util.tracing.Tracer.SPAN_CONTEXT; + +public class AmqpPropagationFormatUtilTest { + + @Test + public void extractContextReturnsSpanContext() { + // Act + Context context = AmqpPropagationFormatUtil.extractContext("", Context.NONE); + + // Assert + Assert.assertNotNull(context); + Assert.assertTrue(context.getData(SPAN_CONTEXT).isPresent()); + } + + @Test + public void getInvalidSpanContext() { + // Act + Context context = AmqpPropagationFormatUtil.extractContext("", Context.NONE); + + // Assert + Assert.assertNotNull(context); + Assert.assertFalse("Invalid diagnostic Id, returns invalid SpanContext ", + ((SpanContext) context.getData(SPAN_CONTEXT).get()).getTraceId().isValid()); + } + + @Test + public void getValidSpanContext() { + // Act + Context context = AmqpPropagationFormatUtil.extractContext("00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", Context.NONE); + + // Assert + Assert.assertNotNull(context); + Assert.assertTrue("Valid diagnostic Id, returns valid SpanContext ", + ((SpanContext) context.getData(SPAN_CONTEXT).get()).getTraceId().isValid()); + } + + @Test + public void getValidDiagnosticId() { + //Arrange + final String testDiagnosticID = "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01"; + final Context context = AmqpPropagationFormatUtil.extractContext(testDiagnosticID, Context.NONE); + final SpanContext spanContext = (SpanContext) context.getData(SPAN_CONTEXT).get(); + + // Act + String diagnosticId = AmqpPropagationFormatUtil.getDiagnosticId(spanContext); + + // Assert + Assert.assertNotNull(diagnosticId); + Assert.assertEquals(testDiagnosticID, diagnosticId); + } +} diff --git a/sdk/tracing/azure-core-tracing-opencensus/src/test/java/com/azure/core/tracing/opencensus/implementation/AmqpTraceUtilTest.java b/sdk/tracing/azure-core-tracing-opencensus/src/test/java/com/azure/core/tracing/opencensus/implementation/AmqpTraceUtilTest.java new file mode 100644 index 000000000000..67903337bbd6 --- /dev/null +++ b/sdk/tracing/azure-core-tracing-opencensus/src/test/java/com/azure/core/tracing/opencensus/implementation/AmqpTraceUtilTest.java @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.core.tracing.opencensus.implementation; + +import io.opencensus.trace.Status; +import org.junit.Assert; +import org.junit.Test; + +public class AmqpTraceUtilTest { + + @Test + public void parseUnknownStatusMessage() { + // Act + + Status status = AmqpTraceUtil.parseStatusMessage("", null); + + // Assert + Assert.assertNotNull(status); + Assert.assertEquals(Status.UNKNOWN.withDescription(""), status); + } + + @Test + public void parseSuccessStatusMessage() { + // Act + + Status status = AmqpTraceUtil.parseStatusMessage("success", null); + + // Assert + Assert.assertNotNull(status); + Assert.assertEquals(Status.OK, status); + } + + @Test + public void parseStatusMessageOnError() { + // Act + + Status status = AmqpTraceUtil.parseStatusMessage("", new Error("testError")); + + // Assert + Assert.assertNotNull(status); + Assert.assertEquals(Status.UNKNOWN.withDescription("testError"), status); + } +} diff --git a/sdk/tracing/azure-core-tracing-opencensus/src/test/java/com/azure/core/tracing/opencensus/implementation/HttpTraceUtilTest.java b/sdk/tracing/azure-core-tracing-opencensus/src/test/java/com/azure/core/tracing/opencensus/implementation/HttpTraceUtilTest.java new file mode 100644 index 000000000000..734ef156ec8c --- /dev/null +++ b/sdk/tracing/azure-core-tracing-opencensus/src/test/java/com/azure/core/tracing/opencensus/implementation/HttpTraceUtilTest.java @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.core.tracing.opencensus.implementation; + +import io.opencensus.trace.Status; +import org.junit.Assert; +import org.junit.Test; + +public class HttpTraceUtilTest { + @Test + public void parseUnknownStatusCode() { + // Act + + Status status = HttpTraceUtil.parseResponseStatus(1, null); + + // Assert + Assert.assertNotNull(status); + Assert.assertEquals(Status.UNKNOWN.withDescription(null), status); + } + + @Test + public void parseUnauthenticatedStatusCode() { + //Arrange + final String errorMessage = "unauthenticated test user"; + + // Act + Status status = HttpTraceUtil.parseResponseStatus(401, new Error(errorMessage)); + + // Assert + Assert.assertNotNull(status); + Assert.assertEquals(Status.UNAUTHENTICATED.withDescription(errorMessage), status); + } + + @Test + public void parseNullError() { + // Act + Status status = HttpTraceUtil.parseResponseStatus(504, null); + + // Assert + Assert.assertNotNull(status); + Assert.assertEquals(Status.DEADLINE_EXCEEDED.withDescription(null), status); + } +} diff --git a/sdk/tracing/ci.yml b/sdk/tracing/ci.yml index d43cfa04b30d..0ccbc2036fa6 100644 --- a/sdk/tracing/ci.yml +++ b/sdk/tracing/ci.yml @@ -38,6 +38,6 @@ stages: parameters: ServiceDirectory: tracing Artifacts: - - name: tracing-opentelemetry - safeName: tracingopentelemetry - stagingProfileId: 88192f04117501 \ No newline at end of file + - name: azure-core-tracing-opencensus + safeName: azurecoretracingopencensus + stagingProfileId: 88192f04117501