Skip to content

Commit 0b80f3d

Browse files
authored
Add a netty-4.1.x plugin to trace http (#625)
1 parent c94b409 commit 0b80f3d

File tree

48 files changed

+2386
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+2386
-2
lines changed

.github/workflows/plugins-test.1.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ jobs:
8080
- mssql-jdbc-scenario
8181
- mybatis-3.x-scenario
8282
- resteasy-4.x-scenario
83+
- netty-http-4.1.x-scenario
8384
steps:
8485
- uses: actions/checkout@v2
8586
with:

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Release Notes.
1717
* Fix config length limitation.
1818
* Support collecting ZGC memory pool metrics. Require OAP 9.7.0 to support these new metrics.
1919
* Upgrade netty-codec-http2 to 4.1.100.Final
20+
* Add a netty-http 4.1.x plugin to trace HTTP requests.
2021

2122

2223
#### Documentation

apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,4 +242,6 @@ public class ComponentsDefine {
242242
public static final OfficialComponent AEROSPIKE = new OfficialComponent(149, "Aerospike");
243243

244244
public static final OfficialComponent NACOS = new OfficialComponent(150, "Nacos");
245+
246+
public static final OfficialComponent NETTY_HTTP = new OfficialComponent(151, "Netty-http");
245247
}

apm-sniffer/config/agent.config

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,3 +310,9 @@ plugin.redisson.redis_parameter_max_length=${SW_PLUGIN_REDISSON_REDIS_PARAMETER_
310310
plugin.redisson.operation_mapping_write=${SW_PLUGIN_REDISSON_OPERATION_MAPPING_WRITE:getset,set,setbit,setex,setnx,setrange,strlen,mset,msetnx,psetex,incr,incrby,incrbyfloat,decr,decrby,append,hmset,hset,hsetnx,hincrby,hincrbyfloat,hdel,rpoplpush,rpush,rpushx,lpush,lpushx,lrem,ltrim,lset,brpoplpush,linsert,sadd,sdiff,sdiffstore,sinterstore,sismember,srem,sunion,sunionstore,sinter,zadd,zincrby,zinterstore,zrange,zrangebylex,zrangebyscore,zrank,zrem,zremrangebylex,zremrangebyrank,zremrangebyscore,zrevrange,zrevrangebyscore,zrevrank,zunionstore,xadd,xdel,del,xtrim}
311311
# Specify which command should be converted to read operation
312312
plugin.redisson.operation_mapping_read=${SW_PLUGIN_REDISSON_OPERATION_MAPPING_READ:getrange,getbit,mget,hvals,hkeys,hlen,hexists,hget,hgetall,hmget,blpop,brpop,lindex,llen,lpop,lrange,rpop,scard,srandmember,spop,sscan,smove,zlexcount,zscore,zscan,zcard,zcount,xget,get,xread,xlen,xrange,xrevrange}
313+
# This config item controls that whether the Netty-http plugin should collect the http body of the request.
314+
plugin.nettyhttp.collect_request_body=${SW_PLUGIN_NETTYHTTP_COLLECT_REQUEST_BODY:false}
315+
# When `HTTP_COLLECT_REQUEST_BODY` is enabled, how many characters to keep and send to the OAP backend, use negative values to keep and send the complete body.
316+
plugin.nettyhttp.filter_length_limit=${SW_PLUGIN_NETTYHTTP_FILTER_LENGTH_LIMIT:1024}
317+
# When `HTTP_COLLECT_REQUEST_BODY` is enabled and content-type start with HTTP_SUPPORTED_CONTENT_TYPES_PREFIX, collect the body of the request , multiple paths should be separated by `,`
318+
plugin.nettyhttp.supported_content_types_prefix=${SW_PLUGIN_NETTYHTTP_SUPPORTED_CONTENT_TYPES_PREFIX:application/json,text/}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Licensed to the Apache Software Foundation (ASF) under one or more
4+
~ contributor license agreements. See the NOTICE file distributed with
5+
~ this work for additional information regarding copyright ownership.
6+
~ The ASF licenses this file to You under the Apache License, Version 2.0
7+
~ (the "License"); you may not use this file except in compliance with
8+
~ the License. You may obtain a copy of the License at
9+
~
10+
~ http://www.apache.org/licenses/LICENSE-2.0
11+
~
12+
~ Unless required by applicable law or agreed to in writing, software
13+
~ distributed under the License is distributed on an "AS IS" BASIS,
14+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
~ See the License for the specific language governing permissions and
16+
~ limitations under the License.
17+
~
18+
-->
19+
20+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
21+
<parent>
22+
<groupId>org.apache.skywalking</groupId>
23+
<artifactId>optional-plugins</artifactId>
24+
<version>9.1.0-SNAPSHOT</version>
25+
</parent>
26+
<modelVersion>4.0.0</modelVersion>
27+
28+
<artifactId>apm-netty-http-4.1.x-plugin</artifactId>
29+
<name>netty-http-4.1.x-plugin</name>
30+
31+
<properties>
32+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
33+
<netty.version>4.1.51.Final</netty.version>
34+
</properties>
35+
36+
<dependencies>
37+
<dependency>
38+
<groupId>io.netty</groupId>
39+
<artifactId>netty-all</artifactId>
40+
<version>${netty.version}</version>
41+
<scope>provided</scope>
42+
</dependency>
43+
</dependencies>
44+
45+
46+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package org.apache.skywalking.apm.plugin.netty.http;
20+
21+
import io.netty.channel.ChannelHandler;
22+
import io.netty.channel.ChannelHandlerContext;
23+
import io.netty.channel.ChannelPipeline;
24+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
25+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
26+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
27+
import org.apache.skywalking.apm.plugin.netty.http.common.AttributeKeys;
28+
import org.apache.skywalking.apm.plugin.netty.http.handler.NettyHttpRequestDecoderTracingHandler;
29+
30+
import java.lang.reflect.Method;
31+
import java.util.Map;
32+
33+
public class AddHttpRequestDecoderInterceptor implements InstanceMethodsAroundInterceptor {
34+
35+
@Override
36+
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
37+
38+
}
39+
40+
@Override
41+
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
42+
ChannelHandlerContext ctx = (ChannelHandlerContext) allArguments[0];
43+
ChannelPipeline pipeline = ctx.channel().pipeline();
44+
45+
if (pipeline.context(ctx.name()) == null) {
46+
return ret;
47+
}
48+
49+
String name = NettyHttpRequestDecoderTracingHandler.class.getName();
50+
if (null != pipeline.context(name)) {
51+
pipeline.remove(name);
52+
}
53+
pipeline.addAfter(ctx.name(), name, NettyHttpRequestDecoderTracingHandler.getInstance());
54+
55+
Map<ChannelHandler, ChannelHandler> map = AttributeKeys.getOrCreateHandlerMap(ctx.channel());
56+
map.put((ChannelHandler) objInst, NettyHttpRequestDecoderTracingHandler.getInstance());
57+
return ret;
58+
}
59+
60+
@Override
61+
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
62+
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package org.apache.skywalking.apm.plugin.netty.http;
20+
21+
import io.netty.channel.ChannelHandler;
22+
import io.netty.channel.ChannelHandlerContext;
23+
import io.netty.channel.ChannelPipeline;
24+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
25+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
26+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
27+
import org.apache.skywalking.apm.plugin.netty.http.common.AttributeKeys;
28+
import org.apache.skywalking.apm.plugin.netty.http.handler.NettyHttpRequestEncoderTracingHandler;
29+
30+
import java.lang.reflect.Method;
31+
import java.util.Map;
32+
33+
public class AddHttpRequestEncoderInterceptor implements InstanceMethodsAroundInterceptor {
34+
35+
@Override
36+
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
37+
38+
}
39+
40+
@Override
41+
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
42+
ChannelHandlerContext ctx = (ChannelHandlerContext) allArguments[0];
43+
ChannelPipeline pipeline = ctx.channel().pipeline();
44+
45+
if (pipeline.context(ctx.name()) == null) {
46+
return ret;
47+
}
48+
49+
String name = NettyHttpRequestEncoderTracingHandler.class.getName();
50+
if (null != pipeline.context(name)) {
51+
pipeline.remove(name);
52+
}
53+
pipeline.addAfter(ctx.name(), name, NettyHttpRequestEncoderTracingHandler.getInstance());
54+
55+
Map<ChannelHandler, ChannelHandler> map = AttributeKeys.getOrCreateHandlerMap(ctx.channel());
56+
map.put((ChannelHandler) objInst, NettyHttpRequestEncoderTracingHandler.getInstance());
57+
return ret;
58+
}
59+
60+
@Override
61+
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
62+
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package org.apache.skywalking.apm.plugin.netty.http;
20+
21+
import io.netty.channel.ChannelHandler;
22+
import io.netty.channel.ChannelHandlerContext;
23+
import io.netty.channel.ChannelPipeline;
24+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
25+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
26+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
27+
import org.apache.skywalking.apm.plugin.netty.http.common.AttributeKeys;
28+
import org.apache.skywalking.apm.plugin.netty.http.handler.NettyHttpResponseDecoderTracingHandler;
29+
30+
import java.lang.reflect.Method;
31+
import java.util.Map;
32+
33+
public class AddHttpResponseDecoderInterceptor implements InstanceMethodsAroundInterceptor {
34+
35+
@Override
36+
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
37+
38+
}
39+
40+
@Override
41+
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
42+
ChannelHandlerContext ctx = (ChannelHandlerContext) allArguments[0];
43+
ChannelPipeline pipeline = ctx.channel().pipeline();
44+
45+
if (pipeline.context(ctx.name()) == null) {
46+
return ret;
47+
}
48+
49+
String name = NettyHttpResponseDecoderTracingHandler.class.getName();
50+
if (null != pipeline.context(name)) {
51+
pipeline.remove(name);
52+
}
53+
pipeline.addAfter(ctx.name(), name, NettyHttpResponseDecoderTracingHandler.getInstance());
54+
55+
Map<ChannelHandler, ChannelHandler> map = AttributeKeys.getOrCreateHandlerMap(ctx.channel());
56+
map.put((ChannelHandler) objInst, NettyHttpResponseDecoderTracingHandler.getInstance());
57+
return ret;
58+
}
59+
60+
@Override
61+
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
62+
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package org.apache.skywalking.apm.plugin.netty.http;
20+
21+
import io.netty.channel.ChannelHandler;
22+
import io.netty.channel.ChannelHandlerContext;
23+
import io.netty.channel.ChannelPipeline;
24+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
25+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
26+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
27+
import org.apache.skywalking.apm.plugin.netty.http.common.AttributeKeys;
28+
import org.apache.skywalking.apm.plugin.netty.http.handler.NettyHttpResponseEncoderTracingHandler;
29+
30+
import java.lang.reflect.Method;
31+
import java.util.Map;
32+
33+
public class AddHttpResponseEncoderInterceptor implements InstanceMethodsAroundInterceptor {
34+
35+
@Override
36+
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
37+
38+
}
39+
40+
@Override
41+
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
42+
ChannelHandlerContext ctx = (ChannelHandlerContext) allArguments[0];
43+
ChannelPipeline pipeline = ctx.channel().pipeline();
44+
45+
if (pipeline.context(ctx.name()) == null) {
46+
return ret;
47+
}
48+
49+
String name = NettyHttpResponseEncoderTracingHandler.class.getName();
50+
if (null != pipeline.context(name)) {
51+
pipeline.remove(name);
52+
}
53+
pipeline.addAfter(ctx.name(), name, NettyHttpResponseEncoderTracingHandler.getInstance());
54+
55+
Map<ChannelHandler, ChannelHandler> map = AttributeKeys.getOrCreateHandlerMap(ctx.channel());
56+
map.put((ChannelHandler) objInst, NettyHttpResponseEncoderTracingHandler.getInstance());
57+
return ret;
58+
}
59+
60+
@Override
61+
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
62+
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package org.apache.skywalking.apm.plugin.netty.http;
20+
21+
import io.netty.channel.ChannelHandlerContext;
22+
import org.apache.skywalking.apm.agent.core.context.ContextManager;
23+
import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
24+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
25+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
26+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
27+
import org.apache.skywalking.apm.plugin.netty.http.common.AttributeKeys;
28+
29+
import java.lang.reflect.Method;
30+
31+
public class ChannelHandlerContextInterceptor implements InstanceMethodsAroundInterceptor {
32+
33+
@Override
34+
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
35+
if (ContextManager.isActive()) {
36+
ContextSnapshot contextSnapshot = ContextManager.capture();
37+
if (contextSnapshot != null) {
38+
((ChannelHandlerContext) objInst).channel().attr(AttributeKeys.CONTEXT_SNAPSHOT_ATTRIBUTE_KEY).set(contextSnapshot);
39+
}
40+
}
41+
}
42+
43+
@Override
44+
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
45+
return ret;
46+
}
47+
48+
@Override
49+
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
50+
51+
}
52+
}

0 commit comments

Comments
 (0)