Skip to content

Commit

Permalink
Adds support for org.mongodb:mongodb-driver-core v5 (#1431)
Browse files Browse the repository at this point in the history
Signed-off-by: Adrian Cole <adrian@tetrate.io>
  • Loading branch information
codefromthecrypt authored Apr 10, 2024
1 parent fe3c8b4 commit ef6fbbd
Show file tree
Hide file tree
Showing 12 changed files with 393 additions and 59 deletions.
8 changes: 8 additions & 0 deletions instrumentation/mongodb/RATIONALE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# brave-instrumentation-mongodb rationale

## Floor JRE version

MongoDB client 3.x has a floor JRE version of 1.6, while 4.x moved to 8. We
test on MongoDB client 3.x, despite it being 1.6 bytecode. This is a
maintenance compromise beginning with MongoDB 5.x. We believe this will be less
significant than more widely used libraries, such as Servlet or OkHttp, which
could be used in old environments or Android.

## Default data policy
We tried to make the default data policy similar to other instrumentation, such as MySQL, and also current practice
from existing sites. Like other instrumentation, the policy is intentionally conservative, in efforts to avoid large
Expand Down
51 changes: 45 additions & 6 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>
<floor-mongodb-driver.version>3.11.0</floor-mongodb-driver.version>
</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,14 +62,46 @@
</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>${floor-mongodb-driver.version}</version>
<repositoryType>MAIN</repositoryType>
<type>jar</type>
</DynamicDependency>
</dynamicDependencies>
</configuration>
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>release</id>
<properties>
<!-- mongodb-driver 3.x requires Java 6 -->
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
<maven.compiler.release>6</maven.compiler.release>
<!-- mongodb-driver 3.x requires Java 6, but we only support 7 -->
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.release>7</maven.compiler.release>
</properties>
<build>
<plugins>
Expand Down
2 changes: 2 additions & 0 deletions instrumentation/mongodb/src/it/mongodb_floor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# mongodb_floor
This tests that MongoDBTracing can be used with mongodb <5
120 changes: 120 additions & 0 deletions instrumentation/mongodb/src/it/mongodb_floor/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_floor</artifactId>
<version>@project.version@</version>
<name>mongodb_floor</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>@floor-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_floor;

class ITMongoDBTracing extends brave.mongodb.ITMongoDBTracing {
}
112 changes: 112 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,112 @@
/*
* 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.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
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() {
MethodHandles.Lookup lookup = MethodHandles.lookup();
try {
MethodHandle getHost =
lookup.findVirtual(ServerAddress.class, "getHost", MethodType.methodType(String.class));
MethodHandle getPort =
lookup.findVirtual(ServerAddress.class, "getPort", MethodType.methodType(int.class));
return new Driver5x(getHost, getPort);
} catch (NoSuchMethodException | IllegalAccessException e) {
// not 5.x
}
try {
MethodHandle getSocketAddress = lookup.findVirtual(ServerAddress.class, "getSocketAddress",
MethodType.methodType(InetSocketAddress.class));
return new Driver3x(getSocketAddress);
} catch (NoSuchMethodException | IllegalAccessException e) {
// unknown version
}

// Unknown
return new MongoDBDriver();
}

static final class Driver3x extends MongoDBDriver {
final MethodHandle getSocketAddress;

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

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

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

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

@Override void setRemoteIpAndPort(Span span, ServerAddress serverAddress) {
try {
String host = (String) getHost.invokeExact(serverAddress);
int port = (int) getPort.invokeExact(serverAddress);
span.remoteIpAndPort(host, port);
} 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
Loading

0 comments on commit ef6fbbd

Please sign in to comment.