Skip to content

Commit 6420714

Browse files
committed
Replace span.ended with span.started, add parent.origin attrib
1 parent f42b0ad commit 6420714

File tree

8 files changed

+139
-290
lines changed

8 files changed

+139
-290
lines changed

sdk/common/src/main/java/io/opentelemetry/sdk/internal/SemConvAttributes.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ private SemConvAttributes() {}
2828
public static final AttributeKey<String> OTEL_SPAN_SAMPLING_RESULT =
2929
AttributeKey.stringKey("otel.span.sampling_result");
3030

31+
// TODO: Add tests verifying correctness when included in the semconv-incubating release
32+
public static final AttributeKey<String> OTEL_SPAN_PARENT_ORIGIN =
33+
AttributeKey.stringKey("otel.span.parent.origin");
34+
3135
public static final AttributeKey<String> SERVER_ADDRESS =
3236
AttributeKey.stringKey("server.address");
3337
public static final AttributeKey<Long> SERVER_PORT = AttributeKey.longKey("server.port");

sdk/trace/src/main/java/io/opentelemetry/sdk/trace/NonRecordingSpan.java

Lines changed: 0 additions & 133 deletions
This file was deleted.

sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkSpanBuilder.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,13 @@ public Span startSpan() {
206206
tracerSharedState.isIdGeneratorSafeToSkipIdValidation());
207207

