Skip to content

Commit

Permalink
[DI] Handle unknown path prefixes in probe file paths
Browse files Browse the repository at this point in the history
If there's no match for a known script based on the probe file path
provided via RC, try to remove the base directory and try to match
again. Continue this approach, until there's no more directories in the
path.

This can happen if the user-provided file path contains a base
directory, but this directory isn't part of the deployed code base.
This would for example be the case if the files are stored in a
sub-directory in the git repo, but deployed into a different directory
in production.
  • Loading branch information
watson committed Jan 29, 2025
1 parent c0550a0 commit ea0dcd1
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 4 deletions.
18 changes: 14 additions & 4 deletions packages/dd-trace/src/debugger/devtools_client/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,22 @@ module.exports = {
* To fix this, specify a more unique file path, e.g `demo-project1/index.js` instead of `index.js`
*
* @param {string} path
* @returns {[string, string] | undefined}
* @returns {[string, string, string | undefined] | undefined}
*/
findScriptFromPartialPath (path) {
return scriptIds
.filter(([url]) => url.endsWith(path))
.sort(([a], [b]) => a.length - b.length)[0]
do {
const result = scriptIds
.filter(([url]) => url.endsWith(path))
.sort(([a], [b]) => a.length - b.length)[0]

if (result === undefined) {
const index = path.indexOf('/')
if (index === -1) return
path = path.slice(index + 1)
} else {
return result
}
} while (true)
},

getStackFromCallFrames (callFrames) {
Expand Down
64 changes: 64 additions & 0 deletions packages/dd-trace/test/debugger/devtools_client/state.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
'use strict'

require('../../setup/mocha')

describe('findScriptFromPartialPath', function () {
let state

before(function () {
state = proxyquire('../src/debugger/devtools_client/state', {
'./session': {
'@noCallThru': true,
on (event, listener) {
if (event === 'Debugger.scriptParsed') {
listener({ params: { scriptId: 'script-id', url: 'file:///path/to/foo.js' } })
}
}
}
})
})

describe('full path matches', function () {
it('with a "file:" protocol', testPath('file:///path/to/foo.js'))

it('with a root slash', testPath('/path/to/foo.js'))

it('without a root slash', testPath('path/to/foo.js'))
})

describe('partial path matches', function () {
it('fewer directories', testPath('to/foo.js'))

it('no directories', testPath('foo.js'))
})

describe('path contains directory prefix', function () {
it('prefixed with unknown directory', testPath('prefix/to/foo.js'))

it('prefixed with two unknown directories', testPath('prefix1/prefix2/to/foo.js'))
})

describe('circuit breakers', function () {
it('should abort if the path is unknown', function () {
const result = state.findScriptFromPartialPath('this/path/does/not/exist.js')
expect(result).to.be.undefined
})

it('should abort if the path is undefined', function () {
const result = state.findScriptFromPartialPath(undefined)
expect(result).to.be.undefined
})

it('should abort if the path is an empty string', function () {
const result = state.findScriptFromPartialPath('')
expect(result).to.be.undefined
})
})

function testPath (path) {
return function () {
const result = state.findScriptFromPartialPath(path)
expect(result).to.deep.equal(['file:///path/to/foo.js', 'script-id', undefined])
}
}
})

0 comments on commit ea0dcd1

Please sign in to comment.