001package io.prometheus.metrics.tracer.otel_agent;
002
003import io.opentelemetry.api.trace.Span;
004import io.opentelemetry.api.trace.SpanId;
005import io.opentelemetry.api.trace.TraceId;
006import io.prometheus.metrics.tracer.common.SpanContext;
007
008/**
009 * This is exactly the same as the {@code OpenTelemetrySpanContextSupplier}.
010 * However, the {@code io.opentelemetry.api} package is relocated to
011 * {@code io.opentelemetry.javaagent.shaded.io.opentelemetry.api} in the OpenTelemetry agent.
012 */
013public class OpenTelemetryAgentSpanContext implements SpanContext {
014
015  public static boolean isAvailable() {
016    try {
017      OpenTelemetryAgentSpanContext test = new OpenTelemetryAgentSpanContext();
018      test.getCurrentSpanId();
019      test.getCurrentTraceId();
020      test.isCurrentSpanSampled();
021      return true;
022    } catch (LinkageError ignored) {
023      // NoClassDefFoundError:
024      //   Either OpenTelemetry is not present, or it is version 0.9.1 or older when io.opentelemetry.api.trace.Span did not exist.
025      // IncompatibleClassChangeError:
026      //   The application uses an OpenTelemetry version between 0.10.0 and 0.15.0 when SpanContext was a class, and not an interface.
027      return false;
028    }
029  }
030
031  @Override
032  public String getCurrentTraceId() {
033    String traceId = Span.current().getSpanContext().getTraceId();
034    return TraceId.isValid(traceId) ? traceId : null;
035  }
036
037  @Override
038  public String getCurrentSpanId() {
039    String spanId = Span.current().getSpanContext().getSpanId();
040    return SpanId.isValid(spanId) ? spanId : null;
041  }
042
043  @Override
044  public boolean isCurrentSpanSampled() {
045    return Span.current().getSpanContext().isSampled();
046  }
047
048  @Override
049  public void markCurrentSpanAsExemplar() {
050    Span.current().setAttribute(EXEMPLAR_ATTRIBUTE_NAME, EXEMPLAR_ATTRIBUTE_VALUE);
051  }
052}