Skip to content

Commit

Permalink
Convert liberty dispatcher instrumentation to instrumenter api (#4256)
Browse files Browse the repository at this point in the history
* Convert liberty dispatcher instrumentation to instrumenter api

* nullable

* Add comment

Co-authored-by: Trask Stalnaker <[email protected]>
  • Loading branch information
laurit and trask authored Oct 3, 2021
1 parent ce241d2 commit 39a1604
Show file tree
Hide file tree
Showing 10 changed files with 274 additions and 167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ public String getRemoteHostAddress() {
throw new UnsupportedOperationException();
}

public String getRemoteHostName(boolean canonical) {
throw new UnsupportedOperationException();
}

public String getRequestedHost() {
throw new UnsupportedOperationException();
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.liberty.dispatcher;

import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerAttributesExtractor;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LibertyDispatcherHttpAttributesExtractor
extends HttpServerAttributesExtractor<LibertyRequest, LibertyResponse> {
private static final Logger logger =
LoggerFactory.getLogger(LibertyDispatcherHttpAttributesExtractor.class);

@Override
protected @Nullable String method(LibertyRequest libertyRequest) {
return libertyRequest.getMethod();
}

@Override
protected @Nullable String userAgent(LibertyRequest libertyRequest) {
return libertyRequest.getHeaderValue("User-Agent");
}

@Override
protected @Nullable Long requestContentLength(
LibertyRequest libertyRequest, @Nullable LibertyResponse libertyResponse) {
return null;
}

@Override
protected @Nullable Long requestContentLengthUncompressed(
LibertyRequest libertyRequest, @Nullable LibertyResponse libertyResponse) {
return null;
}

@Override
protected @Nullable String flavor(
LibertyRequest libertyRequest, @Nullable LibertyResponse libertyResponse) {
String flavor = libertyRequest.getProtocol();
if (flavor != null) {
// remove HTTP/ prefix to comply with semantic conventions
if (flavor.startsWith("HTTP/")) {
flavor = flavor.substring("HTTP/".length());
}
}
return flavor;
}

@Override
protected @Nullable Integer statusCode(
LibertyRequest libertyRequest, LibertyResponse libertyResponse) {
return libertyResponse.getStatus();
}

@Override
protected @Nullable Long responseContentLength(
LibertyRequest libertyRequest, LibertyResponse libertyResponse) {
return null;
}

@Override
protected @Nullable Long responseContentLengthUncompressed(
LibertyRequest libertyRequest, LibertyResponse libertyResponse) {
return null;
}

@Override
protected @Nullable String target(LibertyRequest libertyRequest) {
String requestUri = libertyRequest.getRequestUri();
String queryString = libertyRequest.getQueryString();
if (queryString != null && !queryString.isEmpty()) {
return requestUri + "?" + queryString;
}
return requestUri;
}

@Override
protected String host(LibertyRequest libertyRequest) {
return libertyRequest.getServerName() + ":" + libertyRequest.getServerPort();
}

@Override
protected @Nullable String scheme(LibertyRequest libertyRequest) {
return libertyRequest.getScheme();
}

@Override
protected @Nullable String route(LibertyRequest libertyRequest) {
return null;
}

@Override
protected @Nullable String serverName(
LibertyRequest libertyRequest, @Nullable LibertyResponse libertyResponse) {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

package io.opentelemetry.javaagent.instrumentation.liberty.dispatcher;

import static io.opentelemetry.javaagent.instrumentation.liberty.dispatcher.LibertyDispatcherTracer.tracer;
import static io.opentelemetry.javaagent.instrumentation.liberty.dispatcher.LibertyDispatcherSingletons.instrumenter;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;

Expand All @@ -16,6 +16,7 @@
import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
Expand Down Expand Up @@ -53,16 +54,15 @@ public static class SendResponseAdvice {
public static void onEnter(
@Advice.This HttpDispatcherLink httpDispatcherLink,
@Advice.FieldValue("isc") HttpInboundServiceContextImpl isc,
@Advice.Local("otelRequest") LibertyRequest request,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
LibertyRequestWrapper requestWrapper =
new LibertyRequestWrapper(httpDispatcherLink, isc.getRequest());
LibertyConnectionWrapper connectionWrapper =
new LibertyConnectionWrapper(httpDispatcherLink, isc.getRequest());
context =
tracer()
.startSpan(
requestWrapper, connectionWrapper, null, "HTTP " + requestWrapper.getMethod());
Context parentContext = Java8BytecodeBridge.currentContext();
request = new LibertyRequest(httpDispatcherLink, isc.getRequest());
if (!instrumenter().shouldStart(parentContext, request)) {
return;
}
context = instrumenter().start(parentContext, request);
scope = context.makeCurrent();
}

Expand All @@ -71,22 +71,19 @@ public static void stopSpan(
@Advice.Thrown Throwable throwable,
@Advice.Argument(value = 0) StatusCodes statusCode,
@Advice.Argument(value = 2) Exception failure,
@Advice.Local("otelRequest") LibertyRequest request,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
if (scope == null) {
return;
}
scope.close();

LibertyResponseWrapper responseWrapper = new LibertyResponseWrapper(statusCode);
LibertyResponse response = new LibertyResponse(statusCode);
request.setCompleted();

Throwable t = failure != null ? failure : throwable;
if (t != null) {
tracer().endExceptionally(context, t, responseWrapper);
return;
}

tracer().end(context, responseWrapper);
instrumenter().end(context, request, response, t);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.liberty.dispatcher;

import io.opentelemetry.instrumentation.api.instrumenter.net.NetAttributesExtractor;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import org.checkerframework.checker.nullness.qual.Nullable;

public class LibertyDispatcherNetAttributesExtractor
extends NetAttributesExtractor<LibertyRequest, LibertyResponse> {

@Override
public String transport(LibertyRequest libertyRequest) {
return SemanticAttributes.NetTransportValues.IP_TCP;
}

@Override
public @Nullable String peerName(
LibertyRequest libertyRequest, @Nullable LibertyResponse libertyResponse) {
// condition limits calling peerName to onStart because in onEnd it may throw a NPE
if (!libertyRequest.isCompleted()) {
return libertyRequest.peerName();
}
return null;
}

@Override
public @Nullable Integer peerPort(
LibertyRequest libertyRequest, @Nullable LibertyResponse libertyResponse) {
// condition limits calling getServerPort to onStart because in onEnd it may throw a NPE
if (!libertyRequest.isCompleted()) {
return libertyRequest.getServerPort();
}
return null;
}

@Override
public @Nullable String peerIp(
LibertyRequest libertyRequest, @Nullable LibertyResponse libertyResponse) {
// condition limits calling peerIp to onStart because in onEnd it may throw a NPE
if (!libertyRequest.isCompleted()) {
return libertyRequest.peerIp();
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.liberty.dispatcher;

import io.opentelemetry.context.propagation.TextMapGetter;

public class LibertyDispatcherRequestGetter implements TextMapGetter<LibertyRequest> {

public static final LibertyDispatcherRequestGetter GETTER = new LibertyDispatcherRequestGetter();

@Override
public Iterable<String> keys(LibertyRequest carrier) {
return carrier.getAllHeaderNames();
}

@Override
public String get(LibertyRequest carrier, String key) {
return carrier.getHeaderValue(key);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.liberty.dispatcher;

import static io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming.Source.CONTAINER;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerAttributesExtractor;
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.instrumenter.net.NetAttributesExtractor;
import io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming;
import io.opentelemetry.javaagent.instrumentation.api.instrumenter.PeerServiceAttributesExtractor;

public final class LibertyDispatcherSingletons {
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.liberty-dispatcher";

private static final Instrumenter<LibertyRequest, LibertyResponse> INSTRUMENTER;

static {
HttpServerAttributesExtractor<LibertyRequest, LibertyResponse> httpAttributesExtractor =
new LibertyDispatcherHttpAttributesExtractor();
SpanNameExtractor<LibertyRequest> spanNameExtractor =
HttpSpanNameExtractor.create(httpAttributesExtractor);
SpanStatusExtractor<LibertyRequest, LibertyResponse> spanStatusExtractor =
HttpSpanStatusExtractor.create(httpAttributesExtractor);
NetAttributesExtractor<LibertyRequest, LibertyResponse> netAttributesExtractor =
new LibertyDispatcherNetAttributesExtractor();

INSTRUMENTER =
Instrumenter.<LibertyRequest, LibertyResponse>newBuilder(
GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, spanNameExtractor)
.setSpanStatusExtractor(spanStatusExtractor)
.addAttributesExtractor(httpAttributesExtractor)
.addAttributesExtractor(netAttributesExtractor)
.addAttributesExtractor(PeerServiceAttributesExtractor.create(netAttributesExtractor))
.addContextCustomizer(
(context, request, attributes) -> ServerSpanNaming.init(context, CONTAINER))
.addRequestMetrics(HttpServerMetrics.get())
.newServerInstrumenter(LibertyDispatcherRequestGetter.GETTER);
}

public static Instrumenter<LibertyRequest, LibertyResponse> instrumenter() {
return INSTRUMENTER;
}

private LibertyDispatcherSingletons() {}
}
Loading

0 comments on commit 39a1604

Please sign in to comment.