Add nacos-client 2.x plugin (#593)

This commit is contained in:
peachisai 2023-08-18 08:45:46 +08:00 committed by GitHub
parent e7394a87da
commit e31b9bb6a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 1086 additions and 0 deletions

View File

@ -80,6 +80,7 @@ jobs:
- jersey-2.0.x-2.25.x-scenario
- jersey-2.26.x-2.39.x-scenario
- websphere-liberty-23.x-scenario
- nacos-client-2.x-scenario
steps:
- uses: actions/checkout@v2
with:

View File

@ -151,6 +151,7 @@ Callable {
* Fix Jedis-2.x plugin bug and add test for Redis cluster scene
* Merge two instrumentation classes to avoid duplicate enhancements in MySQL plugins.
* Support asynchronous invocation in jetty client 9.0 and 9.x plugin
* Add nacos-client 2.x plugin
#### Documentation

View File

@ -241,4 +241,5 @@ public class ComponentsDefine {
public static final OfficialComponent AEROSPIKE = new OfficialComponent(149, "Aerospike");
public static final OfficialComponent NACOS = new OfficialComponent(150, "Nacos");
}

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
~
-->
<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">
<parent>
<groupId>org.apache.skywalking</groupId>
<artifactId>optional-plugins</artifactId>
<version>9.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apm-nacos-client-2.x-plugin</artifactId>
<name>nacos-client-2.x-plugin</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<nacos-client.version>2.0.3</nacos-client.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>${nacos-client.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -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.nacos.v2;
import com.alibaba.nacos.api.remote.request.Request;
import com.alibaba.nacos.common.remote.client.RpcClient;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
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 java.lang.reflect.Method;
public class ClientHandleServerRequestInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
String peer = getPeer(objInst);
NacosRequestOpt.getHandler(allArguments[0].getClass()).ifPresent(o -> o.buildRequestSpanInfo((Request) allArguments[0], peer));
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
if (ContextManager.isActive()) {
ContextManager.stopSpan();
}
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
if (ContextManager.isActive()) {
ContextManager.activeSpan().log(t);
}
}
private String getPeer(EnhancedInstance objInst) {
Object dynamicField = objInst.getSkyWalkingDynamicField();
if (dynamicField instanceof RpcClient.ServerInfo) {
RpcClient.ServerInfo serverInfo = (RpcClient.ServerInfo) dynamicField;
return serverInfo.getAddress();
}
return "no peer";
}
}

View File

@ -0,0 +1,58 @@
/*
* 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.nacos.v2;
import com.alibaba.nacos.api.remote.response.Response;
import com.alibaba.nacos.common.remote.client.RpcClient;
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;
public class ClientServerCheckInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
String ip = (String) allArguments[0];
int port = (Integer) allArguments[1];
objInst.setSkyWalkingDynamicField(new RpcClient.ServerInfo(ip, port));
AbstractSpan span = ContextManager.createExitSpan("Nacos/serverCheck", ip + ":" + port);
SpanLayer.asRPCFramework(span);
span.setComponent(ComponentsDefine.NACOS);
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
if (ret == null || !((Response) ret).isSuccess()) {
ContextManager.activeSpan().errorOccurred();
}
ContextManager.stopSpan();
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().log(t);
}
}

View File

@ -0,0 +1,58 @@
/*
* 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.nacos.v2;
import com.alibaba.nacos.api.remote.request.Request;
import com.alibaba.nacos.api.remote.response.Response;
import com.alibaba.nacos.common.remote.client.grpc.GrpcConnection;
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.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 java.lang.reflect.Method;
public class GrpcConnectionInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
GrpcConnection connection = (GrpcConnection) objInst;
NacosRequestOpt.getHandler(allArguments[0].getClass()).ifPresent(o -> o.buildRequestSpanInfo((Request) allArguments[0], connection.getChannel().authority()));
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
if (ContextManager.isActive()) {
if (ret == null || !((Response) ret).isSuccess()) {
AbstractSpan span = ContextManager.activeSpan();
span.errorOccurred();
}
ContextManager.stopSpan();
}
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
if (ContextManager.isActive()) {
ContextManager.activeSpan().log(t);
}
}
}

View File

@ -0,0 +1,145 @@
/*
* 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.nacos.v2;
import com.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest;
import com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest;
import com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest;
import com.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest;
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
import com.alibaba.nacos.api.naming.remote.request.InstanceRequest;
import com.alibaba.nacos.api.naming.remote.request.NotifySubscriberRequest;
import com.alibaba.nacos.api.naming.remote.request.ServiceListRequest;
import com.alibaba.nacos.api.naming.remote.request.ServiceQueryRequest;
import com.alibaba.nacos.api.naming.remote.request.SubscribeServiceRequest;
import com.alibaba.nacos.api.remote.request.Request;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
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.network.trace.component.ComponentsDefine;
import org.apache.skywalking.apm.plugin.nacos.v2.constant.NacosConstants;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@SuppressWarnings("rawtypes")
public class NacosRequestOpt {
private static final Map<Class, Handler> OPTS = new HashMap<>();
static {
OPTS.put(InstanceRequest.class, (request, peer) -> {
AbstractSpan span = getNacosExitSpan(peer);
span.setOperationName(span.getOperationName() + ((InstanceRequest) request).getType());
span.tag(Tags.ofKey(NacosConstants.NAMESPACE), ((InstanceRequest) request).getNamespace());
span.tag(Tags.ofKey(NacosConstants.GROUP), ((InstanceRequest) request).getGroupName());
span.tag(Tags.ofKey(NacosConstants.SERVICE_NAME), ((InstanceRequest) request).getServiceName());
});
OPTS.put(ServiceQueryRequest.class, (request, peer) -> {
AbstractSpan span = getNacosExitSpan(peer);
span.setOperationName(span.getOperationName() + NacosConstants.QUERY_SERVICE);
span.tag(Tags.ofKey(NacosConstants.NAMESPACE), ((ServiceQueryRequest) request).getNamespace());
span.tag(Tags.ofKey(NacosConstants.GROUP), ((ServiceQueryRequest) request).getGroupName());
span.tag(Tags.ofKey(NacosConstants.SERVICE_NAME), ((ServiceQueryRequest) request).getServiceName());
});
OPTS.put(SubscribeServiceRequest.class, (request, peer) -> {
AbstractSpan span = getNacosExitSpan(peer);
span.setOperationName(span.getOperationName() + (((SubscribeServiceRequest) request).isSubscribe() ?
NacosConstants.SUBSCRIBE_SERVICE : NacosConstants.UNSUBSCRIBE_SERVICE));
span.tag(Tags.ofKey(NacosConstants.NAMESPACE), ((SubscribeServiceRequest) request).getNamespace());
span.tag(Tags.ofKey(NacosConstants.GROUP), ((SubscribeServiceRequest) request).getGroupName());
span.tag(Tags.ofKey(NacosConstants.SERVICE_NAME), ((SubscribeServiceRequest) request).getServiceName());
});
OPTS.put(ServiceListRequest.class, (request, peer) -> {
AbstractSpan span = getNacosExitSpan(peer);
span.setOperationName(span.getOperationName() + NacosConstants.GET_SERVICE_LIST);
span.tag(Tags.ofKey(NacosConstants.NAMESPACE), ((ServiceListRequest) request).getNamespace());
span.tag(Tags.ofKey(NacosConstants.GROUP), ((ServiceListRequest) request).getGroupName());
span.tag(Tags.ofKey(NacosConstants.SERVICE_NAME), ((ServiceListRequest) request).getServiceName());
});
OPTS.put(ConfigQueryRequest.class, (request, peer) -> {
AbstractSpan span = getNacosExitSpan(peer);
span.setOperationName(span.getOperationName() + NacosConstants.QUERY_CONFIG);
span.tag(Tags.ofKey(NacosConstants.DATA_ID), ((ConfigQueryRequest) request).getDataId());
span.tag(Tags.ofKey(NacosConstants.GROUP), ((ConfigQueryRequest) request).getGroup());
span.tag(Tags.ofKey(NacosConstants.TENANT), ((ConfigQueryRequest) request).getTenant());
});
OPTS.put(ConfigPublishRequest.class, (request, peer) -> {
AbstractSpan span = getNacosExitSpan(peer);
span.setOperationName(span.getOperationName() + NacosConstants.PUBLISH_CONFIG);
span.tag(Tags.ofKey(NacosConstants.DATA_ID), ((ConfigPublishRequest) request).getDataId());
span.tag(Tags.ofKey(NacosConstants.GROUP), ((ConfigPublishRequest) request).getGroup());
span.tag(Tags.ofKey(NacosConstants.TENANT), ((ConfigPublishRequest) request).getTenant());
});
OPTS.put(ConfigRemoveRequest.class, (request, peer) -> {
AbstractSpan span = getNacosExitSpan(peer);
span.setOperationName(span.getOperationName() + NacosConstants.REMOVE_CONFIG);
span.tag(Tags.ofKey(NacosConstants.DATA_ID), ((ConfigRemoveRequest) request).getDataId());
span.tag(Tags.ofKey(NacosConstants.GROUP), ((ConfigRemoveRequest) request).getGroup());
span.tag(Tags.ofKey(NacosConstants.TENANT), ((ConfigRemoveRequest) request).getTenant());
});
OPTS.put(NotifySubscriberRequest.class, (request, peer) -> {
AbstractSpan span = getNacosEntrySpan(peer);
span.setOperationName(span.getOperationName() + NacosConstants.NOTIFY_SUBSCRIBE_CHANGE);
ServiceInfo serviceInfo = ((NotifySubscriberRequest) request).getServiceInfo();
span.tag(Tags.ofKey(NacosConstants.GROUP), serviceInfo.getGroupName());
span.tag(Tags.ofKey(NacosConstants.SERVICE_NAME), serviceInfo.getName());
});
OPTS.put(ConfigChangeNotifyRequest.class, (request, peer) -> {
AbstractSpan span = getNacosEntrySpan(peer);
span.setOperationName(span.getOperationName() + NacosConstants.NOTIFY_CONFIG_CHANGE);
span.tag(Tags.ofKey(NacosConstants.DATA_ID), ((ConfigChangeNotifyRequest) request).getDataId());
span.tag(Tags.ofKey(NacosConstants.GROUP), ((ConfigChangeNotifyRequest) request).getGroup());
span.tag(Tags.ofKey(NacosConstants.TENANT), ((ConfigChangeNotifyRequest) request).getTenant());
});
}
private static AbstractSpan getNacosEntrySpan(String peer) {
AbstractSpan span = ContextManager.createEntrySpan(NacosConstants.NACOS_PREFIX, null);
span.setComponent(ComponentsDefine.NACOS);
span.setPeer(peer);
SpanLayer.asRPCFramework(span);
return span;
}
private static AbstractSpan getNacosExitSpan(String peer) {
AbstractSpan span = ContextManager.createExitSpan(NacosConstants.NACOS_PREFIX, peer);
span.setComponent(ComponentsDefine.NACOS);
SpanLayer.asRPCFramework(span);
return span;
}
public static Optional<Handler> getHandler(Class clazz) {
return Optional.ofNullable(OPTS.get(clazz));
}
interface Handler {
void buildRequestSpanInfo(Request request, String peer);
}
}

View File

@ -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.nacos.v2.constant;
public class NacosConstants {
public static final String NACOS_PREFIX = "Nacos/";
public static final String QUERY_SERVICE = "queryService";
public static final String SUBSCRIBE_SERVICE = "subscribeService";
public static final String UNSUBSCRIBE_SERVICE = "unsubscribeService";
public static final String QUERY_CONFIG = "queryConfig";
public static final String PUBLISH_CONFIG = "publishConfig";
public static final String REMOVE_CONFIG = "removeConfig";
public static final String GET_SERVICE_LIST = "getServiceList";
public static final String NOTIFY_SUBSCRIBE_CHANGE = "notifySubscribeChange";
public static final String NOTIFY_CONFIG_CHANGE = "notifyConfigChange";
public static final String NAMESPACE = "namespace";
public static final String GROUP = "group";
public static final String SERVICE_NAME = "serviceName";
public static final String DATA_ID = "dataId";
public static final String TENANT = "tenant";
}

View File

@ -0,0 +1,28 @@
/*
* 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.nacos.v2.define;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
public abstract class AbstractGrpcClientIntrumentation extends ClassInstanceMethodsEnhancePluginDefine {
@Override
protected String[] witnessClasses() {
return new String[]{"com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy"};
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.nacos.v2.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.match.ClassMatch;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
public class GrpcConnectionClientIntrumentation extends AbstractGrpcClientIntrumentation {
private static final String ENHANCE_CLASS = "com.alibaba.nacos.common.remote.client.grpc.GrpcConnection";
private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.nacos.v2.GrpcConnectionInterceptor";
@Override
protected ClassMatch enhanceClass() {
return byName(ENHANCE_CLASS);
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[]{
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("request");
}
@Override
public String getMethodsInterceptor() {
return INTERCEPTOR_CLASS;
}
@Override
public boolean isOverrideArgs() {
return false;
}
}
};
}
}

View File

@ -0,0 +1,85 @@
/*
* 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.nacos.v2.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.match.ClassMatch;
import org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch;
import static net.bytebuddy.matcher.ElementMatchers.named;
public class RpcClientIntrumentation extends AbstractGrpcClientIntrumentation {
private static final String ENHANCE_CLASS = "com.alibaba.nacos.common.remote.client.RpcClient";
private static final String HANDLE_SERVER_REQUEST_CLASS = "org.apache.skywalking.apm.plugin.nacos.v2.ClientHandleServerRequestInterceptor";
private static final String CONNECT_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.nacos.v2.ClientServerCheckInterceptor";
@Override
protected ClassMatch enhanceClass() {
return HierarchyMatch.byHierarchyMatch(ENHANCE_CLASS);
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[]{
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("serverCheck");
}
@Override
public String getMethodsInterceptor() {
return CONNECT_INTERCEPTOR_CLASS;
}
@Override
public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("handleServerRequest");
}
@Override
public String getMethodsInterceptor() {
return HANDLE_SERVER_REQUEST_CLASS;
}
@Override
public boolean isOverrideArgs() {
return false;
}
}
};
}
}

View File

@ -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.
nacos-client-2.x=org.apache.skywalking.apm.plugin.nacos.v2.define.GrpcConnectionClientIntrumentation
nacos-client-2.x=org.apache.skywalking.apm.plugin.nacos.v2.define.RpcClientIntrumentation

View File

@ -57,6 +57,7 @@
<module>jackson-2.x-plugin</module>
<module>shenyu-2.4.x-plugin</module>
<module>trace-sampler-cpu-policy-plugin</module>
<module>nacos-client-2.x-plugin</module>
</modules>
<dependencies>

View File

@ -23,3 +23,4 @@ Now, we have the following known optional plugins.
* Plugin of Apache ShenYu(incubating) Gateway 2.4.x in optional plugin folder. Please only activate this plugin when you install agent in Apache ShenYu Gateway.
* Plugin of trace sampler CPU policy in the optional plugin folder. Please only activate this plugin when you need to disable trace collecting when the agent process CPU usage is too high(over threshold).
* Plugin for Spring 6.x and RestTemplate 6.x are in the optional plugin folder. Spring 6 requires Java 17 but SkyWalking is still compatible with Java 8. So, we put it in the optional plugin folder.
* Plugin of nacos-client 2.x lib in optional plugin folder.The reason is many business irrelevant traces are generated, which cause extra payload to agents and backends, also spend more CPU, memory and network.

View File

@ -68,6 +68,7 @@
- mysql-5.x
- mysql-6.x
- mysql-8.x
- nacos-client-2.x
- netty-socketio
- nutz-http-1.x
- nutz-mvc-annotation-1.x

View File

@ -69,6 +69,7 @@ metrics based on the tracing data.
* [Thrift](https://github.com/apache/thrift/tree/master/lib/java) 0.10.0 -> 0.12.0
* [Apache CXF](https://github.com/apache/cxf) 3.x
* [JSONRPC4J](https://github.com/briandilley/jsonrpc4j) 1.2.0 -> 1.6
* [Nacos-Client](https://github.com/alibaba/nacos) 2.x (Optional²)
* MQ
* [RocketMQ](https://github.com/apache/rocketmq) 3.x-> 5.x
* [Kafka](http://kafka.apache.org) 0.11.0.0 -> 3.2.3

View File

@ -0,0 +1,21 @@
#!/bin/bash
#
# 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.
home="$(cd "$(dirname $0)"; pwd)"
java -Dnacos.serverAddr=${NACOS_SERVERADDR} -jar ${agent_opts} ${home}/../libs/nacos-client-2.x-scenario.jar &

View File

@ -0,0 +1,120 @@
# 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.
segmentItems:
- serviceName: nacos-client-2.x-scenario
segmentSize: gt 0
segments:
- segmentId: not null
spans:
- operationName: Nacos/serverCheck
parentSpanId: 0
spanId: ge 0
spanLayer: RPCFramework
startTime: not null
endTime: not null
componentId: 150
isError: false
spanType: Exit
peer: nacos-server:9848
skipAnalysis: 'false'
- operationName: Nacos/registerInstance
parentSpanId: 0
spanId: nq 0
spanLayer: RPCFramework
startTime: not null
endTime: not null
componentId: 150
isError: false
spanType: Exit
peer: nacos-server:9848
tags:
- {key: namespace, value: public}
- {key: group, value: DEFAULT_GROUP}
- {key: serviceName, value: nacos-scenario}
skipAnalysis: 'false'
- operationName: Nacos/subscribeService
parentSpanId: 0
spanId: nq 0
spanLayer: RPCFramework
startTime: not null
endTime: not null
componentId: 150
isError: false
spanType: Exit
peer: nacos-server:9848
skipAnalysis: false
tags:
- { key: namespace, value: public }
- { key: group, value: DEFAULT_GROUP }
- { key: serviceName, value: nacos-scenario }
- operationName: Nacos/serverCheck
parentSpanId: 0
spanId: nq 0
spanLayer: RPCFramework
startTime: not null
endTime: not null
componentId: 150
isError: false
spanType: Exit
peer: nacos-server:9848
skipAnalysis: 'false'
- operationName: Nacos/publishConfig
parentSpanId: 0
spanId: nq 0
spanLayer: RPCFramework
startTime: not null
endTime: not null
componentId: 150
isError: false
spanType: Exit
peer: nacos-server:9848
skipAnalysis: false
tags:
- { key: dataId, value: dataId }
- { key: group, value: DEFAULT_GROUP }
- { key: tenant, value: null }
- operationName: GET:/case/nacos-client-2.x-case
parentSpanId: -1
spanId: 0
spanLayer: Http
startTime: not null
endTime: not null
componentId: 14
isError: false
spanType: Entry
peer: ''
tags:
- {key: url, value: not null}
- {key: http.method, value: GET}
- {key: http.status_code, value: '200'}
skipAnalysis: 'false'
- segmentId: not null
spans:
- operationName: Nacos/notifySubscribeChange
parentSpanId: -1
spanId: 0
spanLayer: RPCFramework
startTime: not null
endTime: not null
componentId: 150
isError: false
spanType: Entry
peer: nacos-server:9848
skipAnalysis: 'false'
tags:
- { key: group, value: DEFAULT_GROUP }
- { key: serviceName, value: nacos-scenario }

View File

@ -0,0 +1,32 @@
# 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: jvm
entryService: http://localhost:8080/nacos-client-2.x-scenario/case/nacos-client-2.x-case
healthCheck: http://localhost:8080/nacos-client-2.x-scenario/case/healthCheck
startScript: ./bin/startup.sh
runningMode: with_optional
withPlugins: apm-nacos-client-2.x-plugin-*.jar
environment:
- NACOS_SERVERADDR=nacos-server:8848
depends_on:
- nacos-server
dependencies:
nacos-server:
image: nacos/nacos-server:v2.2.0
hostname: nacos-server
environment:
- MODE=standalone

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
~
-->
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.skywalking</groupId>
<artifactId>nacos-client-2.x-scenario</artifactId>
<version>1.0.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<compiler.version>1.8</compiler.version>
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
<spring.boot.version>2.1.6.RELEASE</spring.boot.version>
<test.framework.version>2.0.3</test.framework.version>
</properties>
<name>skywalking-nacos-client-scenario</name>
<dependencies>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>${test.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
</dependencies>
<build>
<finalName>nacos-client-2.x-scenario</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.9.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${compiler.version}</source>
<target>${compiler.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
<outputDirectory>./target/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
~
-->
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>./bin</directory>
<fileMode>0775</fileMode>
</fileSet>
</fileSets>
<files>
<file>
<source>${project.build.directory}/nacos-client-2.x-scenario.jar</source>
<outputDirectory>./libs</outputDirectory>
<fileMode>0775</fileMode>
</file>
</files>
</assembly>

View File

@ -0,0 +1,30 @@
/*
* 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 test.apache.skywalking.apm.testcase.nacos.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,71 @@
/*
* 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 test.apache.skywalking.apm.testcase.nacos.client.controller;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.EventListener;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Properties;
@RestController
@RequestMapping("/case")
public class CaseController {
@Value("${nacos.serverAddr}")
private String nacosServerAddr;
@RequestMapping("/nacos-client-2.x-case")
@ResponseBody
public String nacosClientCase() throws Exception {
Properties prop = new Properties();
prop.setProperty("serverAddr", nacosServerAddr);
ConfigService configService = NacosFactory.createConfigService(prop);
prop.put(PropertyKeyConst.NAMESPACE, "public");
NamingService namingService = NamingFactory.createNamingService(prop);
String serviceName = "nacos-scenario";
String ip = "1.1.1.1";
int port = 10000;
namingService.registerInstance(serviceName, ip, port);
EventListener listener = event -> {
};
namingService.subscribe(serviceName, listener);
configService.publishConfig(Constants.DATAID, Constants.DEFAULT_GROUP, "content");
return "Success";
}
@RequestMapping("/healthCheck")
@ResponseBody
public String healthCheck() {
return "success";
}
}

View File

@ -0,0 +1,22 @@
#
# 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.
#
#
server:
port: 8080
servlet:
context-path: /nacos-client-2.x-scenario

View File

@ -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.
2.0.3
2.1.1
2.2.0