Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
Comparing source compatibility of opentelemetry-sdk-trace-1.58.0-SNAPSHOT.jar against opentelemetry-sdk-trace-1.57.0.jar
No changes.
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.trace.export.BatchSpanProcessorBuilder (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.trace.export.BatchSpanProcessorBuilder setInternalTelemetryVersion(io.opentelemetry.sdk.common.InternalTelemetryVersion)
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) STATIC(+) io.opentelemetry.sdk.trace.export.SpanProcessorMetrics$LongCallable (not serializable)
Comment thread
jack-berg marked this conversation as resolved.
Outdated
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) long get()
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.opentelemetry.sdk.trace.export.BatchSpanProcessorBuilder;
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.internal.SdkTracerProviderUtil;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import java.io.Closeable;
import java.time.Duration;
Expand Down Expand Up @@ -49,6 +50,7 @@ static void configureTracerProvider(
List<Closeable> closeables) {

tracerProviderBuilder.setSpanLimits(configureSpanLimits(config));
SdkTracerProviderUtil.setMeterProvider(tracerProviderBuilder, meterProvider);

String sampler = config.getString("otel.traces.sampler", PARENTBASED_ALWAYS_ON);
tracerProviderBuilder.setSampler(
Expand Down Expand Up @@ -80,7 +82,10 @@ static List<SpanProcessor> configureSpanProcessors(
for (String simpleProcessorExporterNames : simpleProcessorExporterNames) {
SpanExporter exporter = exportersByNameCopy.remove(simpleProcessorExporterNames);
if (exporter != null) {
SpanProcessor spanProcessor = SimpleSpanProcessor.create(exporter);
SpanProcessor spanProcessor =
SdkTracerProviderUtil.setMeterProvider(
SimpleSpanProcessor.builder(exporter), meterProvider)
.build();
closeables.add(spanProcessor);
spanProcessors.add(spanProcessor);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessorBuilder;
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessorBuilder;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.internal.SdkTracerProviderUtil;
import java.time.Duration;
import java.util.Map;

Expand Down Expand Up @@ -62,7 +64,12 @@ public SpanProcessor create(SpanProcessorModel model, DeclarativeConfigContext c
FileConfigUtil.requireNonNull(
simpleModel.getExporter(), "simple span processor exporter");
SpanExporter spanExporter = SpanExporterFactory.getInstance().create(exporterModel, context);
return context.addCloseable(SimpleSpanProcessor.create(spanExporter));
SimpleSpanProcessorBuilder builder = SimpleSpanProcessor.builder(spanExporter);
MeterProvider meterProvider = context.getMeterProvider();
if (meterProvider != null) {
SdkTracerProviderUtil.setMeterProvider(builder, meterProvider);
}
return context.addCloseable(builder.build());
}

Map.Entry<String, Object> keyValue =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,8 @@ void create_Configured() throws NoSuchFieldException, IllegalAccessException {
.extracting("sharedState")
.extracting("activeSpanProcessor")
.extracting("worker")
.extracting("processedSpansCounter")
.extracting("spanProcessorMetrics")
.extracting("processedSpans")
.extracting("sdkMeter")
.extracting("meterProviderSharedState")
.isEqualTo(sharedState);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ final class ExtendedSdkSpanBuilder extends SdkSpanBuilder implements ExtendedSpa
String spanName,
InstrumentationScopeInfo instrumentationScopeInfo,
TracerSharedState tracerSharedState,
SpanLimits spanLimits) {
super(spanName, instrumentationScopeInfo, tracerSharedState, spanLimits);
SpanLimits spanLimits,
SdkTracerMetrics tracerProviderMetrics) {
super(spanName, instrumentationScopeInfo, tracerSharedState, spanLimits, tracerProviderMetrics);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ final class ExtendedSdkTracer extends SdkTracer implements ExtendedTracer {
ExtendedSdkTracer(
TracerSharedState sharedState,
InstrumentationScopeInfo instrumentationScopeInfo,
TracerConfig tracerConfig) {
super(sharedState, instrumentationScopeInfo, tracerConfig);
TracerConfig tracerConfig,
SdkTracerMetrics tracerProviderMetrics) {
super(sharedState, instrumentationScopeInfo, tracerConfig, tracerProviderMetrics);
Comment thread
jack-berg marked this conversation as resolved.
Outdated
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,19 @@ private IncubatingUtil() {}
static SdkTracer createExtendedTracer(
TracerSharedState sharedState,
InstrumentationScopeInfo instrumentationScopeInfo,
TracerConfig tracerConfig) {
return new ExtendedSdkTracer(sharedState, instrumentationScopeInfo, tracerConfig);
TracerConfig tracerConfig,
SdkTracerMetrics tracerProviderMetrics) {
return new ExtendedSdkTracer(
sharedState, instrumentationScopeInfo, tracerConfig, tracerProviderMetrics);
}

static SdkSpanBuilder createExtendedSpanBuilder(
String spanName,
InstrumentationScopeInfo instrumentationScopeInfo,
TracerSharedState tracerSharedState,
SpanLimits spanLimits) {
SpanLimits spanLimits,
SdkTracerMetrics tracerProviderMetrics) {
return new ExtendedSdkSpanBuilder(
spanName, instrumentationScopeInfo, tracerSharedState, spanLimits);
spanName, instrumentationScopeInfo, tracerSharedState, spanLimits, tracerProviderMetrics);
}
}
15 changes: 12 additions & 3 deletions sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkSpan.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ final class SdkSpan implements ReadWriteSpan {
private final InstrumentationScopeInfo instrumentationScopeInfo;
// The start time of the span.
private final long startEpochNanos;
// Callback to run when span ends to record metrics.
private final Runnable recordEndMetrics;

// Lock used to internally guard the mutable state of this instance
private final Object lock = new Object();

Expand Down Expand Up @@ -132,7 +135,8 @@ private SdkSpan(
@Nullable AttributesMap attributes,
@Nullable List<LinkData> links,
int totalRecordedLinks,
long startEpochNanos) {
long startEpochNanos,
Runnable recordEndMetrics) {
this.context = context;
this.instrumentationScopeInfo = instrumentationScopeInfo;
this.parentSpanContext = parentSpanContext;
Expand All @@ -148,6 +152,7 @@ private SdkSpan(
this.startEpochNanos = startEpochNanos;
this.attributes = attributes;
this.spanLimits = spanLimits;
this.recordEndMetrics = recordEndMetrics;
}

/**
Expand All @@ -163,6 +168,7 @@ private SdkSpan(
* @param resource the resource associated with this span.
* @param attributes the attributes set during span creation.
* @param links the links set during span creation, may be truncated. The list MUST be immutable.
* @param recordEndMetrics a {@link Runnable} to run when the span is ended to record metrics.
* @return a new and started span.
*/
static SdkSpan startSpan(
Expand All @@ -180,7 +186,8 @@ static SdkSpan startSpan(
@Nullable AttributesMap attributes,
@Nullable List<LinkData> links,
int totalRecordedLinks,
long userStartEpochNanos) {
long userStartEpochNanos,
Runnable recordEndMetrics) {
boolean createdAnchoredClock;
AnchoredClock clock;
if (parentSpan instanceof SdkSpan) {
Expand Down Expand Up @@ -219,7 +226,8 @@ static SdkSpan startSpan(
attributes,
links,
totalRecordedLinks,
startEpochNanos);
startEpochNanos,
recordEndMetrics);
// Call onStart here instead of calling in the constructor to make sure the span is completely
// initialized.
if (spanProcessor.isStartRequired()) {
Expand Down Expand Up @@ -557,6 +565,7 @@ private void endInternal(long endEpochNanos) {
spanEndingThread = Thread.currentThread();
hasEnded = EndState.ENDING;
}
recordEndMetrics.run();
if (spanProcessor instanceof ExtendedSpanProcessor) {
ExtendedSpanProcessor extendedSpanProcessor = (ExtendedSpanProcessor) spanProcessor;
if (extendedSpanProcessor.isOnEndingRequired()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class SdkSpanBuilder implements SpanBuilder {
private final InstrumentationScopeInfo instrumentationScopeInfo;
private final TracerSharedState tracerSharedState;
private final SpanLimits spanLimits;
private final SdkTracerMetrics tracerProviderMetrics;

@Nullable private Context parent; // null means: Use current context.
private SpanKind spanKind = SpanKind.INTERNAL;
Expand All @@ -51,11 +52,13 @@ class SdkSpanBuilder implements SpanBuilder {
String spanName,
InstrumentationScopeInfo instrumentationScopeInfo,
TracerSharedState tracerSharedState,
SpanLimits spanLimits) {
SpanLimits spanLimits,
SdkTracerMetrics tracerProviderMetrics) {
this.spanName = spanName;
this.instrumentationScopeInfo = instrumentationScopeInfo;
this.tracerSharedState = tracerSharedState;
this.spanLimits = spanLimits;
this.tracerProviderMetrics = tracerProviderMetrics;
}

@Override
Expand Down Expand Up @@ -204,6 +207,9 @@ public Span startSpan() {
/* remote= */ false,
tracerSharedState.isIdGeneratorSafeToSkipIdValidation());

Runnable recordEndSpanMetrics =
tracerProviderMetrics.startSpan(parentSpanContext, samplingDecision);

if (!isRecording(samplingDecision)) {
return Span.wrap(spanContext);
}
Expand Down Expand Up @@ -232,7 +238,8 @@ public Span startSpan() {
recordedAttributes,
currentLinks,
totalNumberOfLinksAdded,
startEpochNanos);
startEpochNanos,
recordEndSpanMetrics);
}

private AttributesMap attributes() {
Expand Down
25 changes: 19 additions & 6 deletions sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracer.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,30 @@ class SdkTracer implements Tracer {

private final TracerSharedState sharedState;
private final InstrumentationScopeInfo instrumentationScopeInfo;
private final SdkTracerMetrics tracerProviderMetrics;

protected volatile boolean tracerEnabled;

SdkTracer(
TracerSharedState sharedState,
InstrumentationScopeInfo instrumentationScopeInfo,
TracerConfig tracerConfig) {
TracerConfig tracerConfig,
SdkTracerMetrics tracerProviderMetrics) {
this.sharedState = sharedState;
this.instrumentationScopeInfo = instrumentationScopeInfo;
this.tracerEnabled = tracerConfig.isEnabled();
this.tracerProviderMetrics = tracerProviderMetrics;
}

static SdkTracer create(
TracerSharedState sharedState,
InstrumentationScopeInfo instrumentationScopeInfo,
TracerConfig tracerConfig) {
TracerConfig tracerConfig,
SdkTracerMetrics tracerProviderMetrics) {
return INCUBATOR_AVAILABLE
? IncubatingUtil.createExtendedTracer(sharedState, instrumentationScopeInfo, tracerConfig)
: new SdkTracer(sharedState, instrumentationScopeInfo, tracerConfig);
? IncubatingUtil.createExtendedTracer(
sharedState, instrumentationScopeInfo, tracerConfig, tracerProviderMetrics)
: new SdkTracer(sharedState, instrumentationScopeInfo, tracerConfig, tracerProviderMetrics);
}

/**
Expand All @@ -68,9 +73,17 @@ public SpanBuilder spanBuilder(String spanName) {
}
return INCUBATOR_AVAILABLE
? IncubatingUtil.createExtendedSpanBuilder(
spanName, instrumentationScopeInfo, sharedState, sharedState.getSpanLimits())
spanName,
instrumentationScopeInfo,
sharedState,
sharedState.getSpanLimits(),
tracerProviderMetrics)
: new SdkSpanBuilder(
spanName, instrumentationScopeInfo, sharedState, sharedState.getSpanLimits());
spanName,
instrumentationScopeInfo,
sharedState,
sharedState.getSpanLimits(),
tracerProviderMetrics);
}

// Visible for testing
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.trace;

import static io.opentelemetry.api.common.AttributeKey.stringKey;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.metrics.LongUpDownCounter;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.sdk.trace.samplers.SamplingDecision;

/**
* SDK metrics exported for started and ended spans as defined in the <a
* href="https://opentelemetry.io/docs/specs/semconv/otel/sdk-metrics/#span-metrics">semantic
* conventions</a>.
*/
final class SdkTracerMetrics {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#nit For alignment with ExporterInstrumentation

Suggested change
final class SdkTracerMetrics {
final class SdkTracerInstrumentation {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's possible, I'd like to suggest the Metrics name, and maybe renaming that other one. I think instrumentation is something else, usually using interceptors or such to add telemetry in a somewhat black-box way. These are just shared state + helper methods and don't seem like instrumentation to me (admittedly a personal take).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine. Personally, I think any code that records spans, metrics, or logs is instrumentation. With that said, for the foreseeable future, these do only record metrics so *Metrics probably does more intuitively capture what's going on. I'm more interested in consistency than the name.


// Visible for testing
static final AttributeKey<String> OTEL_SPAN_PARENT_ORIGIN = stringKey("otel.span.parent.origin");
// Visible for testing
static final AttributeKey<String> OTEL_SPAN_SAMPLING_RESULT =
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should probably move those into SemConvAttributes with the corresponding tests for up-to-date-ness.

stringKey("otel.span.sampling_result");

private final LongCounter startedSpans;
private final LongUpDownCounter liveSpans;

SdkTracerMetrics(MeterProvider meterProvider) {
Meter meter = meterProvider.get("io.opentelemetry.sdk.trace");

startedSpans =
meter
.counterBuilder("otel.sdk.span.started")
.setUnit("{span}")
.setDescription("The number of created spans.")
.build();
liveSpans =
meter
.upDownCounterBuilder("otel.sdk.span.live")
.setUnit("{span}")
.setDescription(
"The number of created spans with recording=true for which the end operation has not been called yet.")
.build();
}

/**
* Records metrics for when a span starts and returns a {@link Runnable} to execute when ending
* the span.
*/
Runnable startSpan(SpanContext parentSpanContext, SamplingDecision samplingDecision) {
startedSpans.add(
1,
Attributes.of(
OTEL_SPAN_PARENT_ORIGIN,
parentOrigin(parentSpanContext),
OTEL_SPAN_SAMPLING_RESULT,
samplingDecision.name()));

if (samplingDecision == SamplingDecision.DROP) {
return () -> {};
}

Attributes liveSpansAttributes =
Attributes.of(OTEL_SPAN_SAMPLING_RESULT, samplingDecision.name());
liveSpans.add(1, liveSpansAttributes);
return () -> liveSpans.add(-1, liveSpansAttributes);
Comment thread
jack-berg marked this conversation as resolved.
Outdated
}

private static String parentOrigin(SpanContext parentSpanContext) {
if (!parentSpanContext.isValid()) {
return "none";
}
if (parentSpanContext.isRemote()) {
return "remote";
}
return "local";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

package io.opentelemetry.sdk.trace;

import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.TracerBuilder;
import io.opentelemetry.api.trace.TracerProvider;
Expand Down Expand Up @@ -54,7 +55,9 @@ public static SdkTracerProviderBuilder builder() {
Sampler sampler,
List<SpanProcessor> spanProcessors,
ScopeConfigurator<TracerConfig> tracerConfigurator,
ExceptionAttributeResolver exceptionAttributeResolver) {
ExceptionAttributeResolver exceptionAttributeResolver,
MeterProvider meterProvider) {
SdkTracerMetrics tracerProviderMetrics = new SdkTracerMetrics(meterProvider);
this.sharedState =
new TracerSharedState(
clock,
Expand All @@ -70,7 +73,8 @@ public static SdkTracerProviderBuilder builder() {
SdkTracer.create(
sharedState,
instrumentationScopeInfo,
getTracerConfig(instrumentationScopeInfo)));
getTracerConfig(instrumentationScopeInfo),
tracerProviderMetrics));
this.tracerConfigurator = tracerConfigurator;
}

Expand Down
Loading
Loading