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, "+ * 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