From f7ddff25412bce75a5d5b58283167732eb661bb1 Mon Sep 17 00:00:00 2001 From: Yashwant Date: Tue, 2 Sep 2025 18:43:25 +0530 Subject: [PATCH 1/4] revert 2dff5262c6dc88d028ab276d3f6e8f3b924f3a09 --- .../NettyChannelPipelineInstrumentation.java | 6 +- .../OtelHttpClientRequestTracingHandler.java | 117 ----------------- .../HttpServerRequestTracingHandler.java | 71 +++++----- .../NettyChannelPipelineInstrumentation.java | 6 +- .../OtelHttpClientRequestTracingHandler.java | 121 ------------------ .../HttpServerRequestTracingHandler.java | 75 +++++------ 6 files changed, 69 insertions(+), 327 deletions(-) delete mode 100644 instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/OtelHttpClientRequestTracingHandler.java delete mode 100644 instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/OtelHttpClientRequestTracingHandler.java diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/NettyChannelPipelineInstrumentation.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/NettyChannelPipelineInstrumentation.java index af4878f7c..c979ccc05 100644 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/NettyChannelPipelineInstrumentation.java +++ b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/NettyChannelPipelineInstrumentation.java @@ -36,7 +36,6 @@ import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_0.client.HttpClientRequestTracingHandler; import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_0.client.HttpClientResponseTracingHandler; import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_0.client.HttpClientTracingHandler; -import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_0.client.OtelHttpClientRequestTracingHandler; import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_0.server.HttpServerBlockingRequestHandler; import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_0.server.HttpServerRequestTracingHandler; import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_0.server.HttpServerResponseTracingHandler; @@ -136,13 +135,14 @@ public static void addHandler( HttpClientTracingHandler.class.getName(), new HttpClientTracingHandler()); - // add our custom request handler to start spans with proper context propagation + // add OTEL request handler to start spans pipeline.addAfter( HttpClientTracingHandler.class.getName(), io.opentelemetry.javaagent.instrumentation.netty.v4_0.client .HttpClientRequestTracingHandler.class .getName(), - new OtelHttpClientRequestTracingHandler()); + new io.opentelemetry.javaagent.instrumentation.netty.v4_0.client + .HttpClientRequestTracingHandler()); } else if (handler instanceof HttpRequestEncoder) { pipeline.addLast( HttpClientRequestTracingHandler.class.getName(), diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/OtelHttpClientRequestTracingHandler.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/OtelHttpClientRequestTracingHandler.java deleted file mode 100644 index 768c36797..000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/OtelHttpClientRequestTracingHandler.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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 io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_0.client; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpRequest; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.netty.v4_0.AttributeKeys; -import io.opentelemetry.javaagent.instrumentation.netty.v4_0.client.HttpClientRequestTracingHandler; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Custom extension of OpenTelemetry's HttpClientRequestTracingHandler that ensures proper context - * propagation by using Context.current() as the parent context. - */ -public class OtelHttpClientRequestTracingHandler extends HttpClientRequestTracingHandler { - - // Store the server context for each thread - private static final ThreadLocal SERVER_CONTEXT = new ThreadLocal<>(); - - // Store the mapping from thread ID to server span context (for cross-thread scenarios) - private static final ConcurrentHashMap THREAD_TO_SPAN_CONTEXT = - new ConcurrentHashMap<>(); - - // Maximum size for the thread map before triggering cleanup - private static final int MAX_THREAD_MAP_SIZE = 1000; - - // Cleanup flag to avoid excessive synchronized blocks - private static volatile boolean cleanupNeeded = false; - - public OtelHttpClientRequestTracingHandler() { - super(); - } - - /** - * Stores the current context as the server context for this thread. This should be called from - * the server handler. - */ - public static void storeServerContext(Context context) { - SERVER_CONTEXT.set(context); - - // Also store the span context by thread ID for cross-thread lookup - Span span = Span.fromContext(context); - if (span != null && span.getSpanContext().isValid()) { - THREAD_TO_SPAN_CONTEXT.put(Thread.currentThread().getId(), span.getSpanContext()); - - // Check if we need to clean up the map - if (THREAD_TO_SPAN_CONTEXT.size() > MAX_THREAD_MAP_SIZE) { - cleanupNeeded = true; - } - } - } - - /** - * Perform cleanup of the thread map if it has grown too large. This is done in a synchronized - * block to prevent concurrent modification issues. - */ - private static void cleanupThreadMapIfNeeded() { - if (cleanupNeeded) { - synchronized (THREAD_TO_SPAN_CONTEXT) { - if (THREAD_TO_SPAN_CONTEXT.size() > MAX_THREAD_MAP_SIZE) { - THREAD_TO_SPAN_CONTEXT.clear(); - cleanupNeeded = false; - } - } - } - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise prm) { - try { - if (!(msg instanceof HttpRequest)) { - super.write(ctx, msg, prm); - return; - } - - Context parentContext = SERVER_CONTEXT.get(); - - // Fallback -> If no context in thread local, try Context.current() - if (parentContext == null) { - parentContext = Context.current(); - } - - // Store the parent context in the channel attributes - // This is used by the Opentelemetry's HttpClientRequestTracingHandler in propagating correct - // context. - ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT).set(parentContext); - - // Call the parent implementation which will use our stored parent context - super.write(ctx, msg, prm); - - // Clean up after use to prevent memory leaks - SERVER_CONTEXT.remove(); - THREAD_TO_SPAN_CONTEXT.remove(Thread.currentThread().getId()); - cleanupThreadMapIfNeeded(); - - } catch (Exception ignored) { - } - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/server/HttpServerRequestTracingHandler.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/server/HttpServerRequestTracingHandler.java index 2dcd6df34..815a9cf64 100644 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/server/HttpServerRequestTracingHandler.java +++ b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/server/HttpServerRequestTracingHandler.java @@ -27,10 +27,8 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_0.AttributeKeys; import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_0.DataCaptureUtils; -import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_0.client.OtelHttpClientRequestTracingHandler; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; @@ -59,54 +57,47 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { ctx.fireChannelRead(msg); return; } + Span span = Span.fromContext(context); - // Store the server context in our ThreadLocal for later use by client handlers - // This is CRITICAL for proper context propagation to client spans - OtelHttpClientRequestTracingHandler.storeServerContext(context); + if (msg instanceof HttpRequest) { + HttpRequest httpRequest = (HttpRequest) msg; - try (Scope ignored = context.makeCurrent()) { - Span span = Span.fromContext(context); - - if (msg instanceof HttpRequest) { - HttpRequest httpRequest = (HttpRequest) msg; - - Map headersMap = headersToMap(httpRequest); - if (instrumentationConfig.httpHeaders().request()) { - headersMap.forEach(span::setAttribute); - } - // used by blocking handler - channel.attr(AttributeKeys.REQUEST_HEADERS).set(headersMap); + Map headersMap = headersToMap(httpRequest); + if (instrumentationConfig.httpHeaders().request()) { + headersMap.forEach(span::setAttribute); + } + // used by blocking handler + channel.attr(AttributeKeys.REQUEST_HEADERS).set(headersMap); - CharSequence contentType = DataCaptureUtils.getContentType(httpRequest); - if (instrumentationConfig.httpBody().request() - && contentType != null - && ContentTypeUtils.shouldCapture(contentType.toString())) { + CharSequence contentType = DataCaptureUtils.getContentType(httpRequest); + if (instrumentationConfig.httpBody().request() + && contentType != null + && ContentTypeUtils.shouldCapture(contentType.toString())) { - CharSequence contentLengthHeader = DataCaptureUtils.getContentLength(httpRequest); - int contentLength = ContentLengthUtils.parseLength(contentLengthHeader); + CharSequence contentLengthHeader = DataCaptureUtils.getContentLength(httpRequest); + int contentLength = ContentLengthUtils.parseLength(contentLengthHeader); - String charsetString = ContentTypeUtils.parseCharset(contentType.toString()); - Charset charset = ContentTypeCharsetUtils.toCharset(charsetString); + String charsetString = ContentTypeUtils.parseCharset(contentType.toString()); + Charset charset = ContentTypeCharsetUtils.toCharset(charsetString); - // set the buffer to capture response body - // the buffer is used byt captureBody method - Attribute bufferAttr = - ctx.channel().attr(AttributeKeys.REQUEST_BODY_BUFFER); - bufferAttr.set(BoundedBuffersFactory.createStream(contentLength, charset)); + // set the buffer to capture response body + // the buffer is used byt captureBody method + Attribute bufferAttr = + ctx.channel().attr(AttributeKeys.REQUEST_BODY_BUFFER); + bufferAttr.set(BoundedBuffersFactory.createStream(contentLength, charset)); - channel.attr(AttributeKeys.CHARSET).set(charset); - } + channel.attr(AttributeKeys.CHARSET).set(charset); } + } - if ((msg instanceof HttpContent || msg instanceof ByteBuf) - && instrumentationConfig.httpBody().request()) { - Charset charset = channel.attr(AttributeKeys.CHARSET).get(); - if (charset == null) { - charset = ContentTypeCharsetUtils.getDefaultCharset(); - } - DataCaptureUtils.captureBody( - span, channel, AttributeKeys.REQUEST_BODY_BUFFER, msg, null, charset); + if ((msg instanceof HttpContent || msg instanceof ByteBuf) + && instrumentationConfig.httpBody().request()) { + Charset charset = channel.attr(AttributeKeys.CHARSET).get(); + if (charset == null) { + charset = ContentTypeCharsetUtils.getDefaultCharset(); } + DataCaptureUtils.captureBody( + span, channel, AttributeKeys.REQUEST_BODY_BUFFER, msg, null, charset); } ctx.fireChannelRead(msg); diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/NettyChannelPipelineInstrumentation.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/NettyChannelPipelineInstrumentation.java index 7e152aaa9..1e55f9a39 100644 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/NettyChannelPipelineInstrumentation.java +++ b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/NettyChannelPipelineInstrumentation.java @@ -36,7 +36,6 @@ import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_1.client.HttpClientRequestTracingHandler; import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_1.client.HttpClientResponseTracingHandler; import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_1.client.HttpClientTracingHandler; -import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_1.client.OtelHttpClientRequestTracingHandler; import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_1.server.HttpServerBlockingRequestHandler; import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_1.server.HttpServerRequestTracingHandler; import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_1.server.HttpServerResponseTracingHandler; @@ -134,13 +133,14 @@ public static void addHandler( HttpClientTracingHandler.class.getName(), new HttpClientTracingHandler()); - // add our custom request handler to start spans with proper context propagation + // add OTEL request handler to start spans pipeline.addAfter( HttpClientTracingHandler.class.getName(), io.opentelemetry.instrumentation.netty.v4_1.internal.client.HttpClientTracingHandler .class .getName(), - new OtelHttpClientRequestTracingHandler(NettyClientSingletons.instrumenter())); + new io.opentelemetry.instrumentation.netty.v4_1.internal.client + .HttpClientRequestTracingHandler(NettyClientSingletons.instrumenter())); } else if (handler instanceof HttpRequestEncoder) { pipeline.addLast( HttpClientRequestTracingHandler.class.getName(), diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/OtelHttpClientRequestTracingHandler.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/OtelHttpClientRequestTracingHandler.java deleted file mode 100644 index 44420b412..000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/OtelHttpClientRequestTracingHandler.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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 io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_1.client; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.context.Context; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel; -import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys; -import io.opentelemetry.instrumentation.netty.v4_1.internal.client.HttpClientRequestTracingHandler; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Custom extension of OpenTelemetry's HttpClientRequestTracingHandler that ensures proper context - * propagation by using Context.current() as the parent context. - */ -public class OtelHttpClientRequestTracingHandler extends HttpClientRequestTracingHandler { - - // Store the server context for each thread - private static final ThreadLocal SERVER_CONTEXT = new ThreadLocal<>(); - - // Store the mapping from thread ID to server span context (for cross-thread scenarios) - private static final ConcurrentHashMap THREAD_TO_SPAN_CONTEXT = - new ConcurrentHashMap<>(); - - // Maximum size for the thread map before triggering cleanup - private static final int MAX_THREAD_MAP_SIZE = 1000; - - // Cleanup flag to avoid excessive synchronized blocks - private static volatile boolean cleanupNeeded = false; - - public OtelHttpClientRequestTracingHandler( - Instrumenter instrumenter) { - super(instrumenter); - } - - /** - * Stores the current context as the server context for this thread. This should be called from - * the server handler. - */ - public static void storeServerContext(Context context) { - SERVER_CONTEXT.set(context); - - // Also store the span context by thread ID for cross-thread lookup - Span span = Span.fromContext(context); - if (span != null && span.getSpanContext().isValid()) { - THREAD_TO_SPAN_CONTEXT.put(Thread.currentThread().getId(), span.getSpanContext()); - - // Check if we need to clean up the map - if (THREAD_TO_SPAN_CONTEXT.size() > MAX_THREAD_MAP_SIZE) { - cleanupNeeded = true; - } - } - } - - /** - * Perform cleanup of the thread map if it has grown too large. This is done in a synchronized - * block to prevent concurrent modification issues. - */ - private static void cleanupThreadMapIfNeeded() { - if (cleanupNeeded) { - synchronized (THREAD_TO_SPAN_CONTEXT) { - if (THREAD_TO_SPAN_CONTEXT.size() > MAX_THREAD_MAP_SIZE) { - THREAD_TO_SPAN_CONTEXT.clear(); - cleanupNeeded = false; - } - } - } - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise prm) { - try { - if (!(msg instanceof HttpRequest)) { - super.write(ctx, msg, prm); - return; - } - - Context parentContext = SERVER_CONTEXT.get(); - - // Fallback -> If no context in thread local, try Context.current() - if (parentContext == null) { - parentContext = Context.current(); - } - - // Store the parent context in the channel attributes - // This is used by the Opentelemetry's HttpClientRequestTracingHandler in propagating correct - // context. - ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT).set(parentContext); - - // Call the parent implementation which will use our stored parent context - super.write(ctx, msg, prm); - - // Clean up after use to prevent memory leaks - SERVER_CONTEXT.remove(); - THREAD_TO_SPAN_CONTEXT.remove(Thread.currentThread().getId()); - cleanupThreadMapIfNeeded(); - - } catch (Exception ignored) { - } - } -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/server/HttpServerRequestTracingHandler.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/server/HttpServerRequestTracingHandler.java index 320e5306d..6fce19a2b 100644 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/server/HttpServerRequestTracingHandler.java +++ b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/server/HttpServerRequestTracingHandler.java @@ -26,12 +26,9 @@ import io.netty.util.Attribute; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; import io.opentelemetry.instrumentation.netty.v4_1.internal.ServerContext; import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_1.AttributeKeys; import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_1.DataCaptureUtils; -import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_1.client.OtelHttpClientRequestTracingHandler; import java.nio.charset.Charset; import java.util.Deque; import java.util.HashMap; @@ -60,57 +57,49 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { ctx.fireChannelRead(msg); return; } + Span span = Span.fromContext(serverContexts.element().context()); - Context context = serverContexts.element().context(); + if (msg instanceof HttpRequest) { + HttpRequest httpRequest = (HttpRequest) msg; - // Store the server context in our ThreadLocal for later use by client handlers - // This is CRITICAL for proper context propagation to client spans - OtelHttpClientRequestTracingHandler.storeServerContext(context); - - try (Scope ignored = context.makeCurrent()) { - Span span = Span.fromContext(context); - - if (msg instanceof HttpRequest) { - HttpRequest httpRequest = (HttpRequest) msg; - - Map headersMap = headersToMap(httpRequest); - if (instrumentationConfig.httpHeaders().request()) { - headersMap.forEach(span::setAttribute); - } - // used by blocking handler - channel.attr(AttributeKeys.REQUEST_HEADERS).set(headersMap); + Map headersMap = headersToMap(httpRequest); + if (instrumentationConfig.httpHeaders().request()) { + headersMap.forEach(span::setAttribute); + } + // used by blocking handler + channel.attr(AttributeKeys.REQUEST_HEADERS).set(headersMap); - CharSequence contentType = DataCaptureUtils.getContentType(httpRequest); - if (instrumentationConfig.httpBody().request() - && contentType != null - && ContentTypeUtils.shouldCapture(contentType.toString())) { + CharSequence contentType = DataCaptureUtils.getContentType(httpRequest); + if (instrumentationConfig.httpBody().request() + && contentType != null + && ContentTypeUtils.shouldCapture(contentType.toString())) { - CharSequence contentLengthHeader = DataCaptureUtils.getContentLength(httpRequest); - int contentLength = ContentLengthUtils.parseLength(contentLengthHeader); + CharSequence contentLengthHeader = DataCaptureUtils.getContentLength(httpRequest); + int contentLength = ContentLengthUtils.parseLength(contentLengthHeader); - String charsetString = ContentTypeUtils.parseCharset(contentType.toString()); - Charset charset = ContentTypeCharsetUtils.toCharset(charsetString); + String charsetString = ContentTypeUtils.parseCharset(contentType.toString()); + Charset charset = ContentTypeCharsetUtils.toCharset(charsetString); - // set the buffer to capture response body - // the buffer is used byt captureBody method - Attribute bufferAttr = - ctx.channel().attr(AttributeKeys.REQUEST_BODY_BUFFER); - bufferAttr.set(BoundedBuffersFactory.createStream(contentLength, charset)); + // set the buffer to capture response body + // the buffer is used byt captureBody method + Attribute bufferAttr = + ctx.channel().attr(AttributeKeys.REQUEST_BODY_BUFFER); + bufferAttr.set(BoundedBuffersFactory.createStream(contentLength, charset)); - channel.attr(AttributeKeys.PROVIDED_CHARSET).set(charset); - } + channel.attr(AttributeKeys.PROVIDED_CHARSET).set(charset); } + } - if ((msg instanceof HttpContent || msg instanceof ByteBuf) - && instrumentationConfig.httpBody().request()) { - Charset charset = channel.attr(AttributeKeys.PROVIDED_CHARSET).get(); - if (charset == null) { - charset = ContentTypeCharsetUtils.getDefaultCharset(); - } - DataCaptureUtils.captureBody( - span, channel, AttributeKeys.REQUEST_BODY_BUFFER, msg, null, charset); + if ((msg instanceof HttpContent || msg instanceof ByteBuf) + && instrumentationConfig.httpBody().request()) { + Charset charset = channel.attr(AttributeKeys.PROVIDED_CHARSET).get(); + if (charset == null) { + charset = ContentTypeCharsetUtils.getDefaultCharset(); } + DataCaptureUtils.captureBody( + span, channel, AttributeKeys.REQUEST_BODY_BUFFER, msg, null, charset); } + ctx.fireChannelRead(msg); } From 5bcc65550423dc559dda6af9a59ec55db3b2bcea Mon Sep 17 00:00:00 2001 From: Yashwant Date: Tue, 2 Sep 2025 18:44:42 +0530 Subject: [PATCH 2/4] enable executors module --- .../agent/otel/extensions/HypertracePropertySource.java | 1 + 1 file changed, 1 insertion(+) diff --git a/otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/HypertracePropertySource.java b/otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/HypertracePropertySource.java index c4a1a6251..5e6fdc464 100644 --- a/otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/HypertracePropertySource.java +++ b/otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/HypertracePropertySource.java @@ -74,6 +74,7 @@ public Map getProperties() { configProperties.put( "otel.instrumentation.opentelemetry-instrumentation-annotations.enabled", "true"); configProperties.put("otel.instrumentation.opentelemetry-api.enabled", "true"); + configProperties.put("otel.instrumentation.executors.enabled", "true"); return Collections.unmodifiableMap(configProperties); } From 1e12563d9cef6c508cea2508b3be7151a164e459 Mon Sep 17 00:00:00 2001 From: Yashwant Date: Tue, 2 Sep 2025 19:12:17 +0530 Subject: [PATCH 3/4] upload jar as artifact --- .github/workflows/build.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 288928172..d04057f1a 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -45,6 +45,14 @@ jobs: env: JVM_OPTS: -Xmx1g --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED TERM: dumb + + - name: Upload jar as pipeline artifact + uses: actions/upload-artifact@v4 + with: + name: javaagent + path: javaagent/build/libs/*-all.jar + if-no-files-found: error + retention-days: 5 muzzle: runs-on: ubuntu-latest steps: From 9c1a3beac7a3298bb558f1b6a4d137cd888de7f1 Mon Sep 17 00:00:00 2001 From: Yashwant Date: Wed, 3 Sep 2025 02:09:44 +0530 Subject: [PATCH 4/4] null the context attrs after usage --- .../v4_1/client/HttpClientResponseTracingHandler.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/HttpClientResponseTracingHandler.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/HttpClientResponseTracingHandler.java index f1b418e1e..f43458600 100644 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/HttpClientResponseTracingHandler.java +++ b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/HttpClientResponseTracingHandler.java @@ -120,6 +120,16 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { span.setStatus(code >= 100 && code < 400 ? StatusCode.UNSET : StatusCode.ERROR); } if (msg instanceof LastHttpContent) { + // When we end the span, we should set the client context and client parent attr to null. + // so that for the next request a new context is made and stored in channel. + ctx.channel() + .attr(io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys.CLIENT_CONTEXT) + .set(null); + ctx.channel() + .attr( + io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys + .CLIENT_PARENT_CONTEXT) + .set(null); span.end(); } }