Skip to content

Commit d823ffe

Browse files
authored
Netty: don't expose tracing handler in handlers map (#10410)
1 parent 8673574 commit d823ffe

File tree

3 files changed

+85
-8
lines changed

3 files changed

+85
-8
lines changed

instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4/common/AbstractNettyChannelPipelineInstrumentation.java

+23
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import io.opentelemetry.instrumentation.api.util.VirtualField;
1919
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2020
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
21+
import java.util.Iterator;
22+
import java.util.Map;
2123
import net.bytebuddy.asm.Advice;
2224
import net.bytebuddy.description.type.TypeDescription;
2325
import net.bytebuddy.matcher.ElementMatcher;
@@ -59,6 +61,9 @@ public void transform(TypeTransformer transformer) {
5961
.and(takesArgument(1, String.class))
6062
.and(takesArguments(4)),
6163
AbstractNettyChannelPipelineInstrumentation.class.getName() + "$AddAfterAdvice");
64+
transformer.applyAdviceToMethod(
65+
isMethod().and(named("toMap")).and(takesArguments(0)).and(returns(Map.class)),
66+
AbstractNettyChannelPipelineInstrumentation.class.getName() + "$ToMapAdvice");
6267
}
6368

6469
@SuppressWarnings("unused")
@@ -194,4 +199,22 @@ public static void addAfterHandler(
194199
}
195200
}
196201
}
202+
203+
@SuppressWarnings("unused")
204+
public static class ToMapAdvice {
205+
206+
@Advice.OnMethodExit(suppress = Throwable.class)
207+
public static void wrapIterator(@Advice.Return Map<String, ChannelHandler> map) {
208+
VirtualField<ChannelHandler, ChannelHandler> virtualField =
209+
VirtualField.find(ChannelHandler.class, ChannelHandler.class);
210+
for (Iterator<ChannelHandler> iterator = map.values().iterator(); iterator.hasNext(); ) {
211+
ChannelHandler handler = iterator.next();
212+
String handlerClassName = handler.getClass().getName();
213+
if (handlerClassName.startsWith("io.opentelemetry.javaagent.instrumentation.netty.")
214+
|| handlerClassName.startsWith("io.opentelemetry.instrumentation.netty.")) {
215+
iterator.remove();
216+
}
217+
}
218+
}
219+
}
197220
}

instrumentation/netty/netty-4.0/javaagent/src/test/groovy/ChannelPipelineTest.groovy

+31-4
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
7070
replaceMethod(channelPipeline, "test", noopHandler, "http", httpHandler)
7171

7272
then: "noop handler was removed; http and instrumentation handlers were added"
73-
channelPipeline.size() == 2
73+
channelPipeline.size() == 1
7474
channelPipeline.first() == httpHandler
7575
channelPipeline.last().getClass().getSimpleName() == "HttpClientTracingHandler"
7676

@@ -103,7 +103,7 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
103103
channelPipeline.addLast("http", httpHandler)
104104

105105
then: "add http and instrumentation handlers"
106-
channelPipeline.size() == 2
106+
channelPipeline.size() == 1
107107
channelPipeline.first() == httpHandler
108108
channelPipeline.last().getClass().getSimpleName() == "HttpClientTracingHandler"
109109

@@ -112,15 +112,15 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
112112
channelPipeline.addAfter("http", "noop", noopHandler)
113113

114114
then: "instrumentation handler is between with http and noop"
115-
channelPipeline.size() == 3
115+
channelPipeline.size() == 2
116116
channelPipeline.first() == httpHandler
117117
channelPipeline.last() == noopHandler
118118

119119
when:
120120
channelPipeline.removeLast()
121121

122122
then: "http and instrumentation handlers will be remained"
123-
channelPipeline.size() == 2
123+
channelPipeline.size() == 1
124124
channelPipeline.first() == httpHandler
125125
channelPipeline.last().getClass().getSimpleName() == "HttpClientTracingHandler"
126126

