Remove HttpServerTestAdvice (#897)

* Remove HttpServerTestAdvice

* Trying to fix
This commit is contained in:
Nikita Salnikov-Tarnovski 2020-08-06 13:05:55 +03:00 committed by GitHub
parent 2ac65a67d5
commit 46dfa263af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 68 additions and 864 deletions

View File

@ -17,12 +17,14 @@
package io.opentelemetry.auto.bootstrap.instrumentation.decorator;
import static io.opentelemetry.OpenTelemetry.getPropagators;
import static io.opentelemetry.auto.bootstrap.instrumentation.java.concurrent.ExecutorInstrumentationUtils.THREAD_PROPAGATION_DEBUGGER;
import static io.opentelemetry.context.ContextUtils.withScopedContext;
import static io.opentelemetry.trace.Span.Kind.SERVER;
import static io.opentelemetry.trace.TracingContextUtils.getSpan;
import static io.opentelemetry.trace.TracingContextUtils.withSpan;
import io.grpc.Context;
import io.opentelemetry.auto.bootstrap.instrumentation.java.concurrent.ExecutorInstrumentationUtils;
import io.opentelemetry.auto.config.Config;
import io.opentelemetry.auto.instrumentation.api.MoreAttributes;
import io.opentelemetry.context.Scope;
@ -31,10 +33,13 @@ import io.opentelemetry.trace.EndSpanOptions;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.SpanContext;
import io.opentelemetry.trace.Tracer;
import io.opentelemetry.trace.TracingContextUtils;
import io.opentelemetry.trace.attributes.SemanticAttributes;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -47,6 +52,9 @@ public abstract class HttpServerTracer<REQUEST, RESPONSE, CONNECTION, STORAGE> e
protected static final String USER_AGENT = "User-Agent";
private static final boolean FAIL_ON_CONTEXT_LEAK =
Boolean.getBoolean("otel.internal.failOnContextLeak");
public HttpServerTracer() {
super();
}
@ -112,6 +120,7 @@ public abstract class HttpServerTracer<REQUEST, RESPONSE, CONNECTION, STORAGE> e
* Convenience method. Delegates to {@link #endExceptionally(Span, Throwable, RESPONSE)}, passing
* {@code response} value of {@code null}.
*/
@Override
public void endExceptionally(Span span, Throwable throwable) {
endExceptionally(span, throwable, null);
}
@ -269,6 +278,9 @@ public abstract class HttpServerTracer<REQUEST, RESPONSE, CONNECTION, STORAGE> e
}
private <C> SpanContext extract(final C carrier, final HttpTextFormat.Getter<C> getter) {
if (THREAD_PROPAGATION_DEBUGGER) {
debugContextLeak();
}
// Using Context.ROOT here may be quite unexpected, but the reason is simple.
// We want either span context extracted from the carrier or invalid one.
// We DO NOT want any span context potentially lingering in the current context.
@ -277,6 +289,37 @@ public abstract class HttpServerTracer<REQUEST, RESPONSE, CONNECTION, STORAGE> e
return span.getContext();
}
private void debugContextLeak() {
Context current = Context.current();
if (current != Context.ROOT) {
log.error("Unexpected non-root current context found when extracting remote context!");
Span currentSpan = TracingContextUtils.getSpanWithoutDefault(current);
if (currentSpan != null) {
log.error("It contains this span: {}", currentSpan);
}
List<StackTraceElement[]> location =
ExecutorInstrumentationUtils.THREAD_PROPAGATION_LOCATIONS.get(current);
if (location != null) {
StringBuilder sb = new StringBuilder();
Iterator<StackTraceElement[]> i = location.iterator();
while (i.hasNext()) {
for (StackTraceElement ste : i.next()) {
sb.append("\n");
sb.append(ste);
}
if (i.hasNext()) {
sb.append("\nwhich was propagated from:");
}
}
log.error("a context leak was detected. it was propagated from:{}", sb);
}
if (FAIL_ON_CONTEXT_LEAK) {
throw new IllegalStateException("Context leak detected");
}
}
}
private static void setStatus(Span span, int status) {
SemanticAttributes.HTTP_STATUS_CODE.set(span, status);
// TODO status_message

View File

@ -35,7 +35,7 @@ public class ExecutorInstrumentationUtils {
// helpful in akka where there is so much recursive async spawning of new work)
public static final Context.Key<List<StackTraceElement[]>> THREAD_PROPAGATION_LOCATIONS =
Context.key("thread-propagation-locations");
private static final boolean THREAD_PROPAGATION_DEBUGGER =
public static final boolean THREAD_PROPAGATION_DEBUGGER =
Boolean.getBoolean("otel.threadPropagationDebugger");
private static final Logger log = LoggerFactory.getLogger(ExecutorInstrumentationUtils.class);

View File

@ -1,35 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class AkkaHttpTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("akka.http.impl.engine.server.HttpServerBluePrint$PrepareRequests$$anon$1"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(named("onPush"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,35 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class JettyTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("org.eclipse.jetty.server.Server"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(named("handle"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,36 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class NettyServerTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("io.netty.handler.codec.ByteToMessageDecoder"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
named("channelRead"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -43,6 +43,8 @@ public class HttpCodecFilterAdvice {
HttpRequestPacket httpRequest = (HttpRequestPacket) httpHeader;
Span span = TRACER.startSpan(httpRequest, httpRequest, method);
TRACER.startScope(span, ctx);
// We don't actually want to attach new context to this thread, as actual request will continue
// on some other thread. But we do want to attach that new context to FilterChainContext
TRACER.startScope(span, ctx).close();
}
}

View File

@ -43,6 +43,8 @@ public class HttpCodecFilterOldAdvice {
HttpRequestPacket httpRequest = (HttpRequestPacket) httpHeader;
Span span = TRACER.startSpan(httpRequest, httpRequest, method);
TRACER.startScope(span, ctx);
// We don't actually want to attach new context to this thread, as actual request will continue
// on some other thread. But we do want to attach that new context to FilterChainContext
TRACER.startScope(span, ctx).close();
}
}

View File

@ -1,41 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class GrizzlyFilterchainServerTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("org.glassfish.grizzly.http.HttpCodecFilter"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
named("handleRead")
.and(
takesArgument(
0, named("org.glassfish.grizzly.filterchain.FilterChainContext"))),
HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,35 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class JettyTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("org.eclipse.jetty.server.Server"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(named("handle"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,35 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class JettyTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("org.eclipse.jetty.server.Server"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(named("handle"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,37 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class NettyServerTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("org.jboss.netty.handler.codec.http.HttpRequestDecoder"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
named("createMessage"),
HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,37 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class NettyServerTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("org.jboss.netty.handler.codec.http.HttpRequestDecoder"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
named("createMessage"),
HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,36 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class NettyServerTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("io.netty.handler.codec.ByteToMessageDecoder"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
named("channelRead"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,36 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class NettyServerTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("io.netty.handler.codec.ByteToMessageDecoder"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
named("channelRead"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,39 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package server;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class NettyServerTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("org.jboss.netty.handler.codec.http.HttpRequestDecoder"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
named("createMessage"),
HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,38 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package server;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class NettyServerTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("io.netty.handler.codec.ByteToMessageDecoder"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
named("channelRead"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,37 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package server;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class AkkaHttpTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("akka.http.impl.engine.server.HttpServerBluePrint$PrepareRequests$$anon$1"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(named("onPush"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,38 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package server;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class NettyServerTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("io.netty.handler.codec.ByteToMessageDecoder"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
named("channelRead"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -19,6 +19,7 @@ package server
import ratpack.exec.Promise
import ratpack.groovy.test.embed.GroovyEmbeddedApp
import ratpack.test.embed.EmbeddedApp
import io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.ERROR
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.EXCEPTION

View File

@ -19,6 +19,7 @@ package server
import ratpack.exec.Promise
import ratpack.groovy.test.embed.GroovyEmbeddedApp
import ratpack.test.embed.EmbeddedApp
import io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.ERROR
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.EXCEPTION

View File

@ -1,36 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class GrizzlyTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("org.glassfish.grizzly.http.server.HttpServerFilter"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
named("handleRead"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,35 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class ServletTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("org.eclipse.jetty.server.Server"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(named("handle"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,40 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class ServletTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("org.eclipse.jetty.server.Server"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(named("handle"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()))
// Tomcat
.type(named("org.apache.catalina.connector.CoyoteAdapter"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(named("service"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -15,6 +15,8 @@
*/
import com.google.common.io.Files
import javax.servlet.Servlet
import javax.servlet.ServletException
import org.apache.catalina.AccessLog
import org.apache.catalina.Context
import org.apache.catalina.connector.Request
@ -28,16 +30,12 @@ import org.apache.tomcat.JarScanType
import spock.lang.Shared
import spock.lang.Unroll
import javax.servlet.Servlet
import javax.servlet.ServletException
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.AUTH_REQUIRED
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.ERROR
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.EXCEPTION
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.REDIRECT
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.SUCCESS
import static io.opentelemetry.auto.test.utils.TraceUtils.basicSpan
@Unroll
abstract class TomcatServlet3Test extends AbstractServlet3Test<Tomcat, Context> {
@ -125,22 +123,19 @@ abstract class TomcatServlet3Test extends AbstractServlet3Test<Tomcat, Context>
}
and:
assertTraces(count * 2) {
assertTraces(count) {
assert accessLogValue.loggedIds.size() == count
def loggedTraces = accessLogValue.loggedIds*.first
def loggedSpans = accessLogValue.loggedIds*.second
(0..count - 1).each {
trace(it * 2, 1) {
basicSpan(it, 0, "TEST_SPAN")
}
trace(it * 2 + 1, 2) {
trace(it, 2) {
serverSpan(it, 0, null, null, "GET", SUCCESS.body.length())
controllerSpan(it, 1, span(0))
}
assert loggedTraces.contains(traces[it * 2 + 1][0].traceId.toLowerBase16())
assert loggedSpans.contains(traces[it * 2 + 1][0].spanId.toLowerBase16())
assert loggedTraces.contains(traces[it][0].traceId.toLowerBase16())
assert loggedSpans.contains(traces[it][0].spanId.toLowerBase16())
}
}
@ -160,18 +155,15 @@ abstract class TomcatServlet3Test extends AbstractServlet3Test<Tomcat, Context>
response.body().string() == ERROR.body
and:
assertTraces(2) {
trace(0, 1) {
basicSpan(it, 0, "TEST_SPAN")
}
trace(1, 2) {
assertTraces(1) {
trace(0, 2) {
serverSpan(it, 0, null, null, method, response.body().contentLength(), ERROR)
controllerSpan(it, 1, span(0))
}
def (String traceId, String spanId) = accessLogValue.loggedIds[0]
assert traces[1][0].traceId.toLowerBase16() == traceId
assert traces[1][0].spanId.toLowerBase16() == spanId
assert traces[0][0].traceId.toLowerBase16() == traceId
assert traces[0][0].spanId.toLowerBase16() == spanId
}
where:

View File

@ -1,38 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package test;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class ServletTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
// Tomcat
.type(named("org.apache.catalina.connector.CoyoteAdapter"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(named("service"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -32,7 +32,6 @@ import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.LOGI
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.PATH_PARAM
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.REDIRECT
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.SUCCESS
import static io.opentelemetry.auto.test.utils.TraceUtils.basicSpan
import static io.opentelemetry.trace.Span.Kind.INTERNAL
import static io.opentelemetry.trace.Span.Kind.SERVER
import static java.util.Collections.singletonMap
@ -93,11 +92,8 @@ class SpringBootBasedTest extends HttpServerTest<ConfigurableApplicationContext>
authProvider.latestAuthentications.get(0).password == testPassword
and:
assertTraces(2) {
assertTraces(1) {
trace(0, 1) {
basicSpan(it, 0, "TEST_SPAN")
}
trace(1, 1) {
serverSpan(it, 0, null, null, "POST", response.body()?.contentLength(), LOGIN)
}
}

View File

@ -1,38 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package server;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class NettyServerTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("io.netty.handler.codec.ByteToMessageDecoder"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
named("channelRead"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -1,36 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.auto.test.base.HttpServerTestAdvice;
import io.opentelemetry.auto.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class NettyServerTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("io.netty.handler.codec.ByteToMessageDecoder"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
named("channelRead"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -80,6 +80,7 @@ public abstract class AgentTestRunner extends AgentSpecification {
static {
// always run with the thread propagation debugger to help track down sporadic test failures
System.setProperty("otel.threadPropagationDebugger", "true");
System.setProperty("otel.internal.failOnContextLeak", "true");
}
/**

View File

@ -26,7 +26,6 @@ import io.opentelemetry.sdk.trace.data.SpanData
import io.opentelemetry.trace.Span
import io.opentelemetry.trace.attributes.SemanticAttributes
import java.util.concurrent.Callable
import java.util.concurrent.atomic.AtomicBoolean
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
@ -45,7 +44,6 @@ import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.QUER
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.REDIRECT
import static io.opentelemetry.auto.test.base.HttpServerTest.ServerEndpoint.SUCCESS
import static io.opentelemetry.auto.test.utils.ConfigUtils.withConfigOverride
import static io.opentelemetry.auto.test.utils.TraceUtils.basicSpan
import static io.opentelemetry.auto.test.utils.TraceUtils.runUnderTrace
import static org.junit.Assume.assumeTrue
@ -394,12 +392,9 @@ abstract class HttpServerTest<SERVER> extends AgentTestRunner {
spanCount++
}
}
assertTraces(size * 2) {
assertTraces(size) {
(0..size - 1).each {
trace(it * 2, 1) {
basicSpan(it, 0, "TEST_SPAN")
}
trace(it * 2 + 1, spanCount) {
trace(it, spanCount) {
def spanIndex = 0
serverSpan(it, spanIndex++, traceID, parentID, method, response?.body()?.contentLength(), endpoint)
if (hasHandlerSpan()) {
@ -479,7 +474,8 @@ abstract class HttpServerTest<SERVER> extends AgentTestRunner {
attributes {
"${SemanticAttributes.NET_PEER_PORT.key()}" { it == null || it instanceof Long }
"${SemanticAttributes.NET_PEER_IP.key()}" { it == null || it == "127.0.0.1" } // Optional
"${SemanticAttributes.HTTP_CLIENT_IP.key()}" { it == null || it == TEST_CLIENT_IP } // Optional
"${SemanticAttributes.HTTP_CLIENT_IP.key()}" { it == null || it == TEST_CLIENT_IP }
// Optional
"${SemanticAttributes.HTTP_URL.key()}" { it == "${endpoint.resolve(address)}" || it == "${endpoint.resolveWithoutFragment(address)}" }
"${SemanticAttributes.HTTP_METHOD.key()}" method
"${SemanticAttributes.HTTP_STATUS_CODE.key()}" endpoint.status
@ -496,13 +492,4 @@ abstract class HttpServerTest<SERVER> extends AgentTestRunner {
}
}
public static final AtomicBoolean ENABLE_TEST_ADVICE = new AtomicBoolean(false)
def setup() {
ENABLE_TEST_ADVICE.set(true)
}
def cleanup() {
ENABLE_TEST_ADVICE.set(false)
}
}

View File

@ -1,83 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.opentelemetry.auto.test.base;
import static io.opentelemetry.trace.TracingContextUtils.currentContextWith;
import io.grpc.Context;
import io.opentelemetry.OpenTelemetry;
import io.opentelemetry.auto.bootstrap.instrumentation.java.concurrent.ExecutorInstrumentationUtils;
import io.opentelemetry.auto.instrumentation.api.SpanWithScope;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.Tracer;
import java.util.Iterator;
import java.util.List;
import net.bytebuddy.asm.Advice;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class HttpServerTestAdvice {
// needs to be public otherwise IllegalAccessError from inlined advice below
public static final Tracer TRACER =
OpenTelemetry.getTracerProvider().get("io.opentelemetry.auto");
// needs to be public otherwise IllegalAccessError from inlined advice below
public static final Logger log = LoggerFactory.getLogger(HttpServerTestAdvice.class);
/**
* This advice should be applied at the root of a http server request to validate the
* instrumentation correctly ignores other traces.
*/
public static class ServerEntryAdvice {
@Advice.OnMethodEnter
public static SpanWithScope methodEnter() {
if (!HttpServerTest.ENABLE_TEST_ADVICE.get()) {
// Skip if not running the HttpServerTest.
return null;
}
List<StackTraceElement[]> location =
ExecutorInstrumentationUtils.THREAD_PROPAGATION_LOCATIONS.get(Context.current());
if (location != null) {
StringBuilder sb = new StringBuilder();
Iterator<StackTraceElement[]> i = location.iterator();
while (i.hasNext()) {
for (StackTraceElement ste : i.next()) {
sb.append("\n");
sb.append(ste);
}
if (i.hasNext()) {
sb.append("\nwhich was propagated from:");
}
}
log.error("a context leak was detected. it was propagated from:{}", sb);
}
Span span = TRACER.spanBuilder("TEST_SPAN").startSpan();
return new SpanWithScope(span, currentContextWith(span));
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void methodExit(@Advice.Enter final SpanWithScope spanWithScope) {
if (spanWithScope != null) {
spanWithScope.getSpan().end();
spanWithScope.closeScope();
}
}
}
}