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 OpenTracing Command Listener to MongoDB client #13863

Merged
merged 1 commit into from
Apr 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 6 additions & 0 deletions bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<opentracing-concurrent.version>0.2.0</opentracing-concurrent.version>
<opentracing-jdbc.version>0.0.12</opentracing-jdbc.version>
<opentracing-kafka.version>0.1.15</opentracing-kafka.version>
<opentracing-mongo.version>0.1.5</opentracing-mongo.version>
<opentelemetry.version>1.0.1</opentelemetry.version>
<opentelemetry-alpha.version>1.0.1-alpha</opentelemetry-alpha.version>
<jaeger.version>0.34.3</jaeger.version>
Expand Down Expand Up @@ -2830,6 +2831,11 @@
<artifactId>opentracing-kafka-client</artifactId>
<version>${opentracing-kafka.version}</version>
</dependency>
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-mongo-common</artifactId>
<version>${opentracing-mongo.version}</version>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
Expand Down
6 changes: 6 additions & 0 deletions docs/src/main/asciidoc/mongodb.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,12 @@ This behavior must first be enabled by setting the `quarkus.mongodb.metrics.enab
So when you access the `/q/metrics` endpoint of your application you will have information about the connection pool status.
When using link:microprofile-metrics[SmallRye Metrics], connection pool metrics will be available under the `vendor` scope.

== Tracing

If you are using the `quarkus-smallrye-opentracing` extension, `quarkus-mongodb-client` can register traces about the commands executed.
This behavior must be enabled by setting the `quarkus.mongodb.tracing.enabled` property to `true` in your `application.properties` and adding the dependency `io.opentracing.contrib:opentracing-mongo-common` to your pom.xml (for more info read the link:opentracing#mongodb-client[OpenTracing - MongoDB client] section).

Read the link:opentracing[OpenTracing] guide, for how to configure OpenTracing and how to use the Jaeger tracer.

== The legacy client

Expand Down
22 changes: 22 additions & 0 deletions docs/src/main/asciidoc/opentracing.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,28 @@ mp.messaging.incoming.prices.interceptor.classes=io.opentracing.contrib.kafka.Tr

NOTE: `interceptor.classes` accept a list of classes separated by a comma.


=== MongoDB client

The https://github.com/opentracing-contrib/java-mongo-driver[Mongo Driver instrumentation] will add a span for each command executed by your application. To enable it, add the following dependency to your pom.xml:

[source, xml]
----
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-mongo-common</artifactId>
</dependency>
----

It contains the OpenTracing CommandListener that will be registered on the configuration of the mongo client.
Following the link:mongodb[MongoDB guide], the command listener will be registered defining the config property as follows:

[source, properties]
----
# Enable tracing commands in mongodb client
quarkus.mongodb.tracing.enabled=true
----

[[configuration-reference]]
== Jaeger Configuration Reference

Expand Down
21 changes: 21 additions & 0 deletions extensions/mongodb-client/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,27 @@
<artifactId>quarkus-resteasy-deployment</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-opentracing-deployment</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-mongo-common</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.opentracing</groupId>
<artifactId>opentracing-mock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.opentracing</groupId>
<artifactId>opentracing-util</artifactId>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ public class MongoClientBuildTimeConfig {
@ConfigItem(name = "metrics.enabled")
public boolean metricsEnabled;

/**
* Whether or not tracing spans of driver commands are sent in case the smallrye-opentracing extension is present.
*/
@ConfigItem(name = "tracing.enabled")
public boolean tracingEnabled;

/**
* If set to true, the default clients will always be created even if there are no injection points that use them
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
import io.quarkus.arc.processor.BuildExtension;
import io.quarkus.arc.processor.DotNames;
import io.quarkus.arc.processor.InjectionPointInfo;
import io.quarkus.deployment.Capabilities;
import io.quarkus.deployment.Capability;
import io.quarkus.deployment.Feature;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
Expand All @@ -59,6 +61,7 @@
import io.quarkus.smallrye.health.deployment.spi.HealthBuildItem;

public class MongoClientProcessor {
private static final String MONGODB_TRACING_COMMANDLISTENER_CLASSNAME = "io.quarkus.mongodb.tracing.MongoTracingCommandListener";
private static final DotName LEGACY_MONGO_CLIENT_ANNOTATION = DotName
.createSimple(io.quarkus.mongodb.runtime.MongoClientName.class.getName());
private static final DotName MONGO_CLIENT_ANNOTATION = DotName.createSimple(MongoClientName.class.getName());
Expand Down Expand Up @@ -93,10 +96,16 @@ BsonDiscriminatorBuildItem collectBsonDiscriminators(CombinedIndexBuildItem inde
}

@BuildStep
CommandListenerBuildItem collectCommandListeners(CombinedIndexBuildItem indexBuildItem) {
CommandListenerBuildItem collectCommandListeners(CombinedIndexBuildItem indexBuildItem,
MongoClientBuildTimeConfig buildTimeConfig, Capabilities capabilities) {
Collection<ClassInfo> commandListenerClasses = indexBuildItem.getIndex()
.getAllKnownImplementors(DotName.createSimple(CommandListener.class.getName()));
List<String> names = commandListenerClasses.stream().map(ci -> ci.name().toString()).collect(Collectors.toList());
List<String> names = commandListenerClasses.stream()
.map(ci -> ci.name().toString())
.collect(Collectors.toList());
if (buildTimeConfig.tracingEnabled && capabilities.isPresent(Capability.OPENTRACING)) {
names.add(MONGODB_TRACING_COMMANDLISTENER_CLASSNAME);
}
return new CommandListenerBuildItem(names);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package io.quarkus.mongodb;

import static org.assertj.core.api.Assertions.assertThat;

import javax.inject.Inject;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import com.mongodb.client.MongoClient;

import io.opentracing.mock.MockSpan;
import io.opentracing.mock.MockTracer;
import io.opentracing.util.GlobalTracer;
import io.opentracing.util.GlobalTracerTestUtil;
import io.quarkus.mongodb.tracing.MongoTracingCommandListener;
import io.quarkus.test.QuarkusUnitTest;

/**
* Test the inclusion and config of the {@link MongoTracingCommandListener}.
*
* @see io.quarkus.smallrye.opentracing.deployment.TracingTest
*/
public class MongoTracingCommandListenerTest extends MongoTestBase {

@Inject
MongoClient client;

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.setArchiveProducer(
() -> ShrinkWrap.create(JavaArchive.class).addClasses(MongoTestBase.class))
.withConfigurationResource("application-tracing-mongo.properties");

static MockTracer mockTracer = new MockTracer();
static {
GlobalTracer.register(mockTracer);
}

@BeforeEach
public void before() {
mockTracer.reset();
}

@AfterAll
public static void afterAll() {
GlobalTracerTestUtil.resetGlobalTracer();
}

@AfterEach
void cleanup() {
if (client != null) {
client.close();
}
}

@Test
void testClientInitialization() {
assertThat(mockTracer.finishedSpans()).isEmpty();

assertThat(client.listDatabaseNames().first()).isNotEmpty();

assertThat(mockTracer.finishedSpans()).hasSize(1);
MockSpan span = mockTracer.finishedSpans().get(0);
assertThat(span.operationName()).isEqualTo("listDatabases");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
quarkus.mongodb.connection-string=mongodb://localhost:27018
quarkus.mongodb.tracing.enabled=true


quarkus.jaeger.enabled=true
quarkus.jaeger.service-name=tracing-test
quarkus.jaeger.sampler-param=1
quarkus.jaeger.sampler-type=const
11 changes: 11 additions & 0 deletions extensions/mongodb-client/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@
<optional>true</optional>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-opentracing</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-mongo-common</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>svm</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.quarkus.mongodb.tracing;

import com.mongodb.event.CommandFailedEvent;
import com.mongodb.event.CommandListener;
import com.mongodb.event.CommandStartedEvent;
import com.mongodb.event.CommandSucceededEvent;

import io.opentracing.contrib.mongo.common.TracingCommandListener;
import io.opentracing.util.GlobalTracer;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;

/**
* Command Listener for Mongo client delegated to {@link TracingCommandListener}.
*
*/
public class MongoTracingCommandListener implements CommandListener {

private static final Logger LOGGER = LoggerFactory.getLogger(MongoTracingCommandListener.class);

private TracingCommandListener delegate;

public MongoTracingCommandListener() {
this.delegate = new TracingCommandListener.Builder(GlobalTracer.get()).build();
loicmathieu marked this conversation as resolved.
Show resolved Hide resolved
LOGGER.debug("TracingCommandListener Delegate created");
}

@Override
public void commandStarted(CommandStartedEvent event) {
LOGGER.trace("commandStarted event " + event.getCommandName());
delegate.commandStarted(event);
}

@Override
public void commandFailed(CommandFailedEvent event) {
LOGGER.trace("commandFailed event " + event.getCommandName());
delegate.commandFailed(event);
}

@Override
public void commandSucceeded(CommandSucceededEvent event) {
LOGGER.trace("commandSucceded event " + event.getCommandName());
delegate.commandSucceeded(event);
}

}