208208
SpanInstrumentation.Recording metricsRecording =
209-
tracerSharedState.getSpanMetrics().recordSpanStart(samplingResult);
209+
tracerSharedState.getSpanMetrics().recordSpanStart(samplingResult, parentSpanContext);
210210
if (!isRecording(samplingDecision)) {
211-
return new NonRecordingSpan(spanContext, metricsRecording);
211+
if (!metricsRecording.isNoop()) {
212+
throw new IllegalStateException(
213+
"instrumentation ending is not supported for non-recording spans.");
214+
}
215+
return Span.wrap(spanContext);
212216
}
213217
Attributes samplingAttributes = samplingResult.getAttributes();
214218
if (!samplingAttributes.isEmpty()) {

sdk/trace/src/main/java/io/opentelemetry/sdk/trace/internal/NoopSpanInstrumentation.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,27 @@
55

66
package io.opentelemetry.sdk.trace.internal;
77

8+
import io.opentelemetry.api.trace.SpanContext;
89
import io.opentelemetry.sdk.trace.samplers.SamplingResult;
910

1011
class NoopSpanInstrumentation implements SpanInstrumentation {
1112

1213
static final NoopSpanInstrumentation INSTANCE = new NoopSpanInstrumentation();
1314

15+
static final SpanInstrumentation.Recording RECORDING_INSTANCE = new NoopRecording();
16+
1417
@Override
15-
public SpanInstrumentation.Recording recordSpanStart(SamplingResult samplingResult) {
16-
return NoopRecording.INSTANCE;
18+
public SpanInstrumentation.Recording recordSpanStart(
19+
SamplingResult samplingResult, SpanContext parentContext) {
20+
return RECORDING_INSTANCE;
1721
}
1822

1923
private static class NoopRecording implements SpanInstrumentation.Recording {
2024

21-
private static final NoopRecording INSTANCE = new NoopRecording();
25+
@Override
26+
public boolean isNoop() {
27+
return true;
28+
}
2229

2330
@Override
2431
public void recordSpanEnd() {}

sdk/trace/src/main/java/io/opentelemetry/sdk/trace/internal/SemConvSpanInstrumentation.java

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import io.opentelemetry.api.metrics.LongUpDownCounter;
1212
import io.opentelemetry.api.metrics.Meter;
1313
import io.opentelemetry.api.metrics.MeterProvider;
14+
import io.opentelemetry.api.trace.SpanContext;
1415
import io.opentelemetry.sdk.internal.SemConvAttributes;
1516
import io.opentelemetry.sdk.trace.samplers.SamplingDecision;
1617
import io.opentelemetry.sdk.trace.samplers.SamplingResult;
@@ -29,7 +30,7 @@ class SemConvSpanInstrumentation implements SpanInstrumentation {
2930
Attributes.of(SemConvAttributes.OTEL_SPAN_SAMPLING_RESULT, "RECORD_AND_SAMPLE");
3031

3132
@Nullable private volatile LongUpDownCounter live = null;
32-
@Nullable private volatile LongCounter ended = null;
33+
@Nullable private volatile LongCounter started = null;
3334

3435
SemConvSpanInstrumentation(Supplier<MeterProvider> meterProviderSupplier) {
3536
this.meterProviderSupplier = meterProviderSupplier;
@@ -58,18 +59,18 @@ private LongUpDownCounter live() {
5859
return live;
5960
}
6061

61-
private LongCounter ended() {
62-
LongCounter ended = this.ended;
63-
if (ended == null) {
64-
ended =
62+
private LongCounter started() {
63+
LongCounter started = this.started;
64+
if (started == null) {
65+
started =
6566
meter()
66-
.counterBuilder("otel.sdk.span.ended")
67+
.counterBuilder("otel.sdk.span.started")
6768
.setUnit("{span}")
68-
.setDescription("The number of created spans for which the end operation was called")
69+
.setDescription("The number of created spans")
6970
.build();
70-
this.ended = ended;
71+
this.started = started;
7172
}
72-
return ended;
73+
return started;
7374
}
7475

7576
static Attributes getAttributesForSamplingDecisions(SamplingDecision decision) {
@@ -84,11 +85,35 @@ static Attributes getAttributesForSamplingDecisions(SamplingDecision decision) {
8485
throw new IllegalStateException("Unhandled SamplingDecision case: " + decision);
8586
}
8687

88+
// TODO: Add test verifying attribute values when released in semantic conventions
89+
static String getParentOriginAttributeValue(SpanContext parentSpanContext) {
90+
if (!parentSpanContext.isValid()) {
91+
return "none";
92+
} else if (parentSpanContext.isRemote()) {
93+
return "remote";
94+
} else {
95+
return "local";
96+
}
97+
}
98+
8799
@Override
88-
public SpanInstrumentation.Recording recordSpanStart(SamplingResult samplingResult) {
89-
Attributes attribs = getAttributesForSamplingDecisions(samplingResult.getDecision());
90-
live().add(1, attribs);
91-
return new Recording(attribs);
100+
public SpanInstrumentation.Recording recordSpanStart(
101+
SamplingResult samplingResult, SpanContext parentSpanContext) {
102+
Attributes samplingResultAttribs =
103+
getAttributesForSamplingDecisions(samplingResult.getDecision());
104+
Attributes startAttributes =
105+
samplingResultAttribs.toBuilder()
106+
.put(
107+
SemConvAttributes.OTEL_SPAN_PARENT_ORIGIN,
108+
getParentOriginAttributeValue(parentSpanContext))
109+
.build();
110+
started().add(1L, startAttributes);
111+
if (samplingResult.getDecision() == SamplingDecision.DROP) {
112+
// Per semconv, otel.sdk.span.live is NOT collected for non-recording spans
113+
return NoopSpanInstrumentation.RECORDING_INSTANCE;
114+
}
115+
live().add(1, samplingResultAttribs);
116+
return new Recording(samplingResultAttribs);
92117
}
93118

94119
private class Recording implements SpanInstrumentation.Recording {
@@ -102,14 +127,18 @@ private Recording(Attributes attributes) {
102127
this.attributes = attributes;
103128
}
104129

130+
@Override
131+
public boolean isNoop() {
132+
return false;
133+
}
134+
105135
@Override
106136
public synchronized void recordSpanEnd() {
107137
if (endAlreadyReported) {
108138
return;
109139
}
110140
endAlreadyReported = true;
111141
live().add(-1, attributes);
112-
ended().add(1, attributes);
113142
}
114143
}
115144
}

sdk/trace/src/main/java/io/opentelemetry/sdk/trace/internal/SpanInstrumentation.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package io.opentelemetry.sdk.trace.internal;
77

88
import io.opentelemetry.api.metrics.MeterProvider;
9+
import io.opentelemetry.api.trace.SpanContext;
910
import io.opentelemetry.sdk.common.InternalTelemetryVersion;
1011
import io.opentelemetry.sdk.trace.samplers.SamplingResult;
1112
import java.util.function.Supplier;
@@ -29,14 +30,16 @@ static SpanInstrumentation create(
2930
"Unhandled telemetry schema version: " + internalTelemetryVersion);
3031
}
3132

32-
Recording recordSpanStart(SamplingResult samplingResult);
33+
Recording recordSpanStart(SamplingResult samplingResult, SpanContext parentSpanContext);
3334

3435
/**
3536
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
3637
* any time.
3738
*/
3839
interface Recording {
3940

41+
boolean isNoop();
42+
4043
void recordSpanEnd();
4144
}
4245
}

0 commit comments

Comments
 (0)