@@ -133,6 +133,33 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
133133
removed == httpHandler
134134
}
135135

136+
// regression test for https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/10377
137+
def "our handler not in handlers map"() {
138+
setup:
139+
def channel = new EmbeddedChannel(new NoopChannelHandler())
140+
def channelPipeline = new DefaultChannelPipeline(channel)
141+
def handler = new HttpClientCodec()
142+
143+
when:
144+
// no handlers
145+
channelPipeline.first() == null
146+
147+
then:
148+
// add handler
149+
channelPipeline.addLast("http", handler)
150+
channelPipeline.first() == handler
151+
// our handler was also added
152+
channelPipeline.last().getClass().simpleName == "HttpClientTracingHandler"
153+
// our handler not counted
154+
channelPipeline.size() == 1
155+
// our handler is not in handlers map
156+
channelPipeline.toMap().size() == 1
157+
// our handler is not in handlers iterator
158+
def list = []
159+
channelPipeline.iterator().forEachRemaining {list.add(it) }
160+
list.size() == 1
161+
}
162+
136163
private static class NoopChannelHandler extends ChannelHandlerAdapter {
137164
}
138165
}

instrumentation/netty/netty-4.1/javaagent/src/test/groovy/ChannelPipelineTest.groovy

+31-4
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
6868
replaceMethod(channelPipeline, "test", noopHandler, "http", httpHandler)
6969

7070
then: "noop handler was removed; http and instrumentation handlers were added"
71-
channelPipeline.size() == 2
71+
channelPipeline.size() == 1
7272
channelPipeline.first() == httpHandler
7373
channelPipeline.last().getClass().simpleName == "HttpClientTracingHandler"
7474

@@ -101,7 +101,7 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
101101
channelPipeline.addLast("http", httpHandler)
102102

103103
then: "add http and instrumentation handlers"
104-
channelPipeline.size() == 2
104+
channelPipeline.size() == 1
105105
channelPipeline.first() == httpHandler
106106
channelPipeline.last().getClass().simpleName == "HttpClientTracingHandler"
107107

@@ -110,15 +110,15 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
110110
channelPipeline.addAfter("http", "noop", noopHandler)
111111

112112
then: "instrumentation handler is between with http and noop"
113-
channelPipeline.size() == 3
113+
channelPipeline.size() == 2
114114
channelPipeline.first() == httpHandler
115115
channelPipeline.last() == noopHandler
116116

117117
when:
118118
channelPipeline.removeLast()
119119

120120
then: "http and instrumentation handlers will be remained"
121-
channelPipeline.size() == 2
121+
channelPipeline.size() == 1
122122
channelPipeline.first() == httpHandler
123123
channelPipeline.last().getClass().simpleName == "HttpClientTracingHandler"
124124

@@ -131,6 +131,33 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
131131
removed == httpHandler
132132
}
133133

134+
// regression test for https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/10377
135+
def "our handler not in handlers map"() {
136+
setup:
137+
def channel = new EmbeddedChannel()
138+
def channelPipeline = new DefaultChannelPipeline(channel)
139+
def handler = new HttpClientCodec()
140+
141+
when:
142+
// no handlers
143+
channelPipeline.first() == null
144+
145+
then:
146+
// add handler
147+
channelPipeline.addLast("http", handler)
148+
channelPipeline.first() == handler
149+
// our handler was also added
150+
channelPipeline.last().getClass().simpleName == "HttpClientTracingHandler"
151+
// our handler not counted
152+
channelPipeline.size() == 1
153+
// our handler is not in handlers map
154+
channelPipeline.toMap().size() == 1
155+
// our handler is not in handlers iterator
156+
def list = []
157+
channelPipeline.iterator().forEachRemaining {list.add(it) }
158+
list.size() == 1
159+
}
160+
134161
private static class NoopChannelHandler extends ChannelHandlerAdapter {
135162
}
136163
}

0 commit comments

Comments
 (0)