diff --git a/integration-tests/debugger/basic.spec.js b/integration-tests/debugger/basic.spec.js index e48efb343c1..f42388396ef 100644 --- a/integration-tests/debugger/basic.spec.js +++ b/integration-tests/debugger/basic.spec.js @@ -12,7 +12,7 @@ describe('Dynamic Instrumentation', function () { const t = setup() it('base case: target app should work as expected if no test probe has been added', async function () { - const response = await t.axios.get('/foo') + const response = await t.axios.get(t.breakpoint.url) assert.strictEqual(response.status, 200) assert.deepStrictEqual(response.data, { hello: 'foo' }) }) @@ -51,7 +51,7 @@ describe('Dynamic Instrumentation', function () { assertUUID(payload.debugger.diagnostics.runtimeId) if (payload.debugger.diagnostics.status === 'INSTALLED') { - t.axios.get('/foo') + t.axios.get(t.breakpoint.url) .then((response) => { assert.strictEqual(response.status, 200) assert.deepStrictEqual(response.data, { hello: 'foo' }) @@ -293,13 +293,13 @@ describe('Dynamic Instrumentation', function () { const expectedMessages = ['Hello World!', 'Hello Updated World!'] const triggers = [ async () => { - await t.axios.get('/foo') + await t.axios.get(t.breakpoint.url) t.rcConfig.config.version++ t.rcConfig.config.template = 'Hello Updated World!' t.agent.updateRemoteConfig(t.rcConfig.id, t.rcConfig.config) }, async () => { - await t.axios.get('/foo') + await t.axios.get(t.breakpoint.url) } ] @@ -319,7 +319,7 @@ describe('Dynamic Instrumentation', function () { t.agent.on('debugger-diagnostics', ({ payload }) => { if (payload.debugger.diagnostics.status === 'INSTALLED') { t.agent.once('remote-confg-responded', async () => { - await t.axios.get('/foo') + await t.axios.get(t.breakpoint.url) // We want to wait enough time to see if the client triggers on the breakpoint so that the test can fail // if it does, but not so long that the test times out. // TODO: Is there some signal we can use instead of a timer? @@ -368,7 +368,7 @@ describe('Dynamic Instrumentation', function () { }) // Perform HTTP request to try and trigger the probe - t.axios.get('/foo').catch((err) => { + t.axios.get(t.breakpoint.url).catch((err) => { // If the request hasn't fully completed by the time the tests ends and the target app is destroyed, Axios // will complain with a "socket hang up" error. Hence this sanity check before calling `done(err)`. If we // later add more tests below this one, this shouuldn't be an issue. diff --git a/integration-tests/debugger/snapshot-pruning.spec.js b/integration-tests/debugger/snapshot-pruning.spec.js index 91190a1c25d..c1ba218dd1c 100644 --- a/integration-tests/debugger/snapshot-pruning.spec.js +++ b/integration-tests/debugger/snapshot-pruning.spec.js @@ -1,9 +1,7 @@ 'use strict' const { assert } = require('chai') -const { setup, getBreakpointInfo } = require('./utils') - -const { line } = getBreakpointInfo() +const { setup } = require('./utils') describe('Dynamic Instrumentation', function () { const t = setup() @@ -17,7 +15,7 @@ describe('Dynamic Instrumentation', function () { assert.isBelow(Buffer.byteLength(JSON.stringify(payload)), 1024 * 1024) // 1MB assert.deepEqual(payload['debugger.snapshot'].captures, { lines: { - [line]: { + [t.breakpoint.line]: { locals: { notCapturedReason: 'Snapshot was too large', size: 6 diff --git a/integration-tests/debugger/target-app/basic.js b/integration-tests/debugger/target-app/basic.js index f8330012278..2fa9c16d221 100644 --- a/integration-tests/debugger/target-app/basic.js +++ b/integration-tests/debugger/target-app/basic.js @@ -6,7 +6,7 @@ const Fastify = require('fastify') const fastify = Fastify() fastify.get('/:name', function handler (request) { - return { hello: request.params.name } // BREAKPOINT + return { hello: request.params.name } // BREAKPOINT: /foo }) fastify.listen({ port: process.env.APP_PORT }, (err) => { diff --git a/integration-tests/debugger/target-app/snapshot-pruning.js b/integration-tests/debugger/target-app/snapshot-pruning.js index 58752006192..6b14405e61d 100644 --- a/integration-tests/debugger/target-app/snapshot-pruning.js +++ b/integration-tests/debugger/target-app/snapshot-pruning.js @@ -14,7 +14,7 @@ fastify.get('/:name', function handler (request) { // eslint-disable-next-line no-unused-vars const obj = generateObjectWithJSONSizeLargerThan1MB() - return { hello: request.params.name } // BREAKPOINT + return { hello: request.params.name } // BREAKPOINT: /foo }) fastify.listen({ port: process.env.APP_PORT }, (err) => { diff --git a/integration-tests/debugger/target-app/snapshot.js b/integration-tests/debugger/target-app/snapshot.js index bae83a2176e..03cfc758556 100644 --- a/integration-tests/debugger/target-app/snapshot.js +++ b/integration-tests/debugger/target-app/snapshot.js @@ -11,7 +11,7 @@ const fastify = Fastify() fastify.get('/:name', function handler (request) { // eslint-disable-next-line no-unused-vars const { nil, undef, bool, num, bigint, str, lstr, sym, regex, arr, obj, emptyObj, fn, p } = getSomeData() - return { hello: request.params.name } // BREAKPOINT + return { hello: request.params.name } // BREAKPOINT: /foo }) fastify.listen({ port: process.env.APP_PORT }, (err) => { diff --git a/integration-tests/debugger/target-app/unreffed.js b/integration-tests/debugger/target-app/unreffed.js index 3a5353d7399..c3c73d72d8b 100644 --- a/integration-tests/debugger/target-app/unreffed.js +++ b/integration-tests/debugger/target-app/unreffed.js @@ -4,7 +4,7 @@ require('dd-trace/init') const http = require('http') const server = http.createServer((req, res) => { - res.end('hello world') // BREAKPOINT + res.end('hello world') // BREAKPOINT: / setImmediate(() => { server.close() }) diff --git a/integration-tests/debugger/unreffed.spec.js b/integration-tests/debugger/unreffed.spec.js index 2873d80e190..3ce9458f341 100644 --- a/integration-tests/debugger/unreffed.spec.js +++ b/integration-tests/debugger/unreffed.spec.js @@ -12,6 +12,6 @@ describe('Dynamic Instrumentation', function () { assert.strictEqual(code, 0) done() }) - t.axios.get('/') + t.axios.get(t.breakpoint.url) }) }) diff --git a/integration-tests/debugger/utils.js b/integration-tests/debugger/utils.js index c65bd5c0d88..1ea6cb9b54c 100644 --- a/integration-tests/debugger/utils.js +++ b/integration-tests/debugger/utils.js @@ -8,13 +8,14 @@ const getPort = require('get-port') const Axios = require('axios') const { createSandbox, FakeAgent, spawnProc } = require('../helpers') +const { generateProbeConfig } = require('../../packages/dd-trace/test/debugger/devtools_client/utils') +const BREAKPOINT_TOKEN = '// BREAKPOINT' const pollInterval = 1 module.exports = { pollInterval, - setup, - getBreakpointInfo + setup } function setup () { @@ -35,7 +36,7 @@ function setup () { // Trigger the breakpoint once probe is successfully installed t.agent.on('debugger-diagnostics', ({ payload }) => { if (payload.debugger.diagnostics.status === 'INSTALLED') { - t.axios.get('/foo') + t.axios.get(breakpoint.url) } }) } @@ -45,32 +46,15 @@ function setup () { return { product: 'LIVE_DEBUGGING', id: `logProbe_${overrides.id}`, - config: generateProbeConfig(overrides) - } - } - - function generateProbeConfig (overrides = {}) { - overrides.capture = { maxReferenceDepth: 3, ...overrides.capture } - overrides.sampling = { snapshotsPerSecond: 5000, ...overrides.sampling } - return { - id: randomUUID(), - version: 0, - type: 'LOG_PROBE', - language: 'javascript', - where: { sourceFile: breakpoint.file, lines: [String(breakpoint.line)] }, - tags: [], - template: 'Hello World!', - segments: [{ str: 'Hello World!' }], - captureSnapshot: false, - evaluateAt: 'EXIT', - ...overrides + config: generateProbeConfig(breakpoint, overrides) } } before(async function () { sandbox = await createSandbox(['fastify']) // TODO: Make this dynamic cwd = sandbox.folder - t.appFile = join(cwd, ...breakpoint.file.split('/')) + // The sandbox uses the `integration-tests` folder as its root + t.appFile = join(cwd, 'debugger', breakpoint.file) }) after(async function () { @@ -113,12 +97,15 @@ function getBreakpointInfo (stackIndex = 0) { .split(':')[0] // Then, find the corresponding file in which the breakpoint exists - const filename = basename(testFile).replace('.spec', '') + const file = join('target-app', basename(testFile).replace('.spec', '')) // Finally, find the line number of the breakpoint - const line = readFileSync(join(__dirname, 'target-app', filename), 'utf8') - .split('\n') - .findIndex(line => line.includes('// BREAKPOINT')) + 1 - - return { file: `debugger/target-app/${filename}`, line } + const lines = readFileSync(join(__dirname, file), 'utf8').split('\n') + for (let i = 0; i < lines.length; i++) { + const index = lines[i].indexOf(BREAKPOINT_TOKEN) + if (index !== -1) { + const url = lines[i].slice(index + BREAKPOINT_TOKEN.length + 1).trim() + return { file, line: i + 1, url } + } + } } diff --git a/packages/dd-trace/test/debugger/devtools_client/utils.js b/packages/dd-trace/test/debugger/devtools_client/utils.js new file mode 100644 index 00000000000..e15d567a7c1 --- /dev/null +++ b/packages/dd-trace/test/debugger/devtools_client/utils.js @@ -0,0 +1,25 @@ +'use strict' + +const { randomUUID } = require('node:crypto') + +module.exports = { + generateProbeConfig +} + +function generateProbeConfig (breakpoint, overrides = {}) { + overrides.capture = { maxReferenceDepth: 3, ...overrides.capture } + overrides.sampling = { snapshotsPerSecond: 5000, ...overrides.sampling } + return { + id: randomUUID(), + version: 0, + type: 'LOG_PROBE', + language: 'javascript', + where: { sourceFile: breakpoint.file, lines: [String(breakpoint.line)] }, + tags: [], + template: 'Hello World!', + segments: [{ str: 'Hello World!' }], + captureSnapshot: false, + evaluateAt: 'EXIT', + ...overrides + } +}