Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions instrumentation/apache-httpclient-4.0/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ val versions: Map<String, String> by extra

dependencies {
api(project(":instrumentation:java-streams"))
api(project(":otel-extensions"))

library("org.apache.httpcomponents:httpclient:4.0")
testImplementation(project(":testing-common"))
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.hypertrace.agent.core.instrumentation.buffer.BoundedByteArrayOutputStream;
import org.hypertrace.agent.core.instrumentation.utils.ContentTypeCharsetUtils;
import org.hypertrace.agent.core.instrumentation.utils.ContentTypeUtils;
import org.hypertrace.agent.otel.extensions.config.ServiceNameHeaderUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -58,6 +59,12 @@ public static void addRequestHeaders(Span span, HeaderIterator headerIterator) {
addHeaders(span, headerIterator, HypertraceSemanticAttributes::httpRequestHeader);
}

public static void addClientServiceNameHeader(HttpMessage request) {
request.addHeader(
ServiceNameHeaderUtils.getClientServiceKey(),
ServiceNameHeaderUtils.getClientServiceName());
}

private static void addHeaders(
Span span,
HeaderIterator headerIterator,
Expand All @@ -73,6 +80,9 @@ public static void traceRequest(Span span, HttpMessage request) {
ApacheHttpClientUtils.addRequestHeaders(span, request.headerIterator());
}

// Add service name header to outgoing requests
ApacheHttpClientUtils.addClientServiceNameHeader(request);

if (instrumentationConfig.httpBody().request()
&& request instanceof HttpEntityEnclosingRequest) {
HttpEntityEnclosingRequest entityRequest = (HttpEntityEnclosingRequest) request;
Expand Down
1 change: 1 addition & 0 deletions instrumentation/grpc-1.6/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ val grpcVersion = "1.6.0"

dependencies {
api("io.opentelemetry.instrumentation:opentelemetry-grpc-1.6:${versions["opentelemetry_java_agent"]}")
api(project(":otel-extensions"))
implementation(project(":instrumentation:grpc-common"))
implementation(project(":shaded-protobuf-java-util", "shadow"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,16 @@
import io.opentelemetry.javaagent.instrumentation.hypertrace.grpc.v1_6.GrpcSpanDecorator;
import org.hypertrace.agent.core.config.InstrumentationConfig;
import org.hypertrace.agent.core.instrumentation.HypertraceSemanticAttributes;
import org.hypertrace.agent.otel.extensions.config.ServiceNameHeaderUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GrpcClientInterceptor implements ClientInterceptor {

private static final Metadata.Key<String> SERVICE_NAME_METADATA_KEY =
Metadata.Key.of(
ServiceNameHeaderUtils.getClientServiceKey(), Metadata.ASCII_STRING_MARSHALLER);

private static final Logger log = LoggerFactory.getLogger(GrpcClientInterceptor.class);

@Override
Expand Down Expand Up @@ -69,6 +74,9 @@ static final class TracingClientCall<ReqT, RespT>

@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
// Add service name header to outgoing requests
headers.put(SERVICE_NAME_METADATA_KEY, ServiceNameHeaderUtils.getClientServiceName());

super.start(new TracingClientCallListener<>(responseListener, span), headers);

try {
Expand Down
1 change: 1 addition & 0 deletions instrumentation/netty/netty-4.0/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ val versions: Map<String, String> by extra
val nettyVersion = "4.0.38.Final"

dependencies {
api(project(":otel-extensions"))
implementation("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-netty-4.0:${versions["opentelemetry_java_agent"]}")
implementation("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-netty-4-common:${versions["opentelemetry_java_agent"]}")
implementation("io.opentelemetry.instrumentation:opentelemetry-netty-4-common:${versions["opentelemetry_java_agent"]}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.hypertrace.agent.core.instrumentation.utils.ContentLengthUtils;
import org.hypertrace.agent.core.instrumentation.utils.ContentTypeCharsetUtils;
import org.hypertrace.agent.core.instrumentation.utils.ContentTypeUtils;
import org.hypertrace.agent.otel.extensions.config.ServiceNameHeaderUtils;

public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapter {

Expand Down Expand Up @@ -68,6 +69,13 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise prm) {
headersMap.forEach(span::setAttribute);
}

// Add service name header to outgoing requests
httpRequest
.headers()
.add(
ServiceNameHeaderUtils.getClientServiceKey(),
ServiceNameHeaderUtils.getClientServiceName());

CharSequence contentType = DataCaptureUtils.getContentType(httpRequest);
if (instrumentationConfig.httpBody().request()
&& contentType != null
Expand Down
1 change: 1 addition & 0 deletions instrumentation/netty/netty-4.1/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ afterEvaluate{
val versions: Map<String, String> by extra

dependencies {
api(project(":otel-extensions"))
implementation("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-netty-4-common:${versions["opentelemetry_java_agent"]}")
implementation("io.opentelemetry.instrumentation:opentelemetry-netty-common:${versions["opentelemetry_java_agent"]}")
implementation("io.opentelemetry.instrumentation:opentelemetry-netty-4-common:${versions["opentelemetry_java_agent"]}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.hypertrace.agent.core.instrumentation.utils.ContentLengthUtils;
import org.hypertrace.agent.core.instrumentation.utils.ContentTypeCharsetUtils;
import org.hypertrace.agent.core.instrumentation.utils.ContentTypeUtils;
import org.hypertrace.agent.otel.extensions.config.ServiceNameHeaderUtils;

public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapter {

Expand Down Expand Up @@ -67,6 +68,13 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise prm) {
headersMap.forEach(span::setAttribute);
}

// Add service name header to outgoing requests
httpRequest
.headers()
.add(
ServiceNameHeaderUtils.getClientServiceKey(),
ServiceNameHeaderUtils.getClientServiceName());

CharSequence contentType = DataCaptureUtils.getContentType(httpRequest);
if (instrumentationConfig.httpBody().request()
&& contentType != null
Expand Down
1 change: 1 addition & 0 deletions instrumentation/okhttp/okhttp-3.0/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ afterEvaluate{
val versions: Map<String, String> by extra

dependencies {
api(project(":otel-extensions"))
compileOnly("com.squareup.okhttp3:okhttp:3.0.0")
testImplementation(project(":testing-common"))
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.hypertrace.agent.core.config.InstrumentationConfig;
import org.hypertrace.agent.core.instrumentation.HypertraceSemanticAttributes;
import org.hypertrace.agent.core.instrumentation.utils.ContentTypeUtils;
import org.hypertrace.agent.otel.extensions.config.ServiceNameHeaderUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -57,6 +58,10 @@ public Response intercept(Chain chain) throws IOException {
if (instrumentationConfig.httpHeaders().request()) {
captureHeaders(span, request.headers(), HypertraceSemanticAttributes::httpRequestHeader);
}

// Add service name header to outgoing requests
request = addClientSeriveNameHeader(request);

captureRequestBody(span, request.body());

Response response = chain.proceed(request);
Expand Down Expand Up @@ -149,4 +154,16 @@ private static void captureHeaders(
}
}
}

private static Request addClientSeriveNameHeader(Request request) {
// Add service name header to outgoing requests
request =
request
.newBuilder()
.addHeader(
ServiceNameHeaderUtils.getClientServiceKey(),
ServiceNameHeaderUtils.getClientServiceName())
.build();
return request;
}
}
1 change: 1 addition & 0 deletions instrumentation/vertx/vertx-web-3.0/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ val versions: Map<String, String> by extra
val nettyVersion = "4.0.28.Final"

dependencies {
api(project(":otel-extensions"))
implementation("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-vertx-web-3.0:${versions["opentelemetry_java_agent"]}")
implementation("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-vertx-http-client-3.0:${versions["opentelemetry_java_agent"]}")
implementation("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-vertx-http-client-common:${versions["opentelemetry_java_agent"]}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.hypertrace.agent.core.instrumentation.buffer.BoundedBuffersFactory;
import org.hypertrace.agent.core.instrumentation.buffer.BoundedCharArrayWriter;
import org.hypertrace.agent.core.instrumentation.utils.ContentTypeUtils;
import org.hypertrace.agent.otel.extensions.config.ServiceNameHeaderUtils;

public class HttpRequestInstrumentation implements TypeInstrumentation {

Expand Down Expand Up @@ -93,6 +94,11 @@ public static void enter(@Advice.This HttpClientRequest request) {
return;
}

request
.headers()
.add(
ServiceNameHeaderUtils.getClientServiceKey(),
ServiceNameHeaderUtils.getClientServiceName());
Contexts contexts = VirtualField.find(HttpClientRequest.class, Contexts.class).get(request);
if (contexts == null) {
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright The Hypertrace 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 org.hypertrace.agent.otel.extensions.config;

/** Utility class for adding service name header to outgoing requests (exit calls). */
public class ServiceNameHeaderUtils {

private static final String SERVICE_NAME_HEADER = "ta-client-servicename";

private ServiceNameHeaderUtils() {}

public static String getClientServiceKey() {
return SERVICE_NAME_HEADER;
}

/**
* Gets the service name from HypertraceConfig.
*
* @return the service name configured in the agent
*/
public static String getClientServiceName() {
return HypertraceConfig.get().getServiceName().getValue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public abstract class AbstractHttpClientTest extends AbstractInstrumenterTest {
private static final String GET_NO_CONTENT_PATH_FORMAT = "http://localhost:%d/get_no_content";
private static final String GET_JSON_PATH_FORMAT = "http://localhost:%d/get_json";
private static final String GET_GZIP_FORMAT = "http://localhost:%d/gzip";
private static final String VERIFY_HEADERS_FORMAT = "http://localhost:%d/verify_headers";
private static final String HEADER_NAME = "headername";
private static final String HEADER_VALUE = "headerValue";
private static final Map<String, String> headers;
Expand Down Expand Up @@ -358,6 +359,82 @@ public void getGzipResponse()
}
}

@Test
public void verifyServiceNameHeader()
throws IOException, TimeoutException, InterruptedException, ExecutionException {
String uri = String.format(VERIFY_HEADERS_FORMAT, testHttpServer.port());

Response response = doGetRequest(uri, headers);

Assertions.assertEquals(200, response.statusCode);
Assertions.assertTrue(
response.body.contains(TestHttpServer.HeaderVerificationHandler.SERVICE_NAME_HEADER_KEY),
"Response should indicate that the service name header was received");
// The response format is
// {"received_header":"ta-client-servicename","header_value":"ACTUAL_VALUE"}
Assertions.assertTrue(
response.body.contains("received_header"),
"Response should confirm that headers were processed");
Assertions.assertTrue(
response.body.contains("header_value"),
"Response should include the header value that was sent");

TEST_WRITER.waitForTraces(1);
List<List<Span>> traces;
if (hasResponseBodySpan) {
traces =
TEST_WRITER.waitForSpans(
2, span -> span.getKind().equals(Span.SpanKind.SPAN_KIND_SERVER));
} else {
traces =
TEST_WRITER.waitForSpans(
1,
span ->
!span.getKind().equals(Span.SpanKind.SPAN_KIND_CLIENT)
|| span.getAttributesList().stream()
.noneMatch(
keyValue ->
keyValue.getKey().equals("http.url")
&& keyValue
.getValue()
.getStringValue()
.contains("/verify_headers")));
}

Assertions.assertEquals(1, traces.size());
Span clientSpan = traces.get(0).get(0);
if (hasResponseBodySpan) {
Assertions.assertEquals(2, traces.get(0).size());
Span responseBodySpan = traces.get(0).get(1);
if (traces.get(0).get(1).getKind().equals(Span.SpanKind.SPAN_KIND_CLIENT)) {
responseBodySpan = traces.get(0).get(0);
clientSpan = traces.get(0).get(1);
}

Assertions.assertNull(TEST_WRITER.getAttributesMap(clientSpan).get("http.response.body"));

Assertions.assertTrue(
TEST_WRITER
.getAttributesMap(responseBodySpan)
.get("http.response.body")
.getStringValue()
.contains("received_header"),
"Response body should confirm that echo headers reached server");

} else {
String clientServiceNameResponseHeaderKey =
"http.response.header."
+ TestHttpServer.HeaderVerificationHandler.HEADER_ECHO_PREFIX
+ TestHttpServer.HeaderVerificationHandler.SERVICE_NAME_HEADER_KEY;
Assertions.assertEquals(
TEST_WRITER
.getAttributesMap(clientSpan)
.get(clientServiceNameResponseHeaderKey)
.getStringValue(),
"unknown");
}
}

private void assertHeaders(Span span) {
Assertions.assertEquals(
TestHttpServer.RESPONSE_HEADER_VALUE,
Expand Down
Loading
Loading