Skip to content

Commit

Permalink
Capture net.host.name for netty (open-telemetry#6892)
Browse files Browse the repository at this point in the history
This may be a regression in 1.19.0 because you can no longer reconstruct
the original url for netty server spans (previously `http.host` was
captured which could be used).
  • Loading branch information
trask authored and dmarkwat committed Oct 22, 2022
1 parent d8f02f3 commit 53c4149
Show file tree
Hide file tree
Showing 31 changed files with 357 additions and 158 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.net.NetServerAttributesGetter;
import io.opentelemetry.instrumentation.api.instrumenter.net.internal.InternalNetServerAttributesExtractor;
import io.opentelemetry.instrumentation.api.internal.SpanKey;
import io.opentelemetry.instrumentation.api.internal.SpanKeyProvider;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
Expand All @@ -36,35 +38,46 @@ public final class HttpServerAttributesExtractor<REQUEST, RESPONSE>

/** Creates the HTTP server attributes extractor with default configuration. */
public static <REQUEST, RESPONSE> HttpServerAttributesExtractor<REQUEST, RESPONSE> create(
HttpServerAttributesGetter<REQUEST, RESPONSE> getter) {
return builder(getter).build();
HttpServerAttributesGetter<REQUEST, RESPONSE> httpAttributesGetter,
NetServerAttributesGetter<REQUEST> netAttributesGetter) {
return builder(httpAttributesGetter, netAttributesGetter).build();
}

/**
* Returns a new {@link HttpServerAttributesExtractorBuilder} that can be used to configure the
* HTTP client attributes extractor.
*/
public static <REQUEST, RESPONSE> HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE> builder(
HttpServerAttributesGetter<REQUEST, RESPONSE> getter) {
return new HttpServerAttributesExtractorBuilder<>(getter);
HttpServerAttributesGetter<REQUEST, RESPONSE> httpAttributesGetter,
NetServerAttributesGetter<REQUEST> netAttributesGetter) {
return new HttpServerAttributesExtractorBuilder<>(httpAttributesGetter, netAttributesGetter);
}

private final NetServerAttributesGetter<REQUEST> netAttributesGetter;
private final Function<Context, String> httpRouteHolderGetter;

HttpServerAttributesExtractor(
HttpServerAttributesGetter<REQUEST, RESPONSE> getter,
HttpServerAttributesGetter<REQUEST, RESPONSE> httpAttributesGetter,
NetServerAttributesGetter<REQUEST> netAttributesGetter,
List<String> capturedRequestHeaders,
List<String> capturedResponseHeaders) {
this(getter, capturedRequestHeaders, capturedResponseHeaders, HttpRouteHolder::getRoute);
this(
httpAttributesGetter,
netAttributesGetter,
capturedRequestHeaders,
capturedResponseHeaders,
HttpRouteHolder::getRoute);
}

// visible for tests
HttpServerAttributesExtractor(
HttpServerAttributesGetter<REQUEST, RESPONSE> getter,
HttpServerAttributesGetter<REQUEST, RESPONSE> httpAttributesGetter,
NetServerAttributesGetter<REQUEST> netAttributesGetter,
List<String> capturedRequestHeaders,
List<String> responseHeaders,
Function<Context, String> httpRouteHolderGetter) {
super(getter, capturedRequestHeaders, responseHeaders);
super(httpAttributesGetter, capturedRequestHeaders, responseHeaders);
this.netAttributesGetter = netAttributesGetter;
this.httpRouteHolderGetter = httpRouteHolderGetter;
}

Expand All @@ -79,6 +92,9 @@ public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST
internalSet(attributes, SemanticAttributes.HTTP_TARGET, getter.target(request));
internalSet(attributes, SemanticAttributes.HTTP_ROUTE, getter.route(request));
internalSet(attributes, SemanticAttributes.HTTP_CLIENT_IP, clientIp(request));

InternalNetServerAttributesExtractor.onStart(
netAttributesGetter, attributes, request, host(request));
}

@Override
Expand All @@ -93,6 +109,11 @@ public void onEnd(
internalSet(attributes, SemanticAttributes.HTTP_ROUTE, httpRouteHolderGetter.apply(context));
}

@Nullable
private String host(REQUEST request) {
return firstHeaderValue(getter.requestHeader(request, "host"));
}

