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

Adds support for org.mongodb:mongodb-driver-core v5 #1431

Merged
merged 3 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions instrumentation/mongodb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,23 @@

<main.basedir>${project.basedir}/../..</main.basedir>

<mongodb-driver.version>3.12.14</mongodb-driver.version>
<mongodb-driver.version>5.0.1</mongodb-driver.version>
<old-mongodb-driver.version>3.11.0</old-mongodb-driver.version>
reta marked this conversation as resolved.
Show resolved Hide resolved
</properties>

<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<artifactId>mongodb-driver-core</artifactId>
<version>${mongodb-driver.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>${mongodb-driver.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>brave-tests</artifactId>
Expand All @@ -55,6 +62,38 @@
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-invoker-plugin</artifactId>
</plugin>
<plugin>
<groupId>de.qaware.maven</groupId>
<artifactId>go-offline-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>resolve-dependencies</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- Add dependencies specific to invoker tests so that they cache on go-offline -->
<dynamicDependencies>
<DynamicDependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<version>${old-mongodb-driver.version}</version>
<repositoryType>MAIN</repositoryType>
<type>jar</type>
</DynamicDependency>
</dynamicDependencies>
</configuration>
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>release</id>
Expand Down
2 changes: 2 additions & 0 deletions instrumentation/mongodb/src/it/mongodb_v3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# mongodb_v3
This tests that MongoDBTracing can be used with mongodb <5
120 changes: 120 additions & 0 deletions instrumentation/mongodb/src/it/mongodb_v3/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright 2013-2024 The OpenZipkin Authors

Licensed 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>@project.groupId@</groupId>
<artifactId>mongodb_v3</artifactId>
<version>@project.version@</version>
<name>mongodb_v3</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.resourceEncoding>UTF-8</project.build.resourceEncoding>

<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<version>@old-mongodb-driver.version@</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>brave-instrumentation-mongodb</artifactId>
<version>@project.version@</version>
</dependency>

<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>brave-tests</artifactId>
<version>@project.version@</version>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>@junit-jupiter.version@</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>@mockito.version@</version>
</dependency>
<!-- Route jul over log4j2 during integration tests -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>@log4j.version@</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>@log4j.version@</version>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>@testcontainers.version@</version>
</dependency>
</dependencies>

<build>
<sourceDirectory>@project.build.testSourceDirectory@</sourceDirectory>
<testResources>
<testResource>
<directory>@project.basedir@/src/test/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>@maven-compiler-plugin.version@</version>
<configuration>
<includes>
<include>**/IT*.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<!-- Use surefire to run the ITs until someone figures out how to get invoker to run
failsafe -->
<artifactId>maven-surefire-plugin</artifactId>
<version>@maven-surefire-plugin.version@</version>
<configuration>
<failIfNoTests>true</failIfNoTests>
<includes>
<include>**/IT*.java</include>
</includes>
<!-- Try to prevent flakes in CI -->
<reuseForks>false</reuseForks>
<!-- workaround to SUREFIRE-1831 -->
<useModulePath>false</useModulePath>
<!-- Ensure scope leak cause ends up in the console -->
<trimStackTrace>false</trimStackTrace>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright 2013-2024 The OpenZipkin Authors
*
* Licensed 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 brave.mongodb_v3;

class ITMongoDBTracing extends brave.mongodb.ITMongoDBTracing {
}
104 changes: 104 additions & 0 deletions instrumentation/mongodb/src/main/java/brave/mongodb/MongoDBDriver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright 2013-2024 The OpenZipkin Authors
*
* Licensed 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 brave.mongodb;

import brave.Span;
import com.mongodb.ServerAddress;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;

import static brave.internal.Throwables.propagateIfFatal;

/**
* Access to MongoDB version-specific features
*
* <p>Originally designed by OkHttp team, derived from {@code okhttp3.internal.platform.Platform}
*/
class MongoDBDriver {
private static final MongoDBDriver MONGO_DB_DRIVER = findMongoDBDriver();

/** adds the remote IP and port to the span */
void setRemoteIpAndPort(Span span, ServerAddress address) {
// default to no-op instead of crash on future drift
}

MongoDBDriver() {
}

public static MongoDBDriver get() {
return MONGO_DB_DRIVER;
}

/**
* Attempt to match the driver version from two known patterns:
*
* <ol>
* <li>org.mongodb:mongodb-driver - 3.x</li>
* <li>org.mongodb:mongodb-driver-core - 5.x</li>
* </ol>
*/
private static MongoDBDriver findMongoDBDriver() {
try {
Method getHost = ServerAddress.class.getMethod("getHost");
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure if it is worth the effort, but we could use MethodHandles instead of reflection (since this is what reflection is using in latest JDKs under the hood).

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess we can.. technically the old mongodb driver had a floor JRE of 1.6, but I don't think it is widely used enough in that config to matter. If someone complains, we can revert it.

Method getPort = ServerAddress.class.getMethod("getPort");
return new Driver5x(getHost, getPort);
} catch (NoSuchMethodException e) {
// not 5.x
}
try {
return new Driver3x(ServerAddress.class.getMethod("getSocketAddress"));
} catch (NoSuchMethodException e) {
// unknown version
}

// Unknown
return new MongoDBDriver();
}

static final class Driver3x extends MongoDBDriver {
final Method getSocketAddress;

Driver3x(Method getSocketAddress) {
this.getSocketAddress = getSocketAddress;
}

@Override void setRemoteIpAndPort(Span span, ServerAddress serverAddress) {
try {
InetSocketAddress socketAddress =
(InetSocketAddress) getSocketAddress.invoke(serverAddress);
span.remoteIpAndPort(socketAddress.getAddress().getHostAddress(), socketAddress.getPort());
} catch (Throwable t) {
propagateIfFatal(t);
}
}
}

static final class Driver5x extends MongoDBDriver {
final Method getHost, getPort;

Driver5x(Method getHost, Method getPort) {
this.getHost = getHost;
this.getPort = getPort;
}

@Override void setRemoteIpAndPort(Span span, ServerAddress serverAddress) {
try {
span.remoteIpAndPort((String) getHost.invoke(serverAddress),
(int) getPort.invoke(serverAddress));
} catch (Throwable t) {
propagateIfFatal(t);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2023 The OpenZipkin Authors
* Copyright 2013-2024 The OpenZipkin Authors
*
* Licensed 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
Expand Down Expand Up @@ -35,7 +35,7 @@
/**
* A MongoDB command listener that will report via Brave how long each command takes and other
* information about the commands.
*
* <p>
* See <a href="https://github.com/openzipkin/brave/blob/master/instrumentation/mongodb/RATIONALE.md">RATIONALE.md</a>
* for implementation notes.
*/
Expand Down Expand Up @@ -87,13 +87,7 @@ final class TraceMongoCommandListener implements CommandListener {
span.tag("mongodb.cluster_id", connectionId.getServerId().getClusterId().getValue());
}

try {
InetSocketAddress socketAddress =
connectionDescription.getServerAddress().getSocketAddress();
span.remoteIpAndPort(socketAddress.getAddress().getHostAddress(), socketAddress.getPort());
} catch (MongoSocketException ignored) {

}
MongoDBDriver.get().setRemoteIpAndPort(span, connectionDescription.getServerAddress());
}

span.start();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
@Tag("docker")
@Testcontainers(disabledWithoutDocker = true)
@Timeout(60)
class ITMongoDBTracing extends ITRemote {
public class ITMongoDBTracing extends ITRemote { // public for invoker test
static final String DATABASE_NAME = "myDatabase";
static final String COLLECTION_NAME = "myCollection";
static final String INVALID_COLLECTION_NAME = "?.$";
Expand Down
Loading
Loading