@@ -8,15 +8,20 @@ import com.mongodb.event.CommandFailedEvent
88import com.mongodb.event.CommandListener
99import com.mongodb.event.CommandStartedEvent
1010import com.mongodb.event.CommandSucceededEvent
11+ import datadog.trace.api.sampling.PrioritySampling
12+ import datadog.trace.bootstrap.instrumentation.api.AgentSpan
1113import datadog.trace.core.DDSpan
1214import org.bson.BsonDocument
1315import org.bson.BsonString
1416import org.bson.Document
1517import spock.lang.Shared
1618
19+ import java.util.concurrent.ConcurrentLinkedQueue
20+
1721import static datadog.trace.agent.test.utils.PortUtils.UNUSABLE_PORT
1822import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace
1923import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_INSTANCE
24+ import static datadog.trace.api.config.TraceInstrumentationConfig.DB_DBM_PROPAGATION_MODE_MODE
2025import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan
2126
2227abstract class MongoJava31ClientTest extends MongoBaseTest {
@@ -231,6 +236,132 @@ abstract class MongoJava31ClientTest extends MongoBaseTest {
231236 // Unfortunately not caught by our instrumentation.
232237 assertTraces(0 ) {}
233238 }
239+
240+ def " test DBM propagation with sampled flag" () {
241+ setup :
242+ injectSysConfig(" dd." + DB_DBM_PROPAGATION_MODE_MODE , " full" )
243+ injectSysConfig(" service.name" , " test-mongo-service" )
244+ injectSysConfig(" dd.env" , " test" )
245+
246+ String collectionName = randomCollectionName()
247+ def capturedEvents = new ConcurrentLinkedQueue<CommandStartedEvent > ()
248+
249+ def dbmClient = new MongoClient (new ServerAddress (mongoDbContainer. getHost(), port),
250+ MongoClientOptions . builder()
251+ .description(" dbm-test-client" )
252+ .addCommandListener(new CommandListener () {
253+ @Override
254+ void commandStarted (CommandStartedEvent event ) {
255+ capturedEvents. add(event)
256+ }
257+
258+ @Override
259+ void commandSucceeded (CommandSucceededEvent event ) {}
260+
261+ @Override
262+ void commandFailed (CommandFailedEvent event ) {}
263+ })
264+ .build())
265+
266+ DDSpan setupSpan = null
267+ MongoCollection<Document > collection = runUnderTrace(" setup" ) {
268+ setupSpan = activeSpan() as DDSpan
269+ MongoDatabase db = dbmClient. getDatabase(databaseName)
270+ db. createCollection(collectionName)
271+ return db. getCollection(collectionName)
272+ }
273+ TEST_WRITER . waitUntilReported(setupSpan)
274+ TEST_WRITER . clear()
275+ capturedEvents. clear()
276+
277+ when :
278+ runUnderTrace(" dbm-test" ) {
279+ AgentSpan span = activeSpan() as AgentSpan
280+ span. setSamplingPriority(PrioritySampling . SAMPLER_KEEP , 0 )
281+ collection. insertOne(new Document (" test" , " value" ))
282+ }
283+
284+ then :
285+ // Find the insert command event
286+ def insertEvent = capturedEvents. find { it. commandName == " insert" }
287+ insertEvent != null
288+ def command = insertEvent. command
289+ command. containsKey(' $comment' )
290+ def comment = command. getString(' $comment' ). value
291+
292+ // Verify comment contains DBM tags
293+ comment. contains(" dddbs='test-mongo-service'" )
294+ comment. contains(" dde='test'" )
295+
296+ // Verify traceparent has sampled flag (01)
297+ comment ==~ / .*ddtp='00-[0-9a-f]{32}-[0-9a-f]{16}-01'.*/
298+
299+ cleanup :
300+ dbmClient?. close()
301+ }
302+
303+ def " test DBM propagation with not sampled flag" () {
304+ setup :
305+ injectSysConfig(" dd." + DB_DBM_PROPAGATION_MODE_MODE , " full" )
306+ injectSysConfig(" service.name" , " test-mongo-service" )
307+ injectSysConfig(" dd.env" , " test" )
308+
309+ String collectionName = randomCollectionName()
310+ def capturedEvents = new ConcurrentLinkedQueue<CommandStartedEvent > ()
311+
312+ def dbmClient = new MongoClient (new ServerAddress (mongoDbContainer. getHost(), port),
313+ MongoClientOptions . builder()
314+ .description(" dbm-test-client" )
315+ .addCommandListener(new CommandListener () {
316+ @Override
317+ void commandStarted (CommandStartedEvent event ) {
318+ capturedEvents. add(event)
319+ }
320+
321+ @Override
322+ void commandSucceeded (CommandSucceededEvent event ) {}
323+
324+ @Override
325+ void commandFailed (CommandFailedEvent event ) {}
326+ })
327+ .build())
328+
329+ DDSpan setupSpan = null
330+ MongoCollection<Document > collection = runUnderTrace(" setup" ) {
331+ setupSpan = activeSpan() as DDSpan
332+ MongoDatabase db = dbmClient. getDatabase(databaseName)
333+ db. createCollection(collectionName)
334+ return db. getCollection(collectionName)
335+ }
336+ TEST_WRITER . waitUntilReported(setupSpan)
337+ TEST_WRITER . clear()
338+ capturedEvents. clear()
339+
340+ when :
341+ runUnderTrace(" dbm-test" ) {
342+ AgentSpan span = activeSpan() as AgentSpan
343+ span. setSamplingPriority(PrioritySampling . SAMPLER_DROP , 0 )
344+ collection. insertOne(new Document (" test" , " value" ))
345+ }
346+
347+ then :
348+ // Find the insert command event
349+ def insertEvent = capturedEvents. find { it. commandName == " insert" }
350+ insertEvent != null
351+ def command = insertEvent. command
352+ command. containsKey(' $comment' )
353+ def comment = command. getString(' $comment' ). value
354+
355+ // Verify comment contains DBM tags
356+ comment. contains(" dddbs='test-mongo-service'" )
357+ comment. contains(" dde='test'" )
358+
359+ // Verify traceparent has not sampled flag (00)
360+ comment ==~ / .*ddtp='00-[0-9a-f]{32}-[0-9a-f]{16}-00'.*/
361+
362+ cleanup :
363+ dbmClient?. close()
364+ }
234365}
235366
236367class MongoJava31ClientV0Test extends MongoJava31ClientTest {
0 commit comments