Run context customizers before span start instead of after (#6634)

...so that they can have access to the parent span context, and so that
their additions to the context will be visible to span processors
This commit is contained in:
Trask Stalnaker 2022-10-06 12:11:17 -07:00 committed by GitHub
parent 1fcea2017b
commit 586261d25a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 13 additions and 10 deletions

View File

@ -18,5 +18,5 @@ import io.opentelemetry.context.Context;
public interface ContextCustomizer<REQUEST> { public interface ContextCustomizer<REQUEST> {
/** Allows to customize the operation {@link Context}. */ /** Allows to customize the operation {@link Context}. */
Context onStart(Context context, REQUEST request, Attributes startAttributes); Context onStart(Context parentContext, REQUEST request, Attributes startAttributes);
} }

View File

@ -160,10 +160,7 @@ public class Instrumenter<REQUEST, RESPONSE> {
private Context doStart(Context parentContext, REQUEST request, @Nullable Instant startTime) { private Context doStart(Context parentContext, REQUEST request, @Nullable Instant startTime) {
SpanKind spanKind = spanKindExtractor.extract(request); SpanKind spanKind = spanKindExtractor.extract(request);
SpanBuilder spanBuilder = SpanBuilder spanBuilder =
tracer tracer.spanBuilder(spanNameExtractor.extract(request)).setSpanKind(spanKind);
.spanBuilder(spanNameExtractor.extract(request))
.setSpanKind(spanKind)
.setParent(parentContext);
if (startTime != null) { if (startTime != null) {
spanBuilder.setStartTimestamp(startTime); spanBuilder.setStartTimestamp(startTime);
@ -181,22 +178,28 @@ public class Instrumenter<REQUEST, RESPONSE> {
Context context = parentContext; Context context = parentContext;
spanBuilder.setAllAttributes(attributes); // context customizers run before span start, so that they can have access to the parent span
Span span = spanBuilder.startSpan(); // context, and so that their additions to the context will be visible to span processors
context = context.with(span);
for (ContextCustomizer<? super REQUEST> contextCustomizer : contextCustomizers) { for (ContextCustomizer<? super REQUEST> contextCustomizer : contextCustomizers) {
context = contextCustomizer.onStart(context, request, attributes); context = contextCustomizer.onStart(context, request, attributes);
} }
boolean localRoot = LocalRootSpan.isLocalRoot(context);
spanBuilder.setAllAttributes(attributes);
Span span = spanBuilder.setParent(context).startSpan();
context = context.with(span);
if (!operationListeners.isEmpty()) { if (!operationListeners.isEmpty()) {
// operation listeners run after span start, so that they have access to the current span
// for capturing exemplars
long startNanos = getNanos(startTime); long startNanos = getNanos(startTime);
for (OperationListener operationListener : operationListeners) { for (OperationListener operationListener : operationListeners) {
context = operationListener.onStart(context, attributes, startNanos); context = operationListener.onStart(context, attributes, startNanos);
} }
} }
if (LocalRootSpan.isLocalRoot(parentContext)) { if (localRoot) {
context = LocalRootSpan.store(context, span); context = LocalRootSpan.store(context, span);
} }