Skip to content

Commit 77f61e6

Browse files
watsonrochdev
authored andcommitted
[DI] Don't fail to trigger if one of multiple probe conditions throws (#5715)
If two probes are on the same line, and both have a condition, but one condition throws and the other evaluates to true, the one that evaluated to true should still trigger the breakpoint and get collected.
1 parent bd829c1 commit 77f61e6

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

integration-tests/debugger/basic.spec.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,46 @@ describe('Dynamic Instrumentation', function () {
390390
}
391391
})
392392

393+
it('trigger on met condition, even if other condition throws (all have conditions)', function (done) {
394+
let installed = 0
395+
// this condition will throw because `foo` is not defined
396+
const rcConfig1 = t.generateRemoteConfig({ when: { json: { eq: [{ ref: 'foo' }, 'bar'] } } })
397+
const rcConfig2 = t.generateRemoteConfig({
398+
when: { json: { eq: [{ getmember: [{ getmember: [{ ref: 'request' }, 'params'] }, 'name'] }, 'bar'] } }
399+
})
400+
const expectedPayloads = new Map([
401+
[rcConfig2.config.id, {
402+
ddsource: 'dd_debugger',
403+
service: 'node',
404+
debugger: { diagnostics: { probeId: rcConfig2.config.id, probeVersion: 0, status: 'EMITTING' } }
405+
}]
406+
])
407+
408+
t.agent.on('debugger-diagnostics', ({ payload }) => {
409+
payload.forEach((event) => {
410+
const { diagnostics } = event.debugger
411+
if (diagnostics.status === 'INSTALLED') {
412+
if (++installed === 2) {
413+
t.axios.get(t.breakpoint.url).catch(done)
414+
}
415+
} else if (diagnostics.status === 'EMITTING') {
416+
const expected = expectedPayloads.get(diagnostics.probeId)
417+
assert.ok(expected, `expected payload not found for probe ${diagnostics.probeId}`)
418+
expectedPayloads.delete(diagnostics.probeId)
419+
assertObjectContains(event, expected)
420+
}
421+
})
422+
endIfDone()
423+
})
424+
425+
t.agent.addRemoteConfig(rcConfig1)
426+
t.agent.addRemoteConfig(rcConfig2)
427+
428+
function endIfDone () {
429+
if (expectedPayloads.size === 0) done()
430+
}
431+
})
432+
393433
it('should only trigger the probes whos conditions are met (not all have conditions)', function (done) {
394434
let installed = 0
395435
const rcConfig1 = t.generateRemoteConfig({

packages/dd-trace/src/debugger/devtools_client/breakpoints.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,13 @@ function stop () {
187187

188188
// Only if all probes have a condition can we use a compound condition.
189189
// Otherwise, we need to evaluate each probe individually once the breakpoint is hit.
190-
// TODO: Handle errors - if there's 2 conditions, and one fails but the other returns true, we should still pause the
191-
// breakpoint
192190
function compileCompoundCondition (probes) {
191+
if (probes.length === 1) return probes[0].condition
192+
193193
return probes.every(p => p.condition)
194-
? probes.map(p => p.condition).filter(Boolean).join(' || ')
194+
? probes
195+
.map((p) => `(() => { try { return ${p.condition} } catch { return false } })()`)
196+
.join(' || ')
195197
: undefined
196198
}
197199

packages/dd-trace/test/debugger/devtools_client/breakpoints.spec.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,9 @@ describe('breakpoints', function () {
233233
lineNumber: 9,
234234
columnNumber: 0
235235
},
236-
condition: '(foo) === (42) || (foo) === (43)'
236+
condition:
237+
'(() => { try { return (foo) === (42) } catch { return false } })() || ' +
238+
'(() => { try { return (foo) === (43) } catch { return false } })()'
237239
})
238240
})
239241

0 commit comments

Comments
 (0)