Skip to content

Commit 94e2dfa

Browse files
tlhunteruurien
authored andcommitted
postgres: DBM full service fallback w/ prepared statements (#3186)
- when DBM is set to full service - the DBM comment falls back to service mode - but only when sending a prepared statement - without this, each prepared statement query is technically different - this causes the pg library to fail as it does an exact string check of the query - ideally the pg library would somehow parse out and not consider comments - at any rate this brings parity with other tracer implementations - see brianc/node-postgres#2735 - previously attempted in 0ff9465
1 parent f1ce839 commit 94e2dfa

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

packages/datadog-plugin-pg/src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class PGPlugin extends DatabasePlugin {
2727
}
2828
})
2929

30-
query.text = this.injectDbmQuery(query.text, service)
30+
query.text = this.injectDbmQuery(query.text, service, !!query.name)
3131
}
3232
}
3333

packages/datadog-plugin-pg/test/index.spec.js

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ describe('Plugin', () => {
271271
})
272272
})
273273
})
274+
274275
describe('with DBM propagation enabled with service using plugin configurations', () => {
275276
before(() => {
276277
return agent.load('pg', [{ dbmPropagationMode: 'service', service: () => 'serviced' }])
@@ -318,6 +319,7 @@ describe('Plugin', () => {
318319
}
319320
}
320321
})
322+
321323
it('trace query resource should not be changed when propagation is enabled', done => {
322324
agent.use(traces => {
323325
expect(traces[0][0]).to.have.property('resource', 'SELECT $1::text as message')
@@ -331,15 +333,18 @@ describe('Plugin', () => {
331333
})
332334
})
333335
})
336+
334337
describe('DBM propagation should handle special characters', () => {
335338
let clientDBM
339+
336340
before(() => {
337341
return agent.load('pg', [{ dbmPropagationMode: 'service', service: '~!@#$%^&*()_+|??/<>' }])
338342
})
339343

340344
after(() => {
341345
return agent.close({ ritmReset: false })
342346
})
347+
343348
beforeEach(done => {
344349
pg = require(`../../../versions/pg@${version}`).get()
345350

@@ -352,6 +357,7 @@ describe('Plugin', () => {
352357

353358
clientDBM.connect(err => done(err))
354359
})
360+
355361
it('DBM propagation should handle special characters', done => {
356362
clientDBM.query('SELECT $1::text as message', ['Hello world!'], (err, result) => {
357363
if (err) return done(err)
@@ -373,15 +379,18 @@ describe('Plugin', () => {
373379
}
374380
})
375381
})
382+
376383
describe('with DBM propagation enabled with full using tracer configurations', () => {
377384
const tracer = require('../../dd-trace')
378385
let seenTraceParent
379386
let seenTraceId
380387
let seenSpanId
381388
let originalWrite
389+
382390
before(() => {
383391
return agent.load('pg')
384392
})
393+
385394
beforeEach(done => {
386395
pg = require(`../../../versions/pg@${version}`).get()
387396

@@ -409,9 +418,11 @@ describe('Plugin', () => {
409418
return originalWrite.apply(this, arguments)
410419
}
411420
})
421+
412422
afterEach(() => {
413423
net.Socket.prototype.write = originalWrite
414424
})
425+
415426
it('query text should contain traceparent', done => {
416427
agent.use(traces => {
417428
const traceId = traces[0][0].trace_id.toString(16).padStart(32, '0')
@@ -428,6 +439,7 @@ describe('Plugin', () => {
428439
})
429440
})
430441
})
442+
431443
it('query should inject _dd.dbm_trace_injected into span', done => {
432444
agent.use(traces => {
433445
expect(traces[0][0].meta).to.have.property('_dd.dbm_trace_injected', 'true')
@@ -442,6 +454,7 @@ describe('Plugin', () => {
442454
})
443455
})
444456
})
457+
445458
it('service should default to tracer service name', done => {
446459
tracer
447460
agent.use(traces => {
@@ -458,12 +471,14 @@ describe('Plugin', () => {
458471
})
459472
})
460473
})
474+
461475
describe('DBM propagation enabled with full should handle query config objects', () => {
462476
const tracer = require('../../dd-trace')
463477

464478
before(() => {
465479
return agent.load('pg')
466480
})
481+
467482
beforeEach(done => {
468483
pg = require(`../../../versions/pg@${version}`).get()
469484

@@ -484,10 +499,11 @@ describe('Plugin', () => {
484499

485500
it('query config objects should be handled', done => {
486501
let queryText = ''
502+
487503
const query = {
488-
name: 'pgSelectQuery',
489504
text: 'SELECT $1::text as message'
490505
}
506+
491507
agent.use(traces => {
492508
const traceId = traces[0][0].trace_id.toString(16).padStart(32, '0')
493509
const spanId = traces[0][0].span_id.toString(16).padStart(16, '0')
@@ -496,6 +512,7 @@ describe('Plugin', () => {
496512
`/*dddbs='post',dde='tester',ddps='test',ddpv='8.4.0',` +
497513
`traceparent='00-${traceId}-${spanId}-00'*/ SELECT $1::text as message`)
498514
}).then(done, done)
515+
499516
client.query(query, ['Hello world!'], (err) => {
500517
if (err) return done(err)
501518

@@ -505,23 +522,50 @@ describe('Plugin', () => {
505522
})
506523
queryText = client.queryQueue[0].text
507524
})
525+
508526
it('query config object should persist when comment is injected', done => {
509527
const query = {
510528
name: 'pgSelectQuery',
511529
text: 'SELECT $1::text as message'
512530
}
531+
513532
client.query(query, ['Hello world!'], (err) => {
514533
if (err) return done(err)
515534

516535
client.end((err) => {
517536
if (err) return done(err)
518537
})
519538
})
539+
520540
agent.use(traces => {
521541
expect(query).to.have.property(
522542
'name', 'pgSelectQuery')
523543
}).then(done, done)
524544
})
545+
546+
it('falls back to service with prepared statements', done => {
547+
let queryText = ''
548+
549+
const query = {
550+
name: 'pgSelectQuery',
551+
text: 'SELECT $1::text as message'
552+
}
553+
554+
agent.use(traces => {
555+
expect(queryText).to.equal(
556+
`/*dddbs='post',dde='tester',ddps='test',ddpv='8.4.0'` +
557+
`*/ SELECT $1::text as message`)
558+
}).then(done, done)
559+
560+
client.query(query, ['Hello world!'], (err) => {
561+
if (err) return done(err)
562+
563+
client.end((err) => {
564+
if (err) return done(err)
565+
})
566+
})
567+
queryText = client.queryQueue[0].text
568+
})
525569
})
526570
})
527571
})

packages/dd-trace/src/plugins/database.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ class DatabasePlugin extends StoragePlugin {
3737
`ddps='${encodedDdps}',ddpv='${encodedDdpv}'`
3838
}
3939

40-
injectDbmQuery (query, serviceName) {
40+
injectDbmQuery (query, serviceName, isPreparedStatement = false) {
4141
if (this.config.dbmPropagationMode === 'disabled') {
4242
return query
4343
}
4444
const servicePropagation = this.createDBMPropagationCommentService(serviceName)
45-
if (this.config.dbmPropagationMode === 'service') {
45+
if (isPreparedStatement || this.config.dbmPropagationMode === 'service') {
4646
return `/*${servicePropagation}*/ ${query}`
4747
} else if (this.config.dbmPropagationMode === 'full') {
4848
this.activeSpan.setTag('_dd.dbm_trace_injected', 'true')

0 commit comments

Comments
 (0)