diff --git a/Jenkinsfile-Agent-Test b/Jenkinsfile-Agent-Test
index f404cd5e6..563556c03 100755
--- a/Jenkinsfile-Agent-Test
+++ b/Jenkinsfile-Agent-Test
@@ -56,7 +56,7 @@ pipeline {
sh './mvnw -f test/plugin/pom.xml clean package -DskipTests -Dbuild_id=wl1_${BUILD_ID} docker:build'
}
}
- stage('Test Cases Report (135)') {
+ stage('Test Cases Report (139)') {
steps {
echo "reserve."
}
@@ -88,6 +88,12 @@ pipeline {
sh 'bash test/plugin/run.sh --build_id=wl1_${BUILD_ID} spring-async-scenario'
}
}
+
+ stage('netty-socketio 1.x (4)') {
+ steps {
+ sh 'bash test/plugin/run.sh --build_id=wl1_${BUILD_ID} netty-socketio-scenario'
+ }
+ }
}
}
stage('Group2') {
diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
index 45c494ad0..6510c4d2c 100755
--- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
+++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
@@ -141,4 +141,6 @@ public class ComponentsDefine {
public static final OfficialComponent PULSAR_CONSUMER = new OfficialComponent(74, "pulsar-consumer");
public static final OfficialComponent EHCACHE = new OfficialComponent(75, "Ehcache");
+
+ public static final OfficialComponent SOCKET_IO = new OfficialComponent(76, "SocketIO");
}
diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml
new file mode 100644
index 000000000..8fb777345
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+ apm-sdk-plugin
+ org.apache.skywalking
+ 6.5.0-SNAPSHOT
+
+ 4.0.0
+
+ apm-netty-socketio-plugin
+ netty-socketio-plugin
+
+
+ UTF-8
+ 1.7.12
+
+
+
+
+ com.corundumstudio.socketio
+ netty-socketio
+ ${netty-socketio.version}
+ provided
+
+
+
+
+
\ No newline at end of file
diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOClientInfo.java b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOClientInfo.java
new file mode 100644
index 000000000..392c38d4f
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOClientInfo.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.skywalking.apm.plugin.netty.socketio;
+
+import com.corundumstudio.socketio.handler.ClientHead;
+import com.corundumstudio.socketio.namespace.Namespace;
+
+/**
+ * {@link com.corundumstudio.socketio.transport.NamespaceClient} all data
+ *
+ * @author MrPro
+ */
+public class NettySocketIOClientInfo {
+
+ private final ClientHead baseClient;
+ private final Namespace namespace;
+ private final String clientAddress;
+
+ public NettySocketIOClientInfo(ClientHead baseClient, Namespace namespace, String clientAddress) {
+ this.baseClient = baseClient;
+ this.namespace = namespace;
+ this.clientAddress = clientAddress;
+ }
+
+ public Namespace getNamespace() {
+ return namespace;
+ }
+
+ public ClientHead getBaseClient() {
+ return baseClient;
+ }
+
+ public String getClientAddress() {
+ return clientAddress;
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOConnectionInterceptor.java b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOConnectionInterceptor.java
new file mode 100644
index 000000000..e14822385
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOConnectionInterceptor.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.skywalking.apm.plugin.netty.socketio;
+
+import com.corundumstudio.socketio.SocketIOClient;
+import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+
+import java.lang.reflect.Method;
+import java.net.InetSocketAddress;
+
+/**
+ * @author MrPro
+ */
+public class NettySocketIOConnectionInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+ SocketIOClient client = (SocketIOClient) allArguments[0];
+
+ AbstractSpan span = ContextManager.createEntrySpan("SocketIO/" + method.getName(), new ContextCarrier());
+ span.setComponent(ComponentsDefine.SOCKET_IO);
+ SpanLayer.asHttp(span);
+
+ // set client addr
+ InetSocketAddress remoteAddress = (InetSocketAddress) client.getRemoteAddress();
+ String clientAddress = remoteAddress.getAddress().getHostAddress() + ":" + remoteAddress.getPort();
+ span.tag("from", clientAddress);
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes, Object ret) throws Throwable {
+ ContextManager.stopSpan();
+ return ret;
+ }
+
+ @Override
+ public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes, Throwable t) {
+ if (ContextManager.isActive()) {
+ ContextManager.activeSpan().errorOccurred().log(t);
+ }
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOConstructorInterceptor.java
new file mode 100644
index 000000000..7fe4929f1
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOConstructorInterceptor.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.skywalking.apm.plugin.netty.socketio;
+
+import com.corundumstudio.socketio.handler.ClientHead;
+import com.corundumstudio.socketio.namespace.Namespace;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+
+import java.net.InetSocketAddress;
+
+/**
+ * @author MrPro
+ */
+public class NettySocketIOConstructorInterceptor implements InstanceConstructorInterceptor {
+ @Override
+ public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
+ ClientHead clientHead = (ClientHead) allArguments[0];
+ Namespace namespace = (Namespace) allArguments[1];
+
+ // build client address
+ InetSocketAddress remoteAddress = (InetSocketAddress) clientHead.getRemoteAddress();
+ String clientAddress = remoteAddress.getAddress().getHostAddress() + ":" + remoteAddress.getPort();
+
+ objInst.setSkyWalkingDynamicField(new NettySocketIOClientInfo(clientHead, namespace, clientAddress));
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOOnEventInterceptor.java b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOOnEventInterceptor.java
new file mode 100644
index 000000000..5b7d11136
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOOnEventInterceptor.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.skywalking.apm.plugin.netty.socketio;
+
+import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author MrPro
+ */
+public class NettySocketIOOnEventInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+ String eventName = (String) allArguments[1];
+
+ // no place to get context carrier
+ ContextCarrier contextCarrier = new ContextCarrier();
+ AbstractSpan span = ContextManager.createEntrySpan("SocketIO/" + eventName + "/receive", contextCarrier);
+ span.setComponent(ComponentsDefine.SOCKET_IO);
+ SpanLayer.asHttp(span);
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes, Object ret) throws Throwable {
+ ContextManager.stopSpan();
+ return ret;
+ }
+
+ @Override
+ public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes, Throwable t) {
+ if (ContextManager.isActive()) {
+ ContextManager.activeSpan().errorOccurred().log(t);
+ }
+ }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIORoomInterceptor.java b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIORoomInterceptor.java
new file mode 100644
index 000000000..5a1924de7
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIORoomInterceptor.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.skywalking.apm.plugin.netty.socketio;
+
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author MrPro
+ */
+public class NettySocketIORoomInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+ String roomName = (String) allArguments[0];
+ AbstractSpan span = ContextManager.createLocalSpan("SocketIO/" + roomName + "/" + method.getName());
+ span.setComponent(ComponentsDefine.SOCKET_IO);
+ SpanLayer.asHttp(span);
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes, Object ret) throws Throwable {
+ ContextManager.stopSpan();
+ return ret;
+ }
+
+ @Override
+ public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes, Throwable t) {
+ if (ContextManager.isActive()) {
+ ContextManager.activeSpan().errorOccurred().log(t);
+ }
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/define/NettySocketIOPluginClientInstrumentation.java b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/define/NettySocketIOPluginClientInstrumentation.java
new file mode 100644
index 000000000..318476241
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/define/NettySocketIOPluginClientInstrumentation.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.skywalking.apm.plugin.netty.socketio.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.*;
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * enhance operate client
+ *
+ * @author MrPro
+ */
+public class NettySocketIOPluginClientInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return byName("com.corundumstudio.socketio.transport.NamespaceClient");
+ }
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[] {
+ new ConstructorInterceptPoint() {
+ @Override
+ public ElementMatcher getConstructorMatcher() {
+ return takesArguments(2);
+ }
+
+ @Override
+ public String getConstructorInterceptor() {
+ return "org.apache.skywalking.apm.plugin.netty.socketio.NettySocketIOConstructorInterceptor";
+ }
+ }
+ };
+ }
+
+ @Override
+ public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[]{
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return named("joinRoom").or(named("leaveRoom"));
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return "org.apache.skywalking.apm.plugin.netty.socketio.NettySocketIORoomInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+
+ }
+ };
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/define/NettySocketIOPluginNameSpaceInstrumentation.java b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/define/NettySocketIOPluginNameSpaceInstrumentation.java
new file mode 100644
index 000000000..0294ed0b4
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/socketio/define/NettySocketIOPluginNameSpaceInstrumentation.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.skywalking.apm.plugin.netty.socketio.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * enhance socketio get event
+ *
+ * @author MrPro
+ */
+public class NettySocketIOPluginNameSpaceInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return byName("com.corundumstudio.socketio.namespace.Namespace");
+ }
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override
+ public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[] {
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return named("onEvent");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return "org.apache.skywalking.apm.plugin.netty.socketio.NettySocketIOOnEventInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return named("onConnect");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return "org.apache.skywalking.apm.plugin.netty.socketio.NettySocketIOConnectionInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return named("onDisconnect");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return "org.apache.skywalking.apm.plugin.netty.socketio.NettySocketIOConnectionInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 000000000..5416d7468
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/main/resources/skywalking-plugin.def
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+netty-socketio=org.apache.skywalking.apm.plugin.netty.socketio.define.NettySocketIOPluginClientInstrumentation
+netty-socketio=org.apache.skywalking.apm.plugin.netty.socketio.define.NettySocketIOPluginNameSpaceInstrumentation
+netty-socketio=org.apache.skywalking.apm.plugin.netty.socketio.define.NettySocketIOPluginConnectionInstrumentation
diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/test/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOTest.java b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/test/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOTest.java
new file mode 100644
index 000000000..81d955b30
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/src/test/java/org/apache/skywalking/apm/plugin/netty/socketio/NettySocketIOTest.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.skywalking.apm.plugin.netty.socketio;
+
+import com.corundumstudio.socketio.SocketIOClient;
+import com.corundumstudio.socketio.handler.ClientHead;
+import com.corundumstudio.socketio.namespace.Namespace;
+import com.corundumstudio.socketio.protocol.Packet;
+import com.corundumstudio.socketio.transport.NamespaceClient;
+import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
+import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Method;
+import java.net.InetSocketAddress;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+/**
+ * @author MrPro
+ */
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class NettySocketIOTest {
+
+ @SegmentStoragePoint
+ private SegmentStorage segmentStorage;
+
+ @Rule
+ public AgentServiceRule serviceRule = new AgentServiceRule();
+
+ private NettySocketIOConnectionInterceptor connectionInterceptor;
+ private NettySocketIOOnEventInterceptor onEventInterceptor;
+ private NettySocketIORoomInterceptor roomInterceptor;
+ private NettySocketIOConstructorInterceptor constructorInterceptor;
+
+ @Mock
+ private SocketIOClient socketIOClient;
+ @Mock
+ private Packet sendPacket;
+ @Mock
+ private ClientHead clientHead;
+ @Mock
+ private Namespace namespace;
+
+ private Method connectOnConnectMethod;
+ private Method connectOnDisConnectMethod;
+ private Method roomLeaveMethod;
+ private Method roomJoinMethod;
+
+ private NettySocketIOClientInfo socketIOClientInfo = new NettySocketIOClientInfo(null, null, "127.0.0.1:0");
+
+ private EnhancedInstance enhancedInstance = new EnhancedInstance() {
+ @Override
+ public Object getSkyWalkingDynamicField() {
+ return socketIOClientInfo;
+ }
+
+ @Override
+ public void setSkyWalkingDynamicField(Object value) {
+
+ }
+ };
+
+ @Before
+ public void setUp() {
+ InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 0);
+ when(socketIOClient.getRemoteAddress()).thenReturn(addr);
+ when(sendPacket.getName()).thenReturn("test");
+ when(clientHead.getRemoteAddress()).thenReturn(addr);
+
+ connectionInterceptor = new NettySocketIOConnectionInterceptor();
+ onEventInterceptor = new NettySocketIOOnEventInterceptor();
+ roomInterceptor = new NettySocketIORoomInterceptor();
+ constructorInterceptor = new NettySocketIOConstructorInterceptor();
+
+ // work for connection
+ connectOnConnectMethod = Whitebox.getMethods(Namespace.class, "onConnect")[0];
+ connectOnDisConnectMethod = Whitebox.getMethods(Namespace.class, "onDisconnect")[0];
+
+ // work for room
+ roomJoinMethod = Whitebox.getMethods(NamespaceClient.class, "joinRoom")[0];
+ roomLeaveMethod = Whitebox.getMethods(NamespaceClient.class, "leaveRoom")[0];
+ }
+
+ @Test
+ public void assertConnection() throws Throwable {
+ connectionInterceptor.beforeMethod(null, connectOnConnectMethod, new Object[]{socketIOClient}, null, null);
+ connectionInterceptor.afterMethod(null, connectOnConnectMethod, new Object[]{socketIOClient}, null, null);
+
+ connectionInterceptor.beforeMethod(null, connectOnDisConnectMethod, new Object[]{socketIOClient}, null, null);
+ connectionInterceptor.afterMethod(null, connectOnDisConnectMethod, new Object[]{socketIOClient}, null, null);
+
+ List traceSegments = segmentStorage.getTraceSegments();
+ Assert.assertThat(traceSegments.size(), is(2));
+ }
+
+ @Test
+ public void assertOnEvent() throws Throwable {
+ onEventInterceptor.beforeMethod(null, null, new Object[]{null, "test"}, null, null);
+ onEventInterceptor.afterMethod(null, null, new Object[]{null, "test"}, null, null);
+
+ List traceSegments = segmentStorage.getTraceSegments();
+ Assert.assertThat(traceSegments.size(), is(1));
+ }
+
+ @Test
+ public void assertConstructor() throws Throwable {
+ constructorInterceptor.onConstruct(enhancedInstance, new Object[] {clientHead, namespace});
+ }
+
+ @Test
+ public void assertRoom() throws Throwable {
+ roomInterceptor.beforeMethod(null, roomJoinMethod, new Object[] {"test_room"}, null,null);
+ roomInterceptor.afterMethod(null, roomJoinMethod, new Object[] {"test_room"}, null,null);
+
+ roomInterceptor.beforeMethod(null, roomLeaveMethod, new Object[] {"test_room"}, null,null);
+ roomInterceptor.afterMethod(null, roomLeaveMethod, new Object[] {"test_room"}, null,null);
+
+ List traceSegments = segmentStorage.getTraceSegments();
+ Assert.assertThat(traceSegments.size(), is(2));
+ }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml
index e7c75eaa8..2c7feb750 100644
--- a/apm-sniffer/apm-sdk-plugin/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/pom.xml
@@ -78,6 +78,7 @@
light4j-pluginsehcache-2.x-pluginpulsar-plugin
+ netty-socketio-pluginpom
diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md
index 1dc9da5fd..190452ea4 100644
--- a/docs/en/setup/service-agent/java-agent/Supported-list.md
+++ b/docs/en/setup/service-agent/java-agent/Supported-list.md
@@ -14,6 +14,7 @@
* [RESTEasy](https://resteasy.github.io/) 3.1.0.Final -> 3.7.0.Final
* [Play Framework](https://www.playframework.com/) 2.6.x -> 2.7.x (Optional²)
* [Light4J Microservices Framework](https://doc.networknt.com/) 1.6.x -> 2.x
+ * [Netty SocketIO](https://github.com/mrniko/netty-socketio) 1.x
* HTTP Client
* [Feign](https://github.com/OpenFeign/feign) 9.x
* [Netflix Spring Cloud Feign](https://github.com/spring-cloud/spring-cloud-netflix/tree/master/spring-cloud-starter-feign) 1.1.x, 1.2.x, 1.3.x
diff --git a/oap-server/server-core/src/test/resources/component-libraries.yml b/oap-server/server-core/src/test/resources/component-libraries.yml
index 5a57c5fcb..7aec14683 100755
--- a/oap-server/server-core/src/test/resources/component-libraries.yml
+++ b/oap-server/server-core/src/test/resources/component-libraries.yml
@@ -227,6 +227,9 @@ Light4J:
Ehcache:
id: 75
languages: Java
+SocketIO:
+ id: 76
+ languages: Java
# .NET/.NET Core components
# [3000, 4000) for C#/.NET only
diff --git a/oap-server/server-starter/src/main/resources/component-libraries.yml b/oap-server/server-starter/src/main/resources/component-libraries.yml
index 45d0ea806..5f21c5604 100755
--- a/oap-server/server-starter/src/main/resources/component-libraries.yml
+++ b/oap-server/server-starter/src/main/resources/component-libraries.yml
@@ -254,6 +254,9 @@ pulsar-consumer:
Ehcache:
id: 75
languages: Java
+SocketIO:
+ id: 76
+ languages: Java
# .NET/.NET Core components
# [3000, 4000) for C#/.NET only
diff --git a/test/plugin/scenarios/netty-socketio-scenario/config/expectedData.yaml b/test/plugin/scenarios/netty-socketio-scenario/config/expectedData.yaml
new file mode 100644
index 000000000..5f328fd84
--- /dev/null
+++ b/test/plugin/scenarios/netty-socketio-scenario/config/expectedData.yaml
@@ -0,0 +1,79 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+registryItems:
+ applications:
+ - {netty-socketio-scenario: 2}
+ instances:
+ - {netty-socketio-scenario: 1}
+ operationNames:
+ - netty-socketio-scenario: [/netty-socketio-scenario/case/netty-socketio, /socket.io/,
+ /netty-socketio-scenario/healthCheck, SocketIO/onConnect, SocketIO/send_data/receive]
+ heartbeat: []
+segmentItems:
+ - applicationCode: netty-socketio-scenario
+ segmentSize: ge 5
+ segments:
+ - segmentId: not null
+ spans:
+ - operationName: SocketIO/onConnect
+ operationId: 0
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 76
+ componentName: ''
+ isError: false
+ spanType: Entry
+ peer: ''
+ peerId: 0
+ tags:
+ - {key: from, value: not null}
+ - segmentId: not null
+ spans:
+ - operationName: /netty-socketio-scenario/case/netty-socketio
+ operationId: 0
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 1
+ componentName: ''
+ isError: false
+ spanType: Entry
+ peer: ''
+ peerId: 0
+ tags:
+ - {key: url, value: 'http://localhost:8080/netty-socketio-scenario/case/netty-socketio'}
+ - {key: http.method, value: GET}
+ - segmentId: not null
+ spans:
+ - operationName: SocketIO/send_data/receive
+ operationId: 0
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 76
+ componentName: ''
+ isError: false
+ spanType: Entry
+ peer: ''
+ peerId: 0
diff --git a/test/plugin/scenarios/netty-socketio-scenario/configuration.yml b/test/plugin/scenarios/netty-socketio-scenario/configuration.yml
new file mode 100644
index 000000000..b0503a5a0
--- /dev/null
+++ b/test/plugin/scenarios/netty-socketio-scenario/configuration.yml
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+type: tomcat
+entryService: http://localhost:8080/netty-socketio-scenario/case/netty-socketio
+healthCheck: http://localhost:8080/netty-socketio-scenario/healthCheck
+framework: netty-socketio
diff --git a/test/plugin/scenarios/netty-socketio-scenario/pom.xml b/test/plugin/scenarios/netty-socketio-scenario/pom.xml
new file mode 100644
index 000000000..69deea55d
--- /dev/null
+++ b/test/plugin/scenarios/netty-socketio-scenario/pom.xml
@@ -0,0 +1,82 @@
+
+
+
+ 4.0.0
+
+ org.apache.skywalking
+ netty-socketio-scenario
+ 5.0.0
+ war
+
+
+ UTF-8
+ 1.8
+
+
+ netty-socketio
+ 1.7.12
+
+
+ skywalking-netty-socketio-scenario
+
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.1.0
+ provided
+
+
+ org.apache.logging.log4j
+ log4j-api
+ 2.8.1
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.8.1
+
+
+ com.corundumstudio.socketio
+ netty-socketio
+ ${test.framework.version}
+
+
+ io.socket
+ socket.io-client
+ 1.0.0
+
+
+
+
+ netty-socketio-scenario
+
+
+ maven-compiler-plugin
+
+ ${compiler.version}
+ ${compiler.version}
+ ${project.build.sourceEncoding}
+
+
+
+
+
\ No newline at end of file
diff --git a/test/plugin/scenarios/netty-socketio-scenario/src/main/java/org/apache/skywalking/apm/testcase/netty/socketio/CaseServlet.java b/test/plugin/scenarios/netty-socketio-scenario/src/main/java/org/apache/skywalking/apm/testcase/netty/socketio/CaseServlet.java
new file mode 100644
index 000000000..6ad02af9c
--- /dev/null
+++ b/test/plugin/scenarios/netty-socketio-scenario/src/main/java/org/apache/skywalking/apm/testcase/netty/socketio/CaseServlet.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.skywalking.apm.testcase.netty.socketio;
+
+import com.corundumstudio.socketio.SocketIOClient;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class CaseServlet extends HttpServlet {
+
+ static {
+ // start socket io server
+ SocketIOStarter.startServer();
+
+ // start client
+ try {
+ SocketIOStarter.startClientAndWaitConnect();
+ } catch (Exception e) {
+ }
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ // create socket io client and send data
+ // test send message interceptor
+ SocketIOClient client = SocketIOStarter.server.getAllClients().iterator().next();
+ client.sendEvent(SocketIOStarter.SEND_EVENT_NAME, "data");
+
+ // client send message to server
+ // test for get message from client interceptor
+ SocketIOStarter.client.emit(SocketIOStarter.LISTEN_EVENT_NAME, "hello");
+
+ PrintWriter printWriter = resp.getWriter();
+ printWriter.write("success");
+ printWriter.flush();
+ printWriter.close();
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ doGet(req, resp);
+ }
+
+}
diff --git a/test/plugin/scenarios/netty-socketio-scenario/src/main/java/org/apache/skywalking/apm/testcase/netty/socketio/HealthCheckServlet.java b/test/plugin/scenarios/netty-socketio-scenario/src/main/java/org/apache/skywalking/apm/testcase/netty/socketio/HealthCheckServlet.java
new file mode 100644
index 000000000..ac81af30d
--- /dev/null
+++ b/test/plugin/scenarios/netty-socketio-scenario/src/main/java/org/apache/skywalking/apm/testcase/netty/socketio/HealthCheckServlet.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.skywalking.apm.testcase.netty.socketio;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class HealthCheckServlet extends HttpServlet {
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ PrintWriter writer = resp.getWriter();
+ writer.write("Success");
+ writer.flush();
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ doGet(req, resp);
+ }
+}
diff --git a/test/plugin/scenarios/netty-socketio-scenario/src/main/java/org/apache/skywalking/apm/testcase/netty/socketio/SocketIOStarter.java b/test/plugin/scenarios/netty-socketio-scenario/src/main/java/org/apache/skywalking/apm/testcase/netty/socketio/SocketIOStarter.java
new file mode 100644
index 000000000..1c26fa8d7
--- /dev/null
+++ b/test/plugin/scenarios/netty-socketio-scenario/src/main/java/org/apache/skywalking/apm/testcase/netty/socketio/SocketIOStarter.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.skywalking.apm.testcase.netty.socketio;
+
+import com.corundumstudio.socketio.AckRequest;
+import com.corundumstudio.socketio.Configuration;
+import com.corundumstudio.socketio.SocketIOClient;
+import com.corundumstudio.socketio.SocketIOServer;
+import com.corundumstudio.socketio.listener.ConnectListener;
+import com.corundumstudio.socketio.listener.DataListener;
+import io.socket.client.IO;
+import io.socket.client.Socket;
+import io.socket.emitter.Emitter;
+
+import java.net.URISyntaxException;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author MrPro
+ */
+public class SocketIOStarter {
+
+ public static final Integer SERVER_PORT = 9092;
+ public static final String LISTEN_EVENT_NAME = "send_data";
+ public static final String SEND_EVENT_NAME = "get_data";
+
+ public static SocketIOServer server;
+ public static Socket client;
+
+ public static void startServer() {
+ Configuration config = new Configuration();
+ config.setHostname("localhost");
+ config.setPort(SERVER_PORT);
+
+ server = new SocketIOServer(config);
+ server.addEventListener(LISTEN_EVENT_NAME, String.class, new DataListener() {
+ @Override
+ public void onData(SocketIOClient client, String data, AckRequest ackRequest) {
+ // get message
+ }
+ });
+
+ server.addConnectListener(new ConnectClientListener());
+
+ server.start();
+
+ // close server on kill signal
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ server.stop();
+ }
+ });
+ }
+
+ private static class ConnectClientListener implements ConnectListener {
+
+ @Override
+ public void onConnect(SocketIOClient client) {
+ // connect client
+ }
+ }
+
+ public static void startClientAndWaitConnect() throws URISyntaxException, InterruptedException {
+ client = IO.socket("http://localhost:" + SERVER_PORT);
+ LinkedBlockingQueue connected = new LinkedBlockingQueue<>(1);
+ client.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
+ @Override
+ public void call(Object... objects) {
+ connected.add(true);
+ }
+ });
+ client.connect();
+
+ // wait connect to server
+ connected.poll(5, TimeUnit.SECONDS);
+ }
+
+}
diff --git a/test/plugin/scenarios/netty-socketio-scenario/src/main/webapp/WEB-INF/web.xml b/test/plugin/scenarios/netty-socketio-scenario/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..655eb6565
--- /dev/null
+++ b/test/plugin/scenarios/netty-socketio-scenario/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,45 @@
+
+
+ skywalking-netty-socketio-scenario
+
+
+ caseServlet
+ org.apache.skywalking.apm.testcase.netty.socketio.CaseServlet
+
+
+ caseServlet
+ /case/netty-socketio
+
+
+
+ healthCheck
+ org.apache.skywalking.apm.testcase.netty.socketio.HealthCheckServlet
+
+
+ healthCheck
+ /healthCheck
+
+
+
+
+
diff --git a/test/plugin/scenarios/netty-socketio-scenario/support-version.list b/test/plugin/scenarios/netty-socketio-scenario/support-version.list
new file mode 100644
index 000000000..141011deb
--- /dev/null
+++ b/test/plugin/scenarios/netty-socketio-scenario/support-version.list
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+1.7.12
+1.7.14
+1.7.16
+1.7.17
\ No newline at end of file