@Nullable
private String forwardedProto(REQUEST request) {
// try Forwarded
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,22 @@
import static java.util.Collections.emptyList;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
import io.opentelemetry.instrumentation.api.instrumenter.net.NetServerAttributesGetter;
import java.util.List;

/** A builder of {@link HttpServerAttributesExtractor}. */
public final class HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE> {

final HttpServerAttributesGetter<REQUEST, RESPONSE> getter;
final HttpServerAttributesGetter<REQUEST, RESPONSE> httpAttributesGetter;
final NetServerAttributesGetter<REQUEST> netAttributesGetter;
List<String> capturedRequestHeaders = emptyList();
List<String> capturedResponseHeaders = emptyList();

HttpServerAttributesExtractorBuilder(HttpServerAttributesGetter<REQUEST, RESPONSE> getter) {
this.getter = getter;
HttpServerAttributesExtractorBuilder(
HttpServerAttributesGetter<REQUEST, RESPONSE> httpAttributesGetter,
NetServerAttributesGetter<REQUEST> netAttributesGetter) {
this.httpAttributesGetter = httpAttributesGetter;
this.netAttributesGetter = netAttributesGetter;
}

/**
Expand Down Expand Up @@ -64,6 +69,6 @@ public HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE> setCapturedRespon
*/
public HttpServerAttributesExtractor<REQUEST, RESPONSE> build() {
return new HttpServerAttributesExtractor<>(
getter, capturedRequestHeaders, capturedResponseHeaders);
httpAttributesGetter, netAttributesGetter, capturedRequestHeaders, capturedResponseHeaders);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@

package io.opentelemetry.instrumentation.api.instrumenter.net;

import static io.opentelemetry.instrumentation.api.internal.AttributesExtractorUtil.internalSet;

import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import io.opentelemetry.instrumentation.api.instrumenter.net.internal.InternalNetServerAttributesExtractor;
import javax.annotation.Nullable;

/**
Expand All @@ -35,50 +33,7 @@ private NetServerAttributesExtractor(NetServerAttributesGetter<REQUEST> getter)

@Override
public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST request) {
internalSet(attributes, SemanticAttributes.NET_TRANSPORT, getter.transport(request));

boolean setSockFamily = false;

String sockPeerAddr = getter.sockPeerAddr(request);
if (sockPeerAddr != null) {
setSockFamily = true;

internalSet(attributes, NetAttributes.NET_SOCK_PEER_ADDR, sockPeerAddr);

Integer sockPeerPort = getter.sockPeerPort(request);
if (sockPeerPort != null && sockPeerPort > 0) {
internalSet(attributes, NetAttributes.NET_SOCK_PEER_PORT, (long) sockPeerPort);
}
}

String hostName = getter.hostName(request);
Integer hostPort = getter.hostPort(request);
if (hostName != null) {
internalSet(attributes, SemanticAttributes.NET_HOST_NAME, hostName);

if (hostPort != null && hostPort > 0) {
internalSet(attributes, SemanticAttributes.NET_HOST_PORT, (long) hostPort);
}
}

String sockHostAddr = getter.sockHostAddr(request);
if (sockHostAddr != null && !sockHostAddr.equals(hostName)) {
setSockFamily = true;

internalSet(attributes, NetAttributes.NET_SOCK_HOST_ADDR, sockHostAddr);

Integer sockHostPort = getter.sockHostPort(request);
if (sockHostPort != null && sockHostPort > 0 && !sockHostPort.equals(hostPort)) {
internalSet(attributes, NetAttributes.NET_SOCK_HOST_PORT, (long) sockHostPort);
}
}

if (setSockFamily) {
String sockFamily = getter.sockFamily(request);
if (sockFamily != null && !NetAttributes.SOCK_FAMILY_INET.equals(sockFamily)) {
internalSet(attributes, NetAttributes.NET_SOCK_FAMILY, sockFamily);
}
}
InternalNetServerAttributesExtractor.onStart(getter, attributes, request, null);
}

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

package io.opentelemetry.instrumentation.api.instrumenter.net.internal;

import static io.opentelemetry.instrumentation.api.internal.AttributesExtractorUtil.internalSet;
import static java.util.logging.Level.FINE;

import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.instrumentation.api.instrumenter.net.NetServerAttributesGetter;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.util.logging.Logger;
import javax.annotation.Nullable;

/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public class InternalNetServerAttributesExtractor {

private static final Logger logger =
Logger.getLogger(InternalNetServerAttributesExtractor.class.getName());

public static <REQUEST> void onStart(
NetServerAttributesGetter<REQUEST> getter,
AttributesBuilder attributes,
REQUEST request,
@Nullable String hostHeader) {
internalSet(attributes, SemanticAttributes.NET_TRANSPORT, getter.transport(request));

boolean setSockFamily = false;

String sockPeerAddr = getter.sockPeerAddr(request);
if (sockPeerAddr != null) {
setSockFamily = true;

internalSet(attributes, SemanticAttributes.NET_SOCK_PEER_ADDR, sockPeerAddr);

Integer sockPeerPort = getter.sockPeerPort(request);
if (sockPeerPort != null && sockPeerPort > 0) {
internalSet(attributes, SemanticAttributes.NET_SOCK_PEER_PORT, (long) sockPeerPort);
}
}

String hostName = getter.hostName(request);
Integer hostPort = getter.hostPort(request);

int hostHeaderSeparator = -1;
if (hostHeader != null) {
hostHeaderSeparator = hostHeader.indexOf(':');
}
if (hostName == null && hostHeader != null) {
hostName =
hostHeaderSeparator == -1 ? hostHeader : hostHeader.substring(0, hostHeaderSeparator);
}
if (hostPort == null && hostHeader != null && hostHeaderSeparator != -1) {
try {
hostPort = Integer.parseInt(hostHeader.substring(hostHeaderSeparator + 1));
} catch (NumberFormatException e) {
logger.log(FINE, e.getMessage(), e);
}
}

if (hostName != null) {
internalSet(attributes, SemanticAttributes.NET_HOST_NAME, hostName);

if (hostPort != null && hostPort > 0) {
internalSet(attributes, SemanticAttributes.NET_HOST_PORT, (long) hostPort);
}
}

String sockHostAddr = getter.sockHostAddr(request);
if (sockHostAddr != null && !sockHostAddr.equals(hostName)) {
setSockFamily = true;

internalSet(attributes, SemanticAttributes.NET_SOCK_HOST_ADDR, sockHostAddr);

Integer sockHostPort = getter.sockHostPort(request);
if (sockHostPort != null && sockHostPort > 0 && !sockHostPort.equals(hostPort)) {
internalSet(attributes, SemanticAttributes.NET_SOCK_HOST_PORT, (long) sockHostPort);
}
}

if (setSockFamily) {
String sockFamily = getter.sockFamily(request);
if (sockFamily != null && !SemanticAttributes.NetSockFamilyValues.INET.equals(sockFamily)) {
internalSet(attributes, SemanticAttributes.NET_SOCK_FAMILY, sockFamily);
}
}
}

private InternalNetServerAttributesExtractor() {}
}
Loading

0 comments on commit 53c4149

Please sign in to comment.