Skip to content

Add the Nacos-Client 2.x plugin#18758

Open
peachisai wants to merge 25 commits into
open-telemetry:mainfrom
peachisai:dev
Open

Add the Nacos-Client 2.x plugin#18758
peachisai wants to merge 25 commits into
open-telemetry:mainfrom
peachisai:dev

Conversation

@peachisai

Copy link
Copy Markdown

#18290
nacos-client utilizes the Maven Shade plugin to prevent class conflicts. Consequently, gRPC instrumentation is unable to capture the requests.

Copilot AI review requested due to automatic review settings May 15, 2026 00:47
@peachisai peachisai requested a review from a team as a code owner May 15, 2026 00:47
@linux-foundation-easycla

linux-foundation-easycla Bot commented May 15, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: peachisai / name: peachisai (6226da8)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 15 comments.

Comments suppressed due to low confidence (2)

instrumentation/nacos-client-2.0/metadata.yaml:3

  • [Documentation] This module builds RPC client/consumer spans, but the metadata does not declare any semantic_conventions entries. Existing RPC modules such as instrumentation/grpc-1.6/metadata.yaml:3-7 and instrumentation/apache-dubbo-2.7/metadata.yaml:5-9 declare their RPC span/metric signals so generated docs and the instrumentation registry classify the emitted telemetry correctly.
description: This instrumentation provides a template for Nacos client 2.x spans.
disabled_by_default: true

instrumentation/nacos-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/nacosclient/v2_0/NacosClientInstrumentationModule.java:33

  • [General] The module is registered but explicitly disabled by default, while the PR/linked issue describe adding Nacos 2.x instrumentation to cover requests that shaded gRPC cannot capture. As written, users will still get no Nacos spans after upgrading unless they discover and set otel.instrumentation.nacos-client.enabled=true; either make the instrumentation enabled by default or document the opt-in rationale clearly.
  @Override
  public boolean defaultEnabled() {
    return false;
  }

@@ -0,0 +1,4 @@
display_name: Nacos Client
description: This instrumentation provides a template for Nacos client 2.x spans.
Comment on lines +24 to +27
return asList(
new GrpcClientInstrumentation(),
new GrpcConnectionInstrumentation(),
new RpcClientInstrumentation());
Comment on lines +91 to +92
.addAttributesExtractor(new NacosClientAttributesExtractor());
return builder.buildInstrumenter(SpanKindExtractor.alwaysConsumer());
import com.alibaba.nacos.api.remote.request.Request;
import javax.annotation.Nullable;

public final class NacosClientRequest {
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;

public final class ContextAndScope {
Comment on lines +15 to +16
final class NacosClientRpcAttributesGetter
implements RpcAttributesGetter<NacosClientRequest, Response> {
Comment on lines +13 to +15
final class NacosClientNetworkAttributesGetter
implements ServerAttributesGetter<NacosClientRequest>,
NetworkAttributesGetter<NacosClientRequest, Response> {
Comment on lines +25 to +26
final class NacosClientAttributesExtractor
implements AttributesExtractor<NacosClientRequest, Response> {
request, category, operation, peer, hostPort.host(), hostPort.port());
}

private static final class HostPort {
}
}

private static final class ServerCheckRequest extends Request {

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@Override
public void transform(TypeTransformer transformer) {
transformer.applyAdviceToMethod(
isMethod()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isMethod() isn't needed

Comment on lines +46 to +65
if (rawRequest instanceof InstanceRequest) {
InstanceRequest instanceRequest = (InstanceRequest) rawRequest;
put(attributes, NACOS_NAMESPACE, instanceRequest.getNamespace());
put(attributes, NACOS_GROUP, instanceRequest.getGroupName());
put(attributes, NACOS_SERVICE_NAME, instanceRequest.getServiceName());
} else if (rawRequest instanceof ServiceQueryRequest) {
ServiceQueryRequest serviceQueryRequest = (ServiceQueryRequest) rawRequest;
put(attributes, NACOS_NAMESPACE, serviceQueryRequest.getNamespace());
put(attributes, NACOS_GROUP, serviceQueryRequest.getGroupName());
put(attributes, NACOS_SERVICE_NAME, serviceQueryRequest.getServiceName());
} else if (rawRequest instanceof SubscribeServiceRequest) {
SubscribeServiceRequest subscribeServiceRequest = (SubscribeServiceRequest) rawRequest;
put(attributes, NACOS_NAMESPACE, subscribeServiceRequest.getNamespace());
put(attributes, NACOS_GROUP, subscribeServiceRequest.getGroupName());
put(attributes, NACOS_SERVICE_NAME, subscribeServiceRequest.getServiceName());
} else if (rawRequest instanceof ServiceListRequest) {
ServiceListRequest serviceListRequest = (ServiceListRequest) rawRequest;
put(attributes, NACOS_NAMESPACE, serviceListRequest.getNamespace());
put(attributes, NACOS_GROUP, serviceListRequest.getGroupName());
put(attributes, NACOS_SERVICE_NAME, serviceListRequest.getServiceName());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of these are subclasses of AbstractNamingRequest could consider using instanceof AbstractNamingRequest

NacosClientRequest request, @Nullable Response response, @Nullable Throwable error) {
if (response != null && !response.isSuccess()) {
int errorCode = response.getErrorCode();
return errorCode == 0 ? "response_error" : String.valueOf(errorCode);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why response_error?

return builder.buildInstrumenter(SpanKindExtractor.alwaysClient());
}

private static Instrumenter<NacosClientRequest, Response> createServerInstrumenter() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider removing Client from classes shared by client and server instrumentation

if (response != null && !response.isSuccess()) {
String message = response.getMessage();
int errorCode = response.getErrorCode();
return new IllegalStateException(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating an exception here doesn't make sense since the stack trace is not going to be useful for the end user. Consider implementing a SpanStatusExtractor extractor instead that sets span status to error when the response wasn't successful.

if (serverInfo == null) {
serverInfo = rpcClient.getCurrentServer();
}
return serverInfo != null ? serverInfo.getAddress() : "unknown";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

our convention is to leave attributes unfilled if a value can't be extracted

Comment on lines +18 to +23
testImplementation(project(":instrumentation-api"))
testImplementation(project(":instrumentation-api-incubator"))

testImplementation("io.opentelemetry:opentelemetry-api")
testImplementation("io.opentelemetry:opentelemetry-context")
testImplementation("com.alibaba.nacos:nacos-client:2.0.0")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these aren't needed

systemProperty("collectMetadata", otelProps.collectMetadata)
}

val testAgentInstrumentation by tasks.registering(Test::class) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you don't need a separate test task for this, could just add jvmArgs("-Dotel.instrumentation.nacos-client.enabled=true") to the main test task.

"co.elastic.clients:elasticsearch-java#+": "9.4.1",
"co.elastic.clients:elasticsearch-java#8.9.+": "8.9.2",
"com.alibaba:druid#+": "1.2.28",
"com.alibaba.nacos:nacos-client#+": "2.5.2",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you manually edit this? should the latest version be 3.2.1?

@Advice.Argument(0) String serverIp,
@Advice.Argument(1) int serverPort) {
RpcClientServerInfoAccessor.set(rpcClient, new RpcClient.ServerInfo(serverIp, serverPort));
return NacosClientSingletons.startClientSpan(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This somewhat deviates from wheat we usually do. Many instrumentations use a class named AdviceScope to pass context, scope and request to end advice. Using some other class is also fine, for example here instead of ContextAndScope you could pass a class that contains context, scope and request and knows how to end the span.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants