com.azure.messaging.eventhubs.implementation.instrumentation.EventHubsTracer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of azure-messaging-eventhubs Show documentation
Show all versions of azure-messaging-eventhubs Show documentation
Libraries built on Microsoft Azure Event Hubs
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.messaging.eventhubs.implementation.instrumentation;
import com.azure.core.amqp.exception.AmqpException;
import com.azure.core.util.Configuration;
import com.azure.core.util.Context;
import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.tracing.ProcessKind;
import com.azure.core.util.tracing.SpanKind;
import com.azure.core.util.tracing.Tracer;
import com.azure.messaging.eventhubs.EventData;
import com.azure.messaging.eventhubs.models.PartitionEvent;
import org.apache.qpid.proton.message.Message;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.ServiceLoader;
import static com.azure.core.util.tracing.Tracer.DIAGNOSTIC_ID_KEY;
import static com.azure.core.util.tracing.Tracer.MESSAGE_ENQUEUED_TIME;
import static com.azure.core.util.tracing.Tracer.SPAN_CONTEXT_KEY;
import static com.azure.messaging.eventhubs.implementation.ClientConstants.AZ_NAMESPACE_VALUE;
public class EventHubsTracer {
private static final AutoCloseable NOOP_AUTOCLOSEABLE = () -> {
};
public static final String REACTOR_PARENT_TRACE_CONTEXT_KEY = "otel-context-key";
public static final String TRACEPARENT_KEY = "traceparent";
private static final ClientLogger LOGGER = new ClientLogger(EventHubsTracer.class);
private static final boolean IS_TRACING_DISABLED = Configuration.getGlobalConfiguration().get(Configuration.PROPERTY_AZURE_TRACING_DISABLED, false);
protected final Tracer tracer;
private final String fullyQualifiedName;
private final String entityName;
public EventHubsTracer(Tracer tracer, String fullyQualifiedName, String entityName) {
this.tracer = IS_TRACING_DISABLED ? null : tracer;
this.fullyQualifiedName = Objects.requireNonNull(fullyQualifiedName, "'fullyQualifiedName' cannot be null");
this.entityName = Objects.requireNonNull(entityName, "'entityPath' cannot be null");
}
public static Tracer getDefaultTracer() {
Iterable tracers = ServiceLoader.load(Tracer.class);
Iterator it = tracers.iterator();
return it.hasNext() ? it.next() : null;
}
public boolean isEnabled() {
return tracer != null;
}
public Context startSpan(String spanName, Context context, ProcessKind kind) {
return tracer == null ? context : tracer.start(spanName, context, kind);
}
public Mono traceMono(Mono publisher, String spanName) {
if (tracer != null) {
return publisher
.doOnEach(signal -> {
if (signal.isOnComplete() || signal.isOnError()) {
Context span = signal.getContextView().getOrDefault(REACTOR_PARENT_TRACE_CONTEXT_KEY, Context.NONE);
endSpan(signal.getThrowable(), span, null);
}
})
.contextWrite(reactor.util.context.Context.of(REACTOR_PARENT_TRACE_CONTEXT_KEY,
tracer.start(spanName, setAttributes(Context.NONE), ProcessKind.SEND)));
}
return publisher;
}
public void endSpan(Throwable throwable, Context span, AutoCloseable scope) {
if (tracer != null) {
String errorCondition = "success";
if (throwable instanceof AmqpException) {
AmqpException exception = (AmqpException) throwable;
errorCondition = exception.getErrorCondition().getErrorCondition();
}
try {
if (scope != null) {
scope.close();
}
} catch (Exception e) {
LOGGER.warning("Can't close scope", e);
} finally {
tracer.end(errorCondition, throwable, span);
}
}
}
/**
* Used in ServiceBusMessageBatch.tryAddMessage() to start tracing for to-be-sent out messages.
*/
public void reportMessageSpan(EventData eventData, Context eventContext) {
if (tracer == null || eventContext == null || eventContext.getData(SPAN_CONTEXT_KEY).isPresent()) {
// if message has context (in case of retries), don't start a message span or add a new context
return;
}
String traceparent = EventHubsTracer.getTraceparent(eventData.getProperties());
if (traceparent != null) {
// if message has context (in case of retries) or if user supplied it, don't start a message span or add a new context
return;
}
// Starting the span makes the sampling decision (nothing is logged at this time)
Context newMessageContext = setAttributes(eventContext);
Context eventSpanContext = tracer.start("EventHubs.message", newMessageContext, ProcessKind.MESSAGE);
Optional
© 2015 - 2024 Weber Informatics LLC | Privacy Policy