Skip to content

Commit

Permalink
Fix JDK http client propagation of non-sampled traces (#3736)
Browse files Browse the repository at this point in the history
* Fix JDK http client propagation of non-sampled traces

* Lower wait time
  • Loading branch information
trask authored Aug 2, 2021
1 parent 40aad45 commit 03632d9
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import java.net.http.HttpHeaders;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
Expand All @@ -40,9 +39,7 @@ public static class HeadersAdvice {

@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void methodExit(@Advice.Return(readOnly = false) HttpHeaders headers) {
if (Java8BytecodeBridge.currentSpan().isRecording()) {
headers = tracer().inject(headers);
}
headers = tracer().inject(headers);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,11 @@ abstract class HttpClientTest<REQUEST> extends InstrumentationSpecification {
method << BODY_METHODS
}

def "basic GET request with not sampled parent"() {
expect:
junitTest.successfulRequestWithNotSampledParent()
}

def "should suppress nested CLIENT span if already under parent CLIENT span (#method)"() {
assumeTrue(testWithClientParent())
expect:
Expand All @@ -272,7 +277,6 @@ abstract class HttpClientTest<REQUEST> extends InstrumentationSpecification {
method << BODY_METHODS
}
//FIXME: add tests for POST with large/chunked data
def "trace request with callback and parent"() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,10 @@ public <T, E extends Throwable> T runWithServerSpan(
String spanName, ThrowingSupplier<T, E> callback) throws E {
return testInstrumenters.runWithServerSpan(spanName, callback);
}

@Override
public <T, E extends Throwable> T runWithNonRecordingSpan(ThrowingSupplier<T, E> callback)
throws E {
return testInstrumenters.runWithNonRecordingSpan(callback);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,7 @@ default <E extends Throwable> void runWithServerSpan(
*/
<T, E extends Throwable> T runWithServerSpan(String spanName, ThrowingSupplier<T, E> callback)
throws E;

/** Runs the provided {@code callback} inside the scope of a non-recording span. */
<T, E extends Throwable> T runWithNonRecordingSpan(ThrowingSupplier<T, E> callback) throws E;
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ public <T, E extends Throwable> T runWithServerSpan(
return testInstrumenters.runWithServerSpan(spanName, callback);
}

@Override
public <T, E extends Throwable> T runWithNonRecordingSpan(ThrowingSupplier<T, E> callback)
throws E {
return testInstrumenters.runWithNonRecordingSpan(callback);
}

private static class FlushTrackingSpanProcessor implements SpanProcessor {
@Override
public void onStart(Context parentContext, ReadWriteSpan span) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
package io.opentelemetry.instrumentation.testing;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.TraceFlags;
import io.opentelemetry.api.trace.TraceState;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
Expand Down Expand Up @@ -58,6 +62,19 @@ <T, E extends Throwable> T runWithServerSpan(String spanName, ThrowingSupplier<T
return runWithInstrumenter(spanName, testServerInstrumenter, callback);
}

/** Runs the provided {@code callback} inside the scope of a non-recording span. */
<T, E extends Throwable> T runWithNonRecordingSpan(ThrowingSupplier<T, E> callback) throws E {
SpanContext spanContext =
SpanContext.create(
"12345678123456781234567812345678",
"1234567812345678",
TraceFlags.getDefault(),
TraceState.getDefault());
try (Scope ignored = Span.wrap(spanContext).makeCurrent()) {
return callback.get();
}
}

private static <T, E extends Throwable> T runWithInstrumenter(
String spanName, Instrumenter<String, Void> instrumenter, ThrowingSupplier<T, E> callback)
throws E {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,20 @@ void successfulRequestWithParent(String method) {
});
}

@Test
void successfulRequestWithNotSampledParent() throws InterruptedException {
String method = "GET";
URI uri = resolveAddress("/success");
int responseCode = testing.runWithNonRecordingSpan(() -> doRequest(method, uri));

assertThat(responseCode).isEqualTo(200);

// sleep to ensure no spans are emitted
Thread.sleep(200);

assertThat(testing.traces()).isEmpty();
}

@ParameterizedTest
@ValueSource(strings = {"PUT", "POST"})
void shouldSuppressNestedClientSpanIfAlreadyUnderParentClientSpan(String method) {
Expand Down

0 comments on commit 03632d9

Please sign in to comment.