Skip to content

Commit e7869cd

Browse files
authored
Merge pull request #154 from DataDog/ark/mongo_bytebuddy
Mongo Bytebuddy and Mongo Async
2 parents b4ba6d8 + 47b1eec commit e7869cd

File tree

21 files changed

+574
-287
lines changed

21 files changed

+574
-287
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,4 @@ Thumbs.db
5151
*/out
5252
dd-java-agent/integrations/*/out
5353
dd-trace-examples/*/out
54+
derby.log

dd-java-agent-ittests/dd-java-agent-ittests.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ dependencies {
1010
testCompile deps.testLogging
1111

1212
testCompile group: 'org.mongodb', name: 'mongo-java-driver', version: '3.4.2'
13+
testCompile group: 'org.mongodb', name: 'mongodb-driver-async', version: '3.4.2'
14+
// run embeded mongodb for integration testing
15+
testCompile group: 'de.flapdoodle.embed', name: 'de.flapdoodle.embed.mongo', version: '2.0.0'
16+
1317
testCompile group: 'org.eclipse.jetty', name: 'jetty-server', version: '9.4.1.v20170120'
1418
testCompile group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '9.4.1.v20170120'
1519
testCompile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: '8.0.41'

dd-java-agent-ittests/src/test/java/com/datadoghq/agent/instrumentation/annotation/TraceAnnotationsTest.java

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

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

5+
import com.datadoghq.agent.integration.TestUtils;
56
import com.datadoghq.agent.test.SayTracedHello;
67
import com.datadoghq.trace.DDBaseSpan;
78
import com.datadoghq.trace.DDTracer;
@@ -10,12 +11,10 @@
1011
import io.opentracing.util.GlobalTracer;
1112
import java.io.PrintWriter;
1213
import java.io.StringWriter;
13-
import java.lang.reflect.Field;
1414
import org.junit.Before;
1515
import org.junit.Test;
1616

1717
public class TraceAnnotationsTest {
18-
1918
private final ListWriter writer = new ListWriter();
2019
private final DDTracer tracer = new DDTracer(writer);
2120

@@ -24,14 +23,8 @@ public void beforeTest() throws Exception {
2423
Class.forName("com.datadoghq.agent.InstrumentationRulesManager")
2524
.getMethod("registerClassLoad")
2625
.invoke(null);
27-
try {
28-
GlobalTracer.register(tracer);
29-
} catch (final Exception e) {
30-
// Force it anyway using reflection
31-
final Field field = GlobalTracer.class.getDeclaredField("tracer");
32-
field.setAccessible(true);
33-
field.set(null, tracer);
34-
}
26+
TestUtils.registerOrReplaceGlobalTracer(tracer);
27+
3528
writer.start();
3629
assertThat(GlobalTracer.isRegistered()).isTrue();
3730
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package com.datadoghq.agent.integration;
2+
3+
import static com.datadoghq.agent.integration.MongoClientInstrumentationTest.MONGO_DB_NAME;
4+
import static com.datadoghq.agent.integration.MongoClientInstrumentationTest.MONGO_HOST;
5+
import static com.datadoghq.agent.integration.MongoClientInstrumentationTest.MONGO_PORT;
6+
7+
import com.datadoghq.trace.DDBaseSpan;
8+
import com.datadoghq.trace.DDTracer;
9+
import com.datadoghq.trace.writer.ListWriter;
10+
import com.mongodb.async.SingleResultCallback;
11+
import com.mongodb.async.client.MongoClient;
12+
import com.mongodb.async.client.MongoClients;
13+
import com.mongodb.async.client.MongoDatabase;
14+
import io.opentracing.tag.Tags;
15+
import java.net.InetAddress;
16+
import java.nio.ByteBuffer;
17+
import java.util.concurrent.atomic.AtomicBoolean;
18+
import org.bson.Document;
19+
import org.junit.AfterClass;
20+
import org.junit.Assert;
21+
import org.junit.BeforeClass;
22+
import org.junit.Test;
23+
24+
public class MongoAsyncClientInstrumentationTest {
25+
private static MongoClient client;
26+
private static final ListWriter writer = new ListWriter();
27+
private static final DDTracer tracer = new DDTracer(writer);
28+
29+
@BeforeClass
30+
public static void setup() throws Exception {
31+
TestUtils.registerOrReplaceGlobalTracer(tracer);
32+
MongoClientInstrumentationTest.startLocalMongo();
33+
client = MongoClients.create("mongodb://" + MONGO_HOST + ":" + MONGO_PORT);
34+
}
35+
36+
@AfterClass
37+
public static void destroy() throws Exception {
38+
if (null != client) {
39+
client.close();
40+
client = null;
41+
}
42+
MongoClientInstrumentationTest.stopLocalMongo();
43+
}
44+
45+
@Test
46+
public void asyncClientHasListener() {
47+
Assert.assertEquals(1, client.getSettings().getCommandListeners().size());
48+
Assert.assertEquals(
49+
"DDTracingCommandListener",
50+
client.getSettings().getCommandListeners().get(0).getClass().getSimpleName());
51+
}
52+
53+
@Test
54+
public void insertOperation() throws InterruptedException, Exception {
55+
MongoDatabase db = client.getDatabase(MONGO_DB_NAME);
56+
final String collectionName = "asyncCollection";
57+
final AtomicBoolean done = new AtomicBoolean(false);
58+
59+
db.createCollection(
60+
collectionName,
61+
new SingleResultCallback<Void>() {
62+
@Override
63+
public void onResult(Void result, Throwable t) {
64+
done.set(true);
65+
}
66+
});
67+
while (!done.get()) {
68+
Thread.sleep(1);
69+
}
70+
71+
db.getCollection(collectionName)
72+
.insertOne(
73+
new Document("foo", "bar"),
74+
new SingleResultCallback<Void>() {
75+
@Override
76+
public void onResult(final Void result, final Throwable t) {
77+
done.set(true);
78+
}
79+
});
80+
while (!done.get()) {
81+
Thread.sleep(1);
82+
}
83+
84+
done.set(false);
85+
db.getCollection(collectionName)
86+
.count(
87+
new SingleResultCallback<Long>() {
88+
@Override
89+
public void onResult(Long result, Throwable t) {
90+
Assert.assertEquals(1, result.longValue());
91+
done.set(true);
92+
}
93+
});
94+
95+
while (!done.get()) {
96+
Thread.sleep(1);
97+
}
98+
99+
// the final trace may still be reporting to the ListWriter,
100+
// but we're only testing the first trace.
101+
Assert.assertTrue(writer.getList().size() >= 1);
102+
103+
final String createCollectionQuery =
104+
"{ \"create\" : \"asyncCollection\", \"autoIndexId\" : \"?\", \"capped\" : \"?\" }";
105+
final DDBaseSpan<?> trace0 = writer.get(0).get(0);
106+
Assert.assertEquals("mongo.query", trace0.getOperationName());
107+
Assert.assertEquals(createCollectionQuery, trace0.getResourceName());
108+
Assert.assertEquals("mongodb", trace0.getType());
109+
Assert.assertEquals("mongo", trace0.getServiceName());
110+
111+
Assert.assertEquals("java-mongo", trace0.getTags().get(Tags.COMPONENT.getKey()));
112+
Assert.assertEquals(createCollectionQuery, trace0.getTags().get(Tags.DB_STATEMENT.getKey()));
113+
Assert.assertEquals(MONGO_DB_NAME, trace0.getTags().get(Tags.DB_INSTANCE.getKey()));
114+
Assert.assertEquals(MONGO_HOST, trace0.getTags().get(Tags.PEER_HOSTNAME.getKey()));
115+
Assert.assertEquals(
116+
ByteBuffer.wrap(InetAddress.getByName("127.0.0.1").getAddress()).getInt(),
117+
trace0.getTags().get(Tags.PEER_HOST_IPV4.getKey()));
118+
Assert.assertEquals(MONGO_PORT, trace0.getTags().get(Tags.PEER_PORT.getKey()));
119+
Assert.assertEquals("mongo", trace0.getTags().get(Tags.DB_TYPE.getKey()));
120+
}
121+
}
Lines changed: 106 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,116 @@
11
package com.datadoghq.agent.integration;
22

3-
import static org.assertj.core.api.Assertions.assertThat;
4-
3+
import com.datadoghq.trace.DDBaseSpan;
4+
import com.datadoghq.trace.DDTracer;
5+
import com.datadoghq.trace.writer.ListWriter;
56
import com.mongodb.MongoClient;
7+
import com.mongodb.client.MongoCollection;
8+
import com.mongodb.client.MongoDatabase;
9+
import de.flapdoodle.embed.mongo.*;
10+
import de.flapdoodle.embed.mongo.config.IMongodConfig;
11+
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
12+
import de.flapdoodle.embed.mongo.config.Net;
13+
import de.flapdoodle.embed.mongo.distribution.Version;
14+
import de.flapdoodle.embed.process.runtime.Network;
15+
import io.opentracing.tag.Tags;
16+
import java.net.InetAddress;
17+
import java.net.UnknownHostException;
18+
import java.nio.ByteBuffer;
19+
import org.bson.Document;
20+
import org.junit.AfterClass;
21+
import org.junit.Assert;
22+
import org.junit.BeforeClass;
623
import org.junit.Test;
724

825
public class MongoClientInstrumentationTest {
26+
public static final String MONGO_DB_NAME = "embedded";
27+
public static final String MONGO_HOST = "localhost";
28+
public static final int MONGO_PORT = 12345;
29+
private static MongodExecutable mongodExe;
30+
private static MongodProcess mongod;
31+
32+
private static MongoClient client;
33+
private static final ListWriter writer = new ListWriter();
34+
private static final DDTracer tracer = new DDTracer(writer);
35+
36+
public static void startLocalMongo() throws Exception {
37+
MongodStarter starter = MongodStarter.getDefaultInstance();
38+
39+
IMongodConfig mongodConfig =
40+
new MongodConfigBuilder()
41+
.version(Version.Main.PRODUCTION)
42+
.net(new Net(MONGO_HOST, MONGO_PORT, Network.localhostIsIPv6()))
43+
.build();
44+
45+
mongodExe = starter.prepare(mongodConfig);
46+
mongod = mongodExe.start();
47+
}
48+
49+
public static void stopLocalMongo() throws Exception {
50+
if (null != mongod) {
51+
mongod.stop();
52+
mongod = null;
53+
}
54+
if (null != mongodExe) {
55+
mongodExe.stop();
56+
mongodExe = null;
57+
}
58+
}
59+
60+
@BeforeClass
61+
public static void setup() throws Exception {
62+
TestUtils.registerOrReplaceGlobalTracer(tracer);
63+
startLocalMongo();
64+
65+
client = new MongoClient(MONGO_HOST, MONGO_PORT);
66+
}
67+
68+
@AfterClass
69+
public static void destroy() throws Exception {
70+
if (null != client) {
71+
client.close();
72+
client = null;
73+
}
74+
stopLocalMongo();
75+
}
76+
77+
@Test
78+
public void syncClientHasListener() {
79+
Assert.assertEquals(1, client.getMongoClientOptions().getCommandListeners().size());
80+
Assert.assertEquals(
81+
"DDTracingCommandListener",
82+
client.getMongoClientOptions().getCommandListeners().get(0).getClass().getSimpleName());
83+
}
984

1085
@Test
11-
public void test() {
12-
final MongoClient mongoClient = new MongoClient();
13-
14-
assertThat(mongoClient.getMongoClientOptions().getCommandListeners().size()).isEqualTo(1);
15-
assertThat(
16-
mongoClient
17-
.getMongoClientOptions()
18-
.getCommandListeners()
19-
.get(0)
20-
.getClass()
21-
.getSimpleName())
22-
.isEqualTo("DDTracingCommandListener");
23-
24-
mongoClient.close();
86+
public void insertOperation() throws UnknownHostException {
87+
MongoDatabase db = client.getDatabase(MONGO_DB_NAME);
88+
final String collectionName = "testCollection";
89+
db.createCollection(collectionName);
90+
MongoCollection<Document> collection = db.getCollection(collectionName);
91+
92+
collection.insertOne(new Document("foo", "bar"));
93+
94+
Assert.assertEquals(1, collection.count());
95+
96+
Assert.assertEquals(3, writer.getList().size());
97+
98+
final String createCollectionQuery =
99+
"{ \"create\" : \"testCollection\", \"autoIndexId\" : \"?\", \"capped\" : \"?\" }";
100+
final DDBaseSpan<?> trace0 = writer.get(0).get(0);
101+
Assert.assertEquals("mongo.query", trace0.getOperationName());
102+
Assert.assertEquals(createCollectionQuery, trace0.getResourceName());
103+
Assert.assertEquals("mongodb", trace0.getType());
104+
Assert.assertEquals("mongo", trace0.getServiceName());
105+
106+
Assert.assertEquals("java-mongo", trace0.getTags().get(Tags.COMPONENT.getKey()));
107+
Assert.assertEquals(createCollectionQuery, trace0.getTags().get(Tags.DB_STATEMENT.getKey()));
108+
Assert.assertEquals(MONGO_DB_NAME, trace0.getTags().get(Tags.DB_INSTANCE.getKey()));
109+
Assert.assertEquals(MONGO_HOST, trace0.getTags().get(Tags.PEER_HOSTNAME.getKey()));
110+
Assert.assertEquals(
111+
ByteBuffer.wrap(InetAddress.getByName("127.0.0.1").getAddress()).getInt(),
112+
trace0.getTags().get(Tags.PEER_HOST_IPV4.getKey()));
113+
Assert.assertEquals(MONGO_PORT, trace0.getTags().get(Tags.PEER_PORT.getKey()));
114+
Assert.assertEquals("mongo", trace0.getTags().get(Tags.DB_TYPE.getKey()));
25115
}
26116
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.datadoghq.agent.integration;
2+
3+
import io.opentracing.Tracer;
4+
import io.opentracing.util.GlobalTracer;
5+
import java.lang.reflect.Field;
6+
7+
public class TestUtils {
8+
public static void registerOrReplaceGlobalTracer(Tracer tracer) throws Exception {
9+
try {
10+
GlobalTracer.register(tracer);
11+
} catch (final Exception e) {
12+
// Force it anyway using reflection
13+
final Field field = GlobalTracer.class.getDeclaredField("tracer");
14+
field.setAccessible(true);
15+
field.set(null, tracer);
16+
}
17+
}
18+
}

dd-java-agent/dd-java-agent.gradle

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ dependencies {
3030
compile(project(':dd-java-agent:integrations:jms-2')) {
3131
transitive = false
3232
}
33+
compile(project(':dd-java-agent:integrations:mongo-3.1')) {
34+
transitive = false
35+
}
36+
compile(project(':dd-java-agent:integrations:mongo-async-3.3')) {
37+
transitive = false
38+
}
3339
compile(project(':dd-java-agent:integrations:servlet-2')) {
3440
transitive = false
3541
}
@@ -51,7 +57,6 @@ dependencies {
5157

5258
testCompile deps.testLogging
5359
testCompile deps.opentracingMock
54-
testCompile group: 'org.mongodb', name: 'mongo-java-driver', version: '3.4.2'
5560

5661
testCompile(project(path: ':dd-java-agent:integrations:helpers')) {
5762
transitive = false

0 commit comments

Comments
 (0)