From 34289dedb9bb5a3a391ecec42253441d672486ec Mon Sep 17 00:00:00 2001 From: Yashwant Date: Tue, 22 Jul 2025 22:24:08 +0530 Subject: [PATCH 1/3] adding client servicename as request header --- .../apache-httpclient-4.0/build.gradle.kts | 2 + .../v4_0/ApacheHttpClientUtils.java | 10 +++ instrumentation/grpc-1.6/build.gradle.kts | 1 + .../v1_6/client/GrpcClientInterceptor.java | 8 ++ .../netty/netty-4.0/build.gradle.kts | 1 + .../HttpClientRequestTracingHandler.java | 8 ++ .../netty/netty-4.1/build.gradle.kts | 1 + .../HttpClientRequestTracingHandler.java | 8 ++ .../okhttp/okhttp-3.0/build.gradle.kts | 1 + .../okhttp/v3_0/OkHttpTracingInterceptor.java | 17 ++++ .../vertx/vertx-web-3.0/build.gradle.kts | 1 + .../vertx/HttpRequestInstrumentation.java | 6 ++ .../config/ServiceNameHeaderUtils.java | 38 +++++++++ .../agent/testing/AbstractHttpClientTest.java | 77 +++++++++++++++++++ .../agent/testing/TestHttpServer.java | 55 +++++++++++++ 15 files changed, 234 insertions(+) create mode 100644 otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/config/ServiceNameHeaderUtils.java diff --git a/instrumentation/apache-httpclient-4.0/build.gradle.kts b/instrumentation/apache-httpclient-4.0/build.gradle.kts index 9c4503a4..0cc1f9bc 100644 --- a/instrumentation/apache-httpclient-4.0/build.gradle.kts +++ b/instrumentation/apache-httpclient-4.0/build.gradle.kts @@ -41,6 +41,8 @@ val versions: Map by extra dependencies { api(project(":instrumentation:java-streams")) + api(project(":otel-extensions")) + library("org.apache.httpcomponents:httpclient:4.0") testImplementation(project(":testing-common")) } diff --git a/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/ApacheHttpClientUtils.java b/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/ApacheHttpClientUtils.java index 77cec83e..637be8ff 100644 --- a/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/ApacheHttpClientUtils.java +++ b/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/ApacheHttpClientUtils.java @@ -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; @@ -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, @@ -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; diff --git a/instrumentation/grpc-1.6/build.gradle.kts b/instrumentation/grpc-1.6/build.gradle.kts index 3ee2adb2..4606f84c 100644 --- a/instrumentation/grpc-1.6/build.gradle.kts +++ b/instrumentation/grpc-1.6/build.gradle.kts @@ -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")) diff --git a/instrumentation/grpc-1.6/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/grpc/v1_6/client/GrpcClientInterceptor.java b/instrumentation/grpc-1.6/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/grpc/v1_6/client/GrpcClientInterceptor.java index 3c59e306..5e587102 100644 --- a/instrumentation/grpc-1.6/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/grpc/v1_6/client/GrpcClientInterceptor.java +++ b/instrumentation/grpc-1.6/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/grpc/v1_6/client/GrpcClientInterceptor.java @@ -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 SERVICE_NAME_METADATA_KEY = + Metadata.Key.of( + ServiceNameHeaderUtils.getClientServiceKey(), Metadata.ASCII_STRING_MARSHALLER); + private static final Logger log = LoggerFactory.getLogger(GrpcClientInterceptor.class); @Override @@ -69,6 +74,9 @@ static final class TracingClientCall @Override public void start(Listener 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 { diff --git a/instrumentation/netty/netty-4.0/build.gradle.kts b/instrumentation/netty/netty-4.0/build.gradle.kts index b8cab061..31c9a1f7 100644 --- a/instrumentation/netty/netty-4.0/build.gradle.kts +++ b/instrumentation/netty/netty-4.0/build.gradle.kts @@ -46,6 +46,7 @@ val versions: Map 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"]}") diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/HttpClientRequestTracingHandler.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/HttpClientRequestTracingHandler.java index 4c4af06b..db12ff1d 100644 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/HttpClientRequestTracingHandler.java +++ b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/HttpClientRequestTracingHandler.java @@ -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 { @@ -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 diff --git a/instrumentation/netty/netty-4.1/build.gradle.kts b/instrumentation/netty/netty-4.1/build.gradle.kts index 43fb115c..5bacf427 100644 --- a/instrumentation/netty/netty-4.1/build.gradle.kts +++ b/instrumentation/netty/netty-4.1/build.gradle.kts @@ -44,6 +44,7 @@ afterEvaluate{ val versions: Map 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"]}") diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/HttpClientRequestTracingHandler.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/HttpClientRequestTracingHandler.java index b6775666..74ecb043 100644 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/HttpClientRequestTracingHandler.java +++ b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/HttpClientRequestTracingHandler.java @@ -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 { @@ -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 diff --git a/instrumentation/okhttp/okhttp-3.0/build.gradle.kts b/instrumentation/okhttp/okhttp-3.0/build.gradle.kts index 3c6371dc..b3828543 100644 --- a/instrumentation/okhttp/okhttp-3.0/build.gradle.kts +++ b/instrumentation/okhttp/okhttp-3.0/build.gradle.kts @@ -26,6 +26,7 @@ afterEvaluate{ val versions: Map by extra dependencies { + api(project(":otel-extensions")) compileOnly("com.squareup.okhttp3:okhttp:3.0.0") testImplementation(project(":testing-common")) } diff --git a/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/okhttp/v3_0/OkHttpTracingInterceptor.java b/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/okhttp/v3_0/OkHttpTracingInterceptor.java index 9ba992a6..7281c95d 100644 --- a/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/okhttp/v3_0/OkHttpTracingInterceptor.java +++ b/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/okhttp/v3_0/OkHttpTracingInterceptor.java @@ -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; @@ -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); @@ -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; + } } diff --git a/instrumentation/vertx/vertx-web-3.0/build.gradle.kts b/instrumentation/vertx/vertx-web-3.0/build.gradle.kts index 942e1e73..bf2cce05 100644 --- a/instrumentation/vertx/vertx-web-3.0/build.gradle.kts +++ b/instrumentation/vertx/vertx-web-3.0/build.gradle.kts @@ -27,6 +27,7 @@ val versions: Map 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"]}") diff --git a/instrumentation/vertx/vertx-web-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/vertx/HttpRequestInstrumentation.java b/instrumentation/vertx/vertx-web-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/vertx/HttpRequestInstrumentation.java index 02c60d0f..38d6c85d 100644 --- a/instrumentation/vertx/vertx-web-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/vertx/HttpRequestInstrumentation.java +++ b/instrumentation/vertx/vertx-web-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/vertx/HttpRequestInstrumentation.java @@ -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 { @@ -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; diff --git a/otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/config/ServiceNameHeaderUtils.java b/otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/config/ServiceNameHeaderUtils.java new file mode 100644 index 00000000..96e33617 --- /dev/null +++ b/otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/config/ServiceNameHeaderUtils.java @@ -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(); + } +} diff --git a/testing-common/src/main/java/org/hypertrace/agent/testing/AbstractHttpClientTest.java b/testing-common/src/main/java/org/hypertrace/agent/testing/AbstractHttpClientTest.java index d6b7fad7..16e21d21 100644 --- a/testing-common/src/main/java/org/hypertrace/agent/testing/AbstractHttpClientTest.java +++ b/testing-common/src/main/java/org/hypertrace/agent/testing/AbstractHttpClientTest.java @@ -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 headers; @@ -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> 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, diff --git a/testing-common/src/main/java/org/hypertrace/agent/testing/TestHttpServer.java b/testing-common/src/main/java/org/hypertrace/agent/testing/TestHttpServer.java index 7e49ab1c..32f30d25 100644 --- a/testing-common/src/main/java/org/hypertrace/agent/testing/TestHttpServer.java +++ b/testing-common/src/main/java/org/hypertrace/agent/testing/TestHttpServer.java @@ -19,6 +19,9 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; import java.util.zip.GZIPOutputStream; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; @@ -45,6 +48,7 @@ public void start() throws Exception { handlerList.addHandler(new PostRedirect()); handlerList.addHandler(new EchoHandler()); handlerList.addHandler(new GzipHandler()); + handlerList.addHandler(new HeaderVerificationHandler()); server.setHandler(handlerList); server.start(); } @@ -215,4 +219,55 @@ public void handle( } } } + + public static class HeaderVerificationHandler extends ResponseTestHeadersHandler { + + public static final String VERIFY_HEADER_PATH = "/verify_headers"; + public static final String HEADER_ECHO_PREFIX = "echo-header-"; + public static final String SERVICE_NAME_HEADER_KEY = "ta-client-servicename"; + public static final String RECEIVED_HEADER_JSON_FORMAT = + "{\"received_header\":\"%s\",\"header_value\":\"%s\"}"; + + @Override + public void handle( + String target, + Request baseRequest, + HttpServletRequest request, + HttpServletResponse response) + throws IOException { + + if (target.equals(VERIFY_HEADER_PATH)) { + response.setStatus(200); + response.setContentType("application/json"); + + // Get all headers from the request + Map headers = new HashMap<>(); + Enumeration headerNames = request.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + String headerValue = request.getHeader(headerName); + headers.put(headerName, headerValue); + + // Echo back the headers in the response with a prefix + response.setHeader(HEADER_ECHO_PREFIX + headerName, headerValue); + } + + // Check specifically for our service name header + String serviceNameHeaderValue = request.getHeader(SERVICE_NAME_HEADER_KEY); + if (serviceNameHeaderValue != null) { + response + .getWriter() + .print( + String.format( + RECEIVED_HEADER_JSON_FORMAT, + SERVICE_NAME_HEADER_KEY, + serviceNameHeaderValue)); + } else { + response.getWriter().print("{\"received_header\":\"none\"}"); + } + + baseRequest.setHandled(true); + } + } + } } From e80b6e5a059fc438b57e386b317590fc5fe1c5aa Mon Sep 17 00:00:00 2001 From: Yashwant Date: Mon, 25 Aug 2025 12:07:10 +0530 Subject: [PATCH 2/3] placing ServiceNameHeaderUtils in javaagent-core --- instrumentation/apache-httpclient-4.0/build.gradle.kts | 1 - .../apachehttpclient/v4_0/ApacheHttpClientUtils.java | 2 +- instrumentation/grpc-1.6/build.gradle.kts | 1 - .../grpc/v1_6/client/GrpcClientInterceptor.java | 2 +- instrumentation/netty/netty-4.0/build.gradle.kts | 1 - .../v4_0/client/HttpClientRequestTracingHandler.java | 2 +- instrumentation/netty/netty-4.1/build.gradle.kts | 1 - .../v4_1/client/HttpClientRequestTracingHandler.java | 2 +- instrumentation/okhttp/okhttp-3.0/build.gradle.kts | 1 - .../hypertrace/okhttp/v3_0/OkHttpTracingInterceptor.java | 2 +- instrumentation/vertx/vertx-web-3.0/build.gradle.kts | 1 - .../hypertrace/vertx/HttpRequestInstrumentation.java | 2 +- .../agent/core/config/InstrumentationConfig.java | 3 +++ .../instrumentation/utils}/ServiceNameHeaderUtils.java | 8 ++++++-- .../otel/extensions/config/InstrumentationConfigImpl.java | 5 +++++ 15 files changed, 20 insertions(+), 14 deletions(-) rename {otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/config => javaagent-core/src/main/java/org/hypertrace/agent/core/instrumentation/utils}/ServiceNameHeaderUtils.java (81%) diff --git a/instrumentation/apache-httpclient-4.0/build.gradle.kts b/instrumentation/apache-httpclient-4.0/build.gradle.kts index 0cc1f9bc..cb9a03c2 100644 --- a/instrumentation/apache-httpclient-4.0/build.gradle.kts +++ b/instrumentation/apache-httpclient-4.0/build.gradle.kts @@ -41,7 +41,6 @@ val versions: Map by extra dependencies { api(project(":instrumentation:java-streams")) - api(project(":otel-extensions")) library("org.apache.httpcomponents:httpclient:4.0") testImplementation(project(":testing-common")) diff --git a/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/ApacheHttpClientUtils.java b/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/ApacheHttpClientUtils.java index 637be8ff..0616241a 100644 --- a/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/ApacheHttpClientUtils.java +++ b/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/ApacheHttpClientUtils.java @@ -40,7 +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.hypertrace.agent.core.instrumentation.utils.ServiceNameHeaderUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/instrumentation/grpc-1.6/build.gradle.kts b/instrumentation/grpc-1.6/build.gradle.kts index 4606f84c..3ee2adb2 100644 --- a/instrumentation/grpc-1.6/build.gradle.kts +++ b/instrumentation/grpc-1.6/build.gradle.kts @@ -59,7 +59,6 @@ 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")) diff --git a/instrumentation/grpc-1.6/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/grpc/v1_6/client/GrpcClientInterceptor.java b/instrumentation/grpc-1.6/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/grpc/v1_6/client/GrpcClientInterceptor.java index 5e587102..825ecbae 100644 --- a/instrumentation/grpc-1.6/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/grpc/v1_6/client/GrpcClientInterceptor.java +++ b/instrumentation/grpc-1.6/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/grpc/v1_6/client/GrpcClientInterceptor.java @@ -30,7 +30,7 @@ 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.hypertrace.agent.core.instrumentation.utils.ServiceNameHeaderUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/instrumentation/netty/netty-4.0/build.gradle.kts b/instrumentation/netty/netty-4.0/build.gradle.kts index 31c9a1f7..b8cab061 100644 --- a/instrumentation/netty/netty-4.0/build.gradle.kts +++ b/instrumentation/netty/netty-4.0/build.gradle.kts @@ -46,7 +46,6 @@ val versions: Map 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"]}") diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/HttpClientRequestTracingHandler.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/HttpClientRequestTracingHandler.java index db12ff1d..bd721cb1 100644 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/HttpClientRequestTracingHandler.java +++ b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/HttpClientRequestTracingHandler.java @@ -40,7 +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; +import org.hypertrace.agent.core.instrumentation.utils.ServiceNameHeaderUtils; public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapter { diff --git a/instrumentation/netty/netty-4.1/build.gradle.kts b/instrumentation/netty/netty-4.1/build.gradle.kts index 5bacf427..43fb115c 100644 --- a/instrumentation/netty/netty-4.1/build.gradle.kts +++ b/instrumentation/netty/netty-4.1/build.gradle.kts @@ -44,7 +44,6 @@ afterEvaluate{ val versions: Map 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"]}") diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/HttpClientRequestTracingHandler.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/HttpClientRequestTracingHandler.java index 74ecb043..6f5bda18 100644 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/HttpClientRequestTracingHandler.java +++ b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/HttpClientRequestTracingHandler.java @@ -40,7 +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; +import org.hypertrace.agent.core.instrumentation.utils.ServiceNameHeaderUtils; public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapter { diff --git a/instrumentation/okhttp/okhttp-3.0/build.gradle.kts b/instrumentation/okhttp/okhttp-3.0/build.gradle.kts index b3828543..3c6371dc 100644 --- a/instrumentation/okhttp/okhttp-3.0/build.gradle.kts +++ b/instrumentation/okhttp/okhttp-3.0/build.gradle.kts @@ -26,7 +26,6 @@ afterEvaluate{ val versions: Map by extra dependencies { - api(project(":otel-extensions")) compileOnly("com.squareup.okhttp3:okhttp:3.0.0") testImplementation(project(":testing-common")) } diff --git a/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/okhttp/v3_0/OkHttpTracingInterceptor.java b/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/okhttp/v3_0/OkHttpTracingInterceptor.java index 7281c95d..dfafad5d 100644 --- a/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/okhttp/v3_0/OkHttpTracingInterceptor.java +++ b/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/okhttp/v3_0/OkHttpTracingInterceptor.java @@ -36,7 +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.hypertrace.agent.core.instrumentation.utils.ServiceNameHeaderUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/instrumentation/vertx/vertx-web-3.0/build.gradle.kts b/instrumentation/vertx/vertx-web-3.0/build.gradle.kts index bf2cce05..942e1e73 100644 --- a/instrumentation/vertx/vertx-web-3.0/build.gradle.kts +++ b/instrumentation/vertx/vertx-web-3.0/build.gradle.kts @@ -27,7 +27,6 @@ val versions: Map 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"]}") diff --git a/instrumentation/vertx/vertx-web-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/vertx/HttpRequestInstrumentation.java b/instrumentation/vertx/vertx-web-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/vertx/HttpRequestInstrumentation.java index 38d6c85d..31eb3eb9 100644 --- a/instrumentation/vertx/vertx-web-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/vertx/HttpRequestInstrumentation.java +++ b/instrumentation/vertx/vertx-web-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/vertx/HttpRequestInstrumentation.java @@ -43,7 +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; +import org.hypertrace.agent.core.instrumentation.utils.ServiceNameHeaderUtils; public class HttpRequestInstrumentation implements TypeInstrumentation { diff --git a/javaagent-core/src/main/java/org/hypertrace/agent/core/config/InstrumentationConfig.java b/javaagent-core/src/main/java/org/hypertrace/agent/core/config/InstrumentationConfig.java index ee8e3adb..e140f16d 100644 --- a/javaagent-core/src/main/java/org/hypertrace/agent/core/config/InstrumentationConfig.java +++ b/javaagent-core/src/main/java/org/hypertrace/agent/core/config/InstrumentationConfig.java @@ -27,6 +27,9 @@ public interface InstrumentationConfig { /** Maximum capture body size in bytes. */ int maxBodySizeBytes(); + /** Service name. */ + String getServiceName(); + /** Data capture for HTTP headers. */ Message httpHeaders(); diff --git a/otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/config/ServiceNameHeaderUtils.java b/javaagent-core/src/main/java/org/hypertrace/agent/core/instrumentation/utils/ServiceNameHeaderUtils.java similarity index 81% rename from otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/config/ServiceNameHeaderUtils.java rename to javaagent-core/src/main/java/org/hypertrace/agent/core/instrumentation/utils/ServiceNameHeaderUtils.java index 96e33617..f90344e0 100644 --- a/otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/config/ServiceNameHeaderUtils.java +++ b/javaagent-core/src/main/java/org/hypertrace/agent/core/instrumentation/utils/ServiceNameHeaderUtils.java @@ -14,13 +14,17 @@ * limitations under the License. */ -package org.hypertrace.agent.otel.extensions.config; +package org.hypertrace.agent.core.instrumentation.utils; + +import org.hypertrace.agent.core.config.InstrumentationConfig; /** 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 static final String serviceName = InstrumentationConfig.ConfigProvider.get().getServiceName(); + private ServiceNameHeaderUtils() {} public static String getClientServiceKey() { @@ -33,6 +37,6 @@ public static String getClientServiceKey() { * @return the service name configured in the agent */ public static String getClientServiceName() { - return HypertraceConfig.get().getServiceName().getValue(); + return serviceName; } } diff --git a/otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/config/InstrumentationConfigImpl.java b/otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/config/InstrumentationConfigImpl.java index 8e087348..f2f8e7b9 100644 --- a/otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/config/InstrumentationConfigImpl.java +++ b/otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/config/InstrumentationConfigImpl.java @@ -46,6 +46,11 @@ public int maxBodySizeBytes() { return agentConfig.getDataCapture().getBodyMaxSizeBytes().getValue(); } + @Override + public String getServiceName() { + return agentConfig.getServiceName().getValue(); + } + @Override public Message httpHeaders() { return this.httpHeaders; From 87d7f58b80495e6b51a3242ce91c767b8e8c616f Mon Sep 17 00:00:00 2001 From: Yashwant Date: Mon, 25 Aug 2025 12:11:52 +0530 Subject: [PATCH 3/3] spotless apply --- .../core/instrumentation/utils/ServiceNameHeaderUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javaagent-core/src/main/java/org/hypertrace/agent/core/instrumentation/utils/ServiceNameHeaderUtils.java b/javaagent-core/src/main/java/org/hypertrace/agent/core/instrumentation/utils/ServiceNameHeaderUtils.java index f90344e0..cb5ef34b 100644 --- a/javaagent-core/src/main/java/org/hypertrace/agent/core/instrumentation/utils/ServiceNameHeaderUtils.java +++ b/javaagent-core/src/main/java/org/hypertrace/agent/core/instrumentation/utils/ServiceNameHeaderUtils.java @@ -23,7 +23,8 @@ public class ServiceNameHeaderUtils { private static final String SERVICE_NAME_HEADER = "ta-client-servicename"; - private static final String serviceName = InstrumentationConfig.ConfigProvider.get().getServiceName(); + private static final String serviceName = + InstrumentationConfig.ConfigProvider.get().getServiceName(); private ServiceNameHeaderUtils() {}