Repository navigation
Conversation
Live Debugger needs to know which instrumented functions a build ships and
where they are in the repository, so the UI and MCP can copy a function's ID
from SymDB instead of computing it. This adds the generation step
(DEBUG-6327); the upload comes in DEBUG-6328.
After a one-off build, the plugin scans each emitted chunk for the
`$dd_probes('<id>')` call at the start of every instrumented function and the
`$dd_throw(` call at its end, pairs them like brackets, and maps both through
the chunk's final source map to get the original line range. It doesn't parse
the output or rely on the transform hook, so it works with persistent bundler
caches and only lists functions that survive tree-shaking.
File paths and display names come from the function ID. Query strings are
stripped, Yarn PnP virtual paths and symlinks are resolved, and paths are made
relative to the git root. The table also records the build's chunk debug IDs
and which chunks contain each file, when every instrumented chunk has one.
The table is serialized as SymDB scopes (a MODULE per file and nested FUNCTION
scopes, language `browser`). For now its only consumer is an opt-in debug dump
enabled by `DD_LIVE_DEBUGGER_SYMBOL_TABLE_PATH`; without it, the plugin adds no
hooks and no build time. Generation never fails the build and never writes
inside the output directory.
Also make core's `outputJson` resolve once the file is written instead of when
the data has been read, which the new tests exposed as a race.
Environment: Datadog workspace
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Live Debugger Runtime BenchmarkBenchmark results were not produced. Check the workflow logs for details. |
On a web-ui production build, 45% of the symbol table's functions had no line range. The transform appends the closing code of an arrow function's expression body without a source map segment, and minifiers leave some rewritten tokens unmapped, so looking up the `$dd_throw` call alone often found nothing. Use the last mapped position of the same source between the two markers instead. For block bodies that's still the closing brace. For expression bodies, it's the last mapped token of the expression. On the same web-ui build, functions without a line range drop to 1.8%. The integration test fixture now has a multi-line arrow function with an expression body, and a minified Rspack production build. Environment: Datadog workspace Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a web-ui production build, 1.8% of the symbol table's functions still had no line range after the previous fix: - Minifiers can also leave the `$dd_probes` call unmapped. Fall back to the first mapped token between the two markers for the start, like the end already falls back to the last one. - A module bundled into many chunks can be mapped in some chunks and not in others, which left a copy without a line range next to the mapped ones. Drop such copies, and attach their nested functions to their parent. Functions without a line range drop to 0.98% on the same build, mostly helpers that compilers inject, such as `_define_property`, which have no original source. Unit tests cover the lookups with hand-built source maps. Environment: Datadog workspace Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Customers see the build logs, where "symbol table" is an internal term. Call them Live Debugger symbols, like Datadog's documentation does for symbol uploads, and remove noise from the contributing guide. Environment: Datadog workspace Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Environment: Datadog workspace Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Master now guards probe calls with `globalThis.$dd_probes !== void 0 &&`.
The scanner still matches the bare `$dd_probes('<id>')` call, and the
symbol table integration test passes on the merged tree.
Environment: Datadog workspace
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
DEBUG-6327: list the instrumented functions a build ships, with their repository path and original line range, so Live Debugger can upload them as symbols. The upload is #593; for now the only consumer is an opt-in debug dump. Without
DD_LIVE_DEBUGGER_SYMBOL_TABLE_PATH, the plugin adds no hooks and no build time.No output parsing and no transform-hook collection, so it works with persistent bundler caches and only lists functions that survive tree-shaking. Never fails the build: problems are logged as warnings.
Also: core's
outputJsonnow resolves once the file is written, not when the data has been read. The new tests exposed the race.Evidence
Before: nothing records which functions a build ships or where they are.
After:
symbolTable.integration.test.tsbuilds a fixture with esbuild, Rollup, Rspack, Vite and webpack, plus a minified Rspack production build: build rooted in a repo subdirectory, symlinked workspace package, Yarn PnP virtual path, loader query string on webpack and Rspack, multi-line arrow function with an expression body. E.g. forapp/src/math.js:{ "scope_type": "MODULE", "name": "app/src/math.js", "source_file": "app/src/math.js", "language_specifics": { "chunk_debug_ids": ["…"] }, "scopes": [ { "scope_type": "FUNCTION", "name": "add", "source_file": "app/src/math.js", "start_line": 1, "end_line": 6, "language_specifics": { "function_id": "src/math.js;add" }, "scopes": [ { "scope_type": "FUNCTION", "name": "double", "source_file": "app/src/math.js", "start_line": 2, "end_line": 4, "language_specifics": { "function_id": "src/math.js;double" } } ] } ] }Before: collecting in the transform hook would miss every module restored from webpack's filesystem cache.
After: a warm-cache webpack build (transform didn't run) produces the same table as the cold build.
web-ui (
spa-rspack, production build with source maps, Live Debugger + RUM privacy, local plugin linked):_define_property)sourceFileThe first web-ui run had 45% of functions without a line range: minified expression-body arrows. The fallback lookups in
locateFunctionsfixed that; the integration test now covers it.Live Debugger suite: 437/437.
yarn typecheck:allandyarn cli integritypass.Merge Danger
Door: two-way
Nothing new runs unless
DD_LIVE_DEBUGGER_SYMBOL_TABLE_PATHis set.Blast Radius: minimal
@jridgewell/trace-mapping0.3.31, already installed through@jridgewell/remapping.outputJsonresolves slightly later for its other caller, the output plugin.$dd_throw; generated code is unchanged.🤖 Generated with Claude Code