[Debugger] Minor Dynamic Instrumentation cleanups#8770
Conversation
Simplify ProbeExpressionEvaluator.CompileAll to call the Compile* helpers unconditionally; each already returns null when its expression is absent, so the outer null ternaries were redundant (behavior-preserving). Remove an unused Newtonsoft.Json using from ProbeExpressionsProcessor, add a clarifying comment in DebuggerSnapshotCreator.EndEntry, and null-guard ShouldSkipDiUpdate via a property pattern. Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
There was a problem hiding this comment.
Pull request overview
This PR performs small cleanups in the Dynamic Instrumentation / Debugger codepaths, focusing on simplifying null-handling, improving nullable-aware string checks, and fixing a debug logging inconsistency during probe processor creation failures.
Changes:
- Simplifies
ProbeExpressionEvaluator.CompileAllby removing redundant null-guard ternaries and switches to nullable-awareStringUtil.IsNullOrEmptyunder#nullable enable. - Fixes
ProbeExpressionsProcessor.AddProbeProcessorto stop logging success after probe processor creation throws (by returning from the catch block) and removes unusedusings. - Hardens
DebuggerManager.ShouldSkipDiUpdatewith a property-pattern check to avoid potential null-related issues; adds a clarifying comment in snapshot JSON writer flow.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| tracer/src/Datadog.Trace/Debugger/Snapshots/DebuggerSnapshotCreator.cs | Adds a clarifying comment explaining why args/locals container closure must not rely on heuristics. |
| tracer/src/Datadog.Trace/Debugger/Expressions/ProbeExpressionsProcessor.cs | Removes unused usings and fixes a logging/control-flow issue by returning after processor creation exceptions. |
| tracer/src/Datadog.Trace/Debugger/Expressions/ProbeExpressionEvaluator.cs | Uses nullable-aware string helpers and simplifies CompileAll by relying on helper-level null checks. |
| tracer/src/Datadog.Trace/Debugger/DebuggerManager.cs | Uses a property-pattern check in ShouldSkipDiUpdate and applies minor whitespace cleanup. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
BenchmarksBenchmark execution time: 2026-06-09 13:37:28 Comparing candidate commit a6bdcdf in PR branch Found 0 performance improvements and 1 performance regressions! Performance is the same for 71 metrics, 0 unstable metrics, 59 known flaky benchmarks, 67 flaky benchmarks without significant changes.
|
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (8770) and master. ✅ No regressions detected - check the details below Full Metrics ComparisonFakeDbCommand
HttpMessageHandler
Comparison explanationExecution-time benchmarks measure the whole time it takes to execute a program, and are intended to measure the one-off costs. Cases where the execution time results for the PR are worse than latest master results are highlighted in **red**. The following thresholds were used for comparing the execution times:
Note that these results are based on a single point-in-time result for each branch. For full results, see the dashboard. Graphs show the p99 interval based on the mean and StdDev of the test run, as well as the mean value of the run (shown as a diamond below the graph). Duration chartsFakeDbCommand (.NET Framework 4.8)gantt
title Execution time (ms) FakeDbCommand (.NET Framework 4.8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8770) - mean (75ms) : 72, 79
master - mean (74ms) : 71, 76
section Bailout
This PR (8770) - mean (80ms) : 77, 83
master - mean (80ms) : 75, 85
section CallTarget+Inlining+NGEN
This PR (8770) - mean (1,119ms) : 1046, 1191
master - mean (1,116ms) : 1056, 1177
FakeDbCommand (.NET Core 3.1)gantt
title Execution time (ms) FakeDbCommand (.NET Core 3.1)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8770) - mean (117ms) : 110, 124
master - mean (117ms) : 111, 123
section Bailout
This PR (8770) - mean (116ms) : 113, 118
master - mean (117ms) : 112, 121
section CallTarget+Inlining+NGEN
This PR (8770) - mean (799ms) : 770, 827
master - mean (798ms) : 774, 822
FakeDbCommand (.NET 6)gantt
title Execution time (ms) FakeDbCommand (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8770) - mean (102ms) : 97, 108
master - mean (104ms) : 97, 111
section Bailout
This PR (8770) - mean (103ms) : 100, 106
master - mean (105ms) : 100, 110
section CallTarget+Inlining+NGEN
This PR (8770) - mean (952ms) : 905, 999
master - mean (954ms) : 925, 983
FakeDbCommand (.NET 8)gantt
title Execution time (ms) FakeDbCommand (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8770) - mean (102ms) : 98, 107
master - mean (101ms) : 93, 108
section Bailout
This PR (8770) - mean (102ms) : 98, 106
master - mean (101ms) : 99, 102
section CallTarget+Inlining+NGEN
This PR (8770) - mean (825ms) : 783, 867
master - mean (820ms) : 775, 864
HttpMessageHandler (.NET Framework 4.8)gantt
title Execution time (ms) HttpMessageHandler (.NET Framework 4.8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8770) - mean (196ms) : 191, 200
master - mean (198ms) : 191, 205
section Bailout
This PR (8770) - mean (201ms) : 197, 204
master - mean (202ms) : 197, 207
section CallTarget+Inlining+NGEN
This PR (8770) - mean (1,188ms) : 1147, 1229
master - mean (1,194ms) : 1153, 1235
HttpMessageHandler (.NET Core 3.1)gantt
title Execution time (ms) HttpMessageHandler (.NET Core 3.1)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8770) - mean (284ms) : 275, 292
master - mean (286ms) : 281, 291
section Bailout
This PR (8770) - mean (285ms) : 277, 293
master - mean (286ms) : 281, 292
section CallTarget+Inlining+NGEN
This PR (8770) - mean (960ms) : 938, 981
master - mean (954ms) : 931, 977
HttpMessageHandler (.NET 6)gantt
title Execution time (ms) HttpMessageHandler (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8770) - mean (275ms) : 268, 282
master - mean (276ms) : 270, 282
section Bailout
This PR (8770) - mean (276ms) : 269, 284
master - mean (275ms) : 269, 280
section CallTarget+Inlining+NGEN
This PR (8770) - mean (1,153ms) : 1113, 1193
master - mean (1,153ms) : 1121, 1185
HttpMessageHandler (.NET 8)gantt
title Execution time (ms) HttpMessageHandler (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8770) - mean (275ms) : 266, 285
master - mean (275ms) : 269, 281
section Bailout
This PR (8770) - mean (277ms) : 271, 283
master - mean (275ms) : 270, 281
section CallTarget+Inlining+NGEN
This PR (8770) - mean (1,035ms) : 998, 1073
master - mean (1,034ms) : 991, 1076
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
## Summary of changes
- Simplify `ProbeExpressionEvaluator.CompileAll` by dropping the
redundant `== null ? null :` ternaries; each `Compile*` helper already
null-checks its source and returns `null`.
- Use the nullable-aware `StringUtil.IsNullOrEmpty` instead of
`string.IsNullOrEmpty` in the `#nullable enable`
`ProbeExpressionEvaluator`.
- Harden `DebuggerManager.ShouldSkipDiUpdate` with a property-pattern
null check (`debuggerSettings is { DynamicInstrumentationCanBeEnabled:
false }`).
- Remove unused usings in `ProbeExpressionsProcessor` (`Newtonsoft.Json`
and `Debugger.Snapshots`).
- Add a clarifying comment in `DebuggerSnapshotCreator.EndEntry` about
why arg/local capture must not rely on heuristics.
- Fix a logging bug in `ProbeExpressionsProcessor.AddProbeProcessor` so
it no longer logs `"Successfully created probe processor"` after
creation throws.
## Reason for change
- These are low-risk cleanups split out of #8572 to keep that PR focused
on the snapshot-exploration feature.
- The `AddProbeProcessor` change fixes a real (debug-level) logging
inconsistency: a probe whose processor creation throws would log both a
failure and a success line.
## Implementation details
- `CompileAll` simplification is behavior-preserving:
`CompileTemplates`/`CompileCondition`/`CompileMetric`/`CompileDecorations`
each return `null` when their source is null. One benign difference:
when `SpanDecorations` is null, `CompileDecorations` now emits its
existing debug-level "is null" log.
- `StringUtil.IsNullOrEmpty` only adds value under `#nullable enable`
(it carries the `[NotNullWhen(false)]` annotation), so the swap was
limited to that file; other `string.IsNullOrEmpty` call sites in
non-nullable files were intentionally left unchanged.
- The `ShouldSkipDiUpdate` property pattern is equivalent for the normal
(non-null) case and additionally avoids a potential NRE if settings were
ever null.
## Test coverage
- No new tests added; changes are cleanups plus one debug-only logging
fix.
---------
Co-authored-by: Cursor <[email protected]>
Summary of changes
ProbeExpressionEvaluator.CompileAllby dropping the redundant== null ? null :ternaries; eachCompile*helper already null-checks its source and returnsnull.StringUtil.IsNullOrEmptyinstead ofstring.IsNullOrEmptyin the#nullable enableProbeExpressionEvaluator.DebuggerManager.ShouldSkipDiUpdatewith a property-pattern null check (debuggerSettings is { DynamicInstrumentationCanBeEnabled: false }).ProbeExpressionsProcessor(Newtonsoft.JsonandDebugger.Snapshots).DebuggerSnapshotCreator.EndEntryabout why arg/local capture must not rely on heuristics.ProbeExpressionsProcessor.AddProbeProcessorso it no longer logs"Successfully created probe processor"after creation throws.Reason for change
AddProbeProcessorchange fixes a real (debug-level) logging inconsistency: a probe whose processor creation throws would log both a failure and a success line.Implementation details
CompileAllsimplification is behavior-preserving:CompileTemplates/CompileCondition/CompileMetric/CompileDecorationseach returnnullwhen their source is null. One benign difference: whenSpanDecorationsis null,CompileDecorationsnow emits its existing debug-level "is null" log.StringUtil.IsNullOrEmptyonly adds value under#nullable enable(it carries the[NotNullWhen(false)]annotation), so the swap was limited to that file; otherstring.IsNullOrEmptycall sites in non-nullable files were intentionally left unchanged.ShouldSkipDiUpdateproperty pattern is equivalent for the normal (non-null) case and additionally avoids a potential NRE if settings were ever null.Test coverage