Migrate Ratpack javaagent instrumentation to Instrumenter API (#4399)

This commit is contained in:
Mateusz Rzeszutek 2021-10-18 19:00:40 +02:00 committed by GitHub
parent 888496413d
commit 22ea557c41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 62 deletions

View File

@ -11,6 +11,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerMetrics;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanNameExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanStatusExtractor;
import io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming;
import io.opentelemetry.javaagent.instrumentation.netty.common.HttpRequestAndChannel;
import io.opentelemetry.javaagent.instrumentation.netty.common.NettyCommonNetAttributesExtractor;
@ -30,6 +31,11 @@ public final class NettyServerInstrumenterFactory {
.addAttributesExtractor(httpAttributesExtractor)
.addAttributesExtractor(new NettyCommonNetAttributesExtractor())
.addRequestMetrics(HttpServerMetrics.get())
.addContextCustomizer(
(context, request, attributes) -> {
// netty is not exactly a "container", but it's the best match out of these
return ServerSpanNaming.init(context, ServerSpanNaming.Source.CONTAINER);
})
.newServerInstrumenter(new HttpRequestHeadersGetter());
}

View File

@ -0,0 +1,56 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.ratpack;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.instrumentation.api.instrumenter.ErrorCauseExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming;
import ratpack.handling.Context;
public final class RatpackSingletons {
private static final Instrumenter<String, Void> INSTRUMENTER =
Instrumenter.<String, Void>newBuilder(
GlobalOpenTelemetry.get(), "io.opentelemetry.ratpack-1.4", s -> s)
.newInstrumenter();
public static Instrumenter<String, Void> instrumenter() {
return INSTRUMENTER;
}
public static void updateSpanNames(io.opentelemetry.context.Context otelContext, Context ctx) {
String matchedRoute = updateServerSpanName(otelContext, ctx);
// update ratpack span name
Span.fromContext(otelContext).updateName(matchedRoute);
}
public static String updateServerSpanName(
io.opentelemetry.context.Context otelContext, Context ctx) {
String matchedRoute = ctx.getPathBinding().getDescription();
if (matchedRoute == null || matchedRoute.isEmpty()) {
matchedRoute = "/";
} else if (!matchedRoute.startsWith("/")) {
matchedRoute = "/" + matchedRoute;
}
// update the netty server span name; FILTER is probably the best match for ratpack Handlers
ServerSpanNaming.updateServerSpanName(
otelContext, ServerSpanNaming.Source.FILTER, (context, name) -> name, matchedRoute);
return matchedRoute;
}
// copied from BaseTracer#onException()
public static void onError(io.opentelemetry.context.Context context, Throwable error) {
Span span = Span.fromContext(context);
span.setStatus(StatusCode.ERROR);
span.recordException(ErrorCauseExtractor.jdk().extractCause(error));
}
private RatpackSingletons() {}
}

View File

@ -1,42 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.ratpack;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
import ratpack.handling.Context;
public class RatpackTracer extends BaseTracer {
private static final RatpackTracer TRACER = new RatpackTracer();
public static RatpackTracer tracer() {
return TRACER;
}
public void onContext(io.opentelemetry.context.Context otelContext, Context ctx) {
String description = ctx.getPathBinding().getDescription();
if (description == null || description.isEmpty()) {
description = "/";
} else if (!description.startsWith("/")) {
description = "/" + description;
}
Span.fromContext(otelContext).updateName(description);
}
@Override
protected String getInstrumentationName() {
return "io.opentelemetry.ratpack-1.4";
}
@Override
protected Throwable unwrapThrowable(Throwable throwable) {
if (throwable.getCause() != null && throwable instanceof Error) {
throwable = throwable.getCause();
}
return super.unwrapThrowable(throwable);
}
}

View File

@ -7,7 +7,6 @@ package io.opentelemetry.javaagent.instrumentation.ratpack;
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.instrumentation.ratpack.RatpackTracer.tracer;
import static net.bytebuddy.matcher.ElementMatchers.isAbstract;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
@ -51,7 +50,7 @@ public class ServerErrorHandlerInstrumentation implements TypeInstrumentation {
Optional<io.opentelemetry.context.Context> otelContext =
ctx.maybeGet(io.opentelemetry.context.Context.class);
if (otelContext.isPresent()) {
tracer().onException(otelContext.get(), throwable);
RatpackSingletons.onError(otelContext.get(), throwable);
}
}
}

View File

@ -5,10 +5,11 @@
package io.opentelemetry.javaagent.instrumentation.ratpack;
import static io.opentelemetry.javaagent.instrumentation.ratpack.RatpackTracer.tracer;
import static io.opentelemetry.javaagent.instrumentation.ratpack.RatpackSingletons.instrumenter;
import static io.opentelemetry.javaagent.instrumentation.ratpack.RatpackSingletons.updateServerSpanName;
import static io.opentelemetry.javaagent.instrumentation.ratpack.RatpackSingletons.updateSpanNames;
import io.netty.util.Attribute;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.netty.v4_1.AttributeKeys;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
@ -16,6 +17,9 @@ import ratpack.handling.Context;
import ratpack.handling.Handler;
public final class TracingHandler implements Handler {
private static final String INITIAL_SPAN_NAME = "ratpack.handler";
public static final Handler INSTANCE = new TracingHandler();
@Override
@ -27,25 +31,28 @@ public final class TracingHandler implements Handler {
// Must use context from channel, as executor instrumentation is not accurate - Ratpack
// internally queues events and then drains them in batches, causing executor instrumentation to
// attach the same context to a batch of events from different requests.
io.opentelemetry.context.Context parentContext =
io.opentelemetry.context.Context parentOtelContext =
serverSpanContext != null ? serverSpanContext : Java8BytecodeBridge.currentContext();
io.opentelemetry.context.Context callbackContext;
io.opentelemetry.context.Context ratpackContext =
tracer().startSpan(parentContext, "ratpack.handler", SpanKind.INTERNAL);
ctx.getExecution().add(ratpackContext);
if (instrumenter().shouldStart(parentOtelContext, INITIAL_SPAN_NAME)) {
io.opentelemetry.context.Context otelContext =
instrumenter().start(parentOtelContext, INITIAL_SPAN_NAME);
ctx.getExecution().add(otelContext);
ctx.getResponse()
.beforeSend(
response -> {
updateSpanNames(otelContext, ctx);
instrumenter().end(otelContext, INITIAL_SPAN_NAME, null, null);
});
callbackContext = otelContext;
} else {
// just update the server span name
ctx.getResponse().beforeSend(response -> updateServerSpanName(parentOtelContext, ctx));
callbackContext = parentOtelContext;
}
ctx.getResponse()
.beforeSend(
response -> {
if (serverSpanContext != null) {
// Rename the netty span name with the ratpack route.
tracer().onContext(serverSpanContext, ctx);
}
tracer().onContext(ratpackContext, ctx);
tracer().end(ratpackContext);
});
try (Scope ignored = ratpackContext.makeCurrent()) {
try (Scope ignored = callbackContext.makeCurrent()) {
ctx.next();
// exceptions are captured by ServerErrorHandlerInstrumentation
}