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

MongoDB 4 driver instrumentation #2046

Merged
merged 12 commits into from
Jan 25, 2021
Merged

Conversation

malafeev
Copy link
Contributor

@malafeev malafeev commented Jan 14, 2021

Signed-off-by: Sergei Malafeev <sergei@malafeev.org>
Sergei Malafeev added 2 commits January 15, 2021 00:59
Signed-off-by: Sergei Malafeev <sergei@malafeev.org>
Signed-off-by: Sergei Malafeev <sergei@malafeev.org>
pass {
group = "org.mongodb"
module = "mongodb-driver-core"
// this instrumentation is backwards compatible with early versions of the new API that shipped in 3.7
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure if this complicates matters, but the upcoming 4.2.0 release will allow construction of a legacy com.mongodb.MongoClient with a com.mongodb.MongoClientSettings. See mongodb/mongo-java-driver@15b70cf#diff-9edd83ced1b6f12502db95a96af13ed57e647efd84d2ddf5d040af4a653fb1edR211 (you have to expand the MongoClient diffs as they are large)

@Advice.OnMethodEnter(suppress = Throwable.class)
public static void injectTraceListener(
@Advice.This MongoClientSettings.Builder builder,
@Advice.FieldValue("commandListeners") List<CommandListener> commandListeners) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We generally prefer to use public API instead of fields to reduce the chance that testLatestDeps will fail when implementation details change :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it is consistent with all other mongo versions instrumentations, I updated matcher.

.getClass()
.getName()
.startsWith("io.opentelemetry.")) {
// we'll replace it, since it could be the 3.x async driver which is bundled with driver 4
Copy link
Contributor

Choose a reason for hiding this comment

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

So we'd want to filter out calls to the API to add listeners rather than filter here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed that code

| IllegalAccessException
| InvocationTargetException
| NoSuchMethodException ignored) {
}
Copy link
Contributor

Choose a reason for hiding this comment

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

What happens if this is null, is it ok?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no, null is not ok, we will get NPE later. But null shouldn't happen because constructor with boolean exists prior version 4.0. And since 4.0 there is a builder only.

settings.gradle Outdated Show resolved Hide resolved
Comment on lines 64 to 72
if (!commandListeners.isEmpty()
&& commandListeners
.get(commandListeners.size() - 1)
.getClass()
.getName()
.startsWith("io.opentelemetry.")) {
// we'll replace it, since it could be the 3.x async driver which is bundled with driver 4
commandListeners.remove(commandListeners.size() - 1);
}
Copy link
Member

Choose a reason for hiding this comment

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

Is the code above needed? I think the code below will prevent double registration?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed

Sergei Malafeev and others added 5 commits January 15, 2021 16:55
…elemetry/javaagent/instrumentation/mongo/v4/MongoClientInstrumentationModule.java

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
…elemetry/javaagent/instrumentation/mongo/v4/MongoClientInstrumentationModule.java

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
Signed-off-by: Sergei Malafeev <sergei@malafeev.org>
Signed-off-by: Sergei Malafeev <sergei@malafeev.org>
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void injectTraceListener(
@Advice.This MongoClientSettings.Builder builder,
@Advice.FieldValue("commandListeners") List<CommandListener> commandListeners) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for using the public method - for suppression we would want to instrument addCommandListener instead to avoid accessing this private field. However, we've generally been skipping handling duplicate registration in an effort to come with a more general pattern so you don't have to worry about it either if it's tedious.

@malafeev
Copy link
Contributor Author

malafeev commented Jan 21, 2021

Is anything else should be done in this PR?
I ported instrumentation from DD and made it similar to mongo-3.7 instrumentation.

@anuraaga
Copy link
Contributor

@malafeev Do you think you can address #2046 (comment)? We should avoid accessing the private field. I believe you changed to instrumenting addCommandListener but my intention was to keep instrumenting build, but call addCommandListener from inside instead of accessing the private variable. Currently we'll run our instrumentation every time a user executes addCommandListener which is weird.

@malafeev
Copy link
Contributor Author

@anuraaga , no, as I understand, we intercept only build method:
https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/2046/files#diff-68a7a03ca69546307dd8eda75056b354fc429e9f87a5ec3602a3f9a4816d8294R64

    @Override
    public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
      return singletonMap(
          isMethod().and(isPublic()).and(named("build")).and(takesArguments(0)),
          MongoClientInstrumentationModule.class.getName() + "$MongoClientAdvice");
    }

Copy link
Contributor

@anuraaga anuraaga left a comment

Choose a reason for hiding this comment

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

@malafeev sorry, was reading the type matcher, not the transformer!

In other agents we aren't really doing any deduping, so we could possibly remove it here too, but I guess if it causes a problem with testLatestDeps we could do so later too.

Comment on lines 10 to 11
versions = "[3.7,)"
assertInverse = true
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would be cleaner to

Suggested change
versions = "[3.7,)"
assertInverse = true
versions = "[4.0,)"

@trask @mateuszrzeszutek WDYT?

Copy link
Contributor Author

@malafeev malafeev Jan 22, 2021

Choose a reason for hiding this comment

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

but before 4.0 non-uber jars have also been published, that's why 3.7 is here

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't follow, sorry. If this module is meant for mongo 4.0+, then why do we want to verify muzzle for 3.7?

Copy link
Contributor Author

@malafeev malafeev Jan 25, 2021

Choose a reason for hiding this comment

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

there are 2 types of mongo jars:

  1. uber jar. But it doesn't exist since version 4.0.
  2. non-uber jar which exists since version 3.7 up to current version.

DD named module to support non-uber jar mongo-4.
Should I rename this one to mongo-non-uber-3.7? There is already mongo-3.7 module to support uber jars.

Copy link
Contributor

Choose a reason for hiding this comment

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

Wait, so actual instrumentations are the same, right? The only difference is, essentially, the collection of packages used for testing? So this is not a new module for instrumentation, but a new module for testing? Like glassfish-testing?

Copy link
Contributor

Choose a reason for hiding this comment

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

How does it differ from already existing io.opentelemetry.javaagent.instrumentation.mongo.v3_7.MongoClientInstrumentationModule? Instrumentation looks the same to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, instrumentation looks the same.
but mongo-3.7 will not work for mongodb-driver-core 3.7 jar because of muzzle.
mongo-3.7 depends on mongo-java-driver
mongo-4.0 depends on mongodb-driver-core

Copy link
Member

Choose a reason for hiding this comment

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

Instead of copying the 3.7 instrumentation, would it be possible to add another muzzle task there and just move the tests to a separate 4.0/uberjar testing module?

Copy link
Member

Choose a reason for hiding this comment

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

Adding

  pass {
    group = "org.mongodb"
    module = "mongodb-driver-core"
    // this instrumentation is backwards compatible with early versions of the new API that shipped in 3.7
    // the legacy API instrumented in mongo-3.1 continues to be shipped in 4.x, but doesn't conflict here
    // because they are triggered by different types: MongoClientSettings(new) vs MongoClientOptions(legacy)
    versions = "[3.7,)"
    extraDependency "org.mongodb:bson:3.7.0"
    assertInverse = true
  }

to the 3.7 muzzle task definition should cover all the uberjar releases.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Signed-off-by: Sergei Malafeev <sergei@malafeev.org>
Sergei Malafeev added 3 commits January 22, 2021 20:48
Signed-off-by: Sergei Malafeev <sergei@malafeev.org>
Signed-off-by: Sergei Malafeev <sergei@malafeev.org>
@iNikem iNikem merged commit bbcbeb5 into open-telemetry:master Jan 25, 2021
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.

None yet

7 participants