Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Nacos Client (#9961) #12849

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open

Conversation

wl2027
Copy link

@wl2027 wl2027 commented Dec 8, 2024

Enhancement Methods

  • com.alibaba.nacos.common.remote.client.grpc.GrpcConnection#request
  • com.alibaba.nacos.common.remote.client.RpcClient#handleServerRequest

Enable Configuration

Configuration Items Default Value
otel.instrumentation.nacos-client.default-enabled false

Span Info Details

Request Child Class SpanName Additional Tags
InstanceRequest Nacos/{$(lnstanceRequest.getType()} nacos.namespace nacos.group nacos.service.name
ServiceQueryRequest Nacos/queryService
SubscribeServiceRequest Nacos/subscribeService,Nacos/unsubscribeService
ServicelistRequest Nacos/getServicelist
ConfigQueryRequest Nacos/queryConfig
ConfigPublishRequest Nacos/publishConfig nacos.data.id nacos.group nacos.tenant
ConfigRemoveRequest Nacos/removeConfig
ConfigChangeNotifyRequest Nacos/notifyConfigChange
NotifySubscriberRequest Nacos/notifySubscribeChange nacos.group nacos.service.name

@wl2027 wl2027 requested a review from a team as a code owner December 8, 2024 05:22
Copy link

linux-foundation-easycla bot commented Dec 8, 2024

CLA Signed

The committers listed above are authorized under a signed CLA.

@github-actions github-actions bot requested a review from theletterf December 8, 2024 05:22
@@ -101,6 +101,7 @@ These are the supported libraries and frameworks:
| [Micrometer](https://micrometer.io/) | 1.5+ | [opentelemetry-micrometer-1.5](../instrumentation/micrometer/micrometer-1.5/library) | none |
| [MongoDB Driver](https://mongodb.github.io/mongo-java-driver/) | 3.1+ | [opentelemetry-mongo-3.1](../instrumentation/mongo/mongo-3.1/library) | [Database Client Spans] |
| [MyBatis](https://mybatis.org/mybatis-3/) | 3.2+ | N/A | none |
| [Nacos](https://nacos.io/) | 2.0.3+ | N/A | none |
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps use Nacos Client since the instrumentation is for the client

Copy link
Author

Choose a reason for hiding this comment

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

Okay, I will make changes here.

}

dependencies {
val nacosClientVersion = "2.0.3"
Copy link
Contributor

Choose a reason for hiding this comment

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

usually we don't use a separate variable for the instrumented library version, since this is used only in 1 place you could inline it
why are you suing 2.0.3, as far as I can tell tests pass with 2.0.0

Copy link
Author

Choose a reason for hiding this comment

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

The version 2.0.3 was chosen because I referred to the requirements described in issue #9961. However, after testing, I found that version 2.0.0 also works. I will make changes here.


dependencies {
val nacosClientVersion = "2.0.3"
implementation("com.alibaba.nacos:nacos-client:$nacosClientVersion")
Copy link
Contributor

Choose a reason for hiding this comment

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

implementation may not be used here. implementation dependencies are bundled inside the agent jar which is not desired. Usually we use library that is our custom scope that means compileOnly + testImplementation. library also supports running tests with the latest version of the library with -PtestLatestDeps=true (currently tests don't compile with the latest version, you can use latestDepTestLibrary to limit the latest version or you could define tests suites)

Copy link
Author

Choose a reason for hiding this comment

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

Okay, I will make changes here.

Comment on lines 21 to 24
tasks.withType<Test>().configureEach {
jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED")
jvmArgs("-XX:+IgnoreUnrecognizedVMOptions")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

is this really needed?

Copy link
Author

Choose a reason for hiding this comment

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

Okay, I will make changes here.


@Override
public List<TypeInstrumentation> typeInstrumentations() {
return Arrays.asList(new GrpcConnectionInstrumentation(), new RpcClientInstrumentation());
Copy link
Contributor

Choose a reason for hiding this comment

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

usually we static import Arrays.asList

Copy link
Author

Choose a reason for hiding this comment

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

Okay, I will make changes here.

@Override
public void transform(TypeTransformer transformer) {
transformer.applyAdviceToMethod(
isMethod().and(isPublic()).and(namedOneOf("request")).and(returns(Response.class)),
Copy link
Contributor

Choose a reason for hiding this comment

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

usually we use named instead of namedOneOf when there is only one name
don't use returns(Response.class), use returns(named("com.alibaba.nacos.api.remote.response.Response")). This way you don't need to bundle the Response class inside the agent.

Copy link
Author

Choose a reason for hiding this comment

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

Okay, I will make changes here.

public void transform(TypeTransformer transformer) {
transformer.applyAdviceToMethod(
isMethod().and(isPublic()).and(namedOneOf("request")).and(returns(Response.class)),
GrpcConnectionRequestAdvice.class.getName());
Copy link
Contributor

Choose a reason for hiding this comment

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

Usually we have advice classes as inner classes and here use this.getClass() + "$GrpcConnectionRequestAdvice". We avoid using the full class name to avoid loading the advice class when the advice is added, this way we can use the types from instrumented library inside the advice class without bundling the instrumented library inside the agent.

Copy link
Author

Choose a reason for hiding this comment

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

Okay, I will make changes here.

* SPDX-License-Identifier: Apache-2.0
*/

package com.alibaba.nacos.common.remote.client;
Copy link
Contributor

Choose a reason for hiding this comment

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

usually we place test classes in the same package as the instrumentation

Copy link
Author

Choose a reason for hiding this comment

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

I did this because com.alibaba.nacos.common.remote.client.RpcClient#handleServerRequest is a protected method. Is there a better way to handle this here?

public void handleServerRequestSuccessResponse() {
when(serverRequestHandler.requestReply(any(Request.class)))
.thenReturn(NacosClientTestHelper.SUCCESS_RESPONSE);
for (Request request : nacosClientRequestList) {
Copy link
Contributor

Choose a reason for hiding this comment

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

when we need to run the same test with different arguments we use @ParameterizedTest

Copy link
Author

Choose a reason for hiding this comment

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

Okay, I will make changes here.

@Target(TYPE)
@Retention(RUNTIME)
@Documented
public @interface DoNotMock {
Copy link
Contributor

Choose a reason for hiding this comment

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

is this used anywhere?

Copy link
Author

@wl2027 wl2027 Dec 21, 2024

Choose a reason for hiding this comment

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

The class added here is to resolve a test compilation error in the nacos-client version 2.0.3 jar:

Compilation failed; see the compiler output below.
Error: Warning found, but specified -Werror
G:\temp.gradle\caches\modules-2\files-2.1\com.alibaba.nacos\nacos-client\2.0.3\a73c03b466a1f1565ee2b0e459c43046d6c8c15b\nacos-client-2.0.3.jar(/com/alibaba/nacos/shaded/com/google/common/util/concurrent/ListenableFuture.class): Warning: Unable to find class 'DoNotMock' annotation method 'value()': Can't find it com.alibaba.nacos.shaded.com.google.errorprone.annotations.DoNotMock class file.

This issue can be reproduced by removing the class file DoNotMock and then running ./gradlew :instrumentation:nacos-client-2.0.0:javaagent:test -PtestLatestDeps=true.

wl2027 and others added 3 commits December 21, 2024 13:00
- Updated version to support Nacos client version 2.0.0
- Default the plugin to be disabled
@wl2027 wl2027 requested a review from laurit December 21, 2024 08:49
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.

2 participants