Skip to content

Conversation

@tonyredondo
Copy link
Member

Summary of changes

  • Added Exception Replay–specific agentless configuration keys and settings so snapshots can bypass the local agent when explicitly enabled.
  • Introduced an agentless transport helper (with request header injection) and taught SnapshotUploadApi/ExceptionReplay to use static debugger intakes when the agent is absent.
  • Prevented symbol uploader initialization while in agentless ER mode.
  • Expanded unit coverage for the new configuration/transport behavior, including header verification and custom intake overrides.

Reason for change

For complete Test Optimization + Exception Replay integration in environments without the Datadog Agent need a documented path to send snapshots directly to Datadog without impacting Shared Debugger/DI behaviors. The plan isolates ER agentless support, reusing DD_API_KEY/DD_SITE, and ensures we do not silently initialize features (symbol uploads) that still require the agent/RCM.

Implementation details

  • ConfigurationKeys.Debugger + ExceptionReplaySettings now surface DD_EXCEPTION_REPLAY_AGENTLESS_ENABLED/DD_EXCEPTION_REPLAY_AGENTLESS_URL, defaulting to datadoghq.com and the existing DD_API_KEY.
  • ExceptionReplayTransportFactory creates either the existing agent transport or an HTTPS transport that injects DD-API-KEY, DD-EVP-ORIGIN=dd-trace-dotnet, and a per-request DD-REQUEST-ID, honouring site overrides.
  • SnapshotUploadApi accepts a static endpoint so ER can bypass discovery when agentless, and ExceptionReplay wires the new transport info through DebuggerUploadApiFactory.
  • DebuggerManager now emits a clear log and skips symbol uploader initialization whenever ER is agentless, avoiding futile RCM attempts.

Test coverage

  • New test suite has been added.
  • Snapshot uploader tests (SnapshotUploadApiTests) continue to validate static endpoint behavior.
  • New transport tests verify header injection + override URL parsing without exposing additional public APIs.

Other details

  • Agentless mode still logs that symbol uploads are unavailable; long-term support would require backend work to accept symbol payloads without RCM.

@datadog-datadog-prod-us1

This comment has been minimized.

@tonyredondo tonyredondo marked this pull request as ready for review November 24, 2025 17:35
@tonyredondo tonyredondo requested review from a team as code owners November 24, 2025 17:35
@pr-commenter
Copy link

pr-commenter bot commented Nov 24, 2025

Benchmarks

Benchmarks Report for benchmark platform 🐌

Benchmarks for #7859 compared to master:

  • 1 benchmarks are slower, with geometric mean 1.132
  • 3 benchmarks have fewer allocations
  • 3 benchmarks have more allocations

The following thresholds were used for comparing the benchmark speeds:

  • Mann–Whitney U test with statistical test for significance of 5%
  • Only results indicating a difference greater than 10% and 0.3 ns are considered.

Allocation changes below 0.5% are ignored.

Benchmark details

Benchmarks.Trace.ActivityBenchmark - Same speed ✔️ More allocations ⚠️

More allocations ⚠️ in #7859

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.ActivityBenchmark.StartStopWithChild‑netcoreapp3.1 5.62 KB 5.7 KB 78 B 1.39%

Fewer allocations 🎉 in #7859

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.ActivityBenchmark.StartStopWithChild‑net472 5.99 KB 5.96 KB -33 B -0.55%
Benchmarks.Trace.ActivityBenchmark.StartStopWithChild‑net6.0 5.5 KB 5.38 KB -118 B -2.15%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartStopWithChild net6.0 11.5μs 62.2ns 357ns 0 0 0 5.5 KB
master StartStopWithChild netcoreapp3.1 14.3μs 54ns 209ns 0 0 0 5.62 KB
master StartStopWithChild net472 21.8μs 94.3ns 353ns 0.888 0.222 0 5.99 KB
#7859 StartStopWithChild net6.0 11.3μs 48.4ns 187ns 0 0 0 5.38 KB
#7859 StartStopWithChild netcoreapp3.1 14.1μs 68.6ns 275ns 0 0 0 5.7 KB
#7859 StartStopWithChild net472 22.3μs 99.2ns 409ns 1.01 0.338 0.113 5.96 KB
Benchmarks.Trace.AgentWriterBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 1.25ms 103ns 400ns 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 1.38ms 481ns 1.8μs 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces net472 1.75ms 1.26μs 4.71μs 0 0 0 3.26 KB
#7859 WriteAndFlushEnrichedTraces net6.0 1.29ms 137ns 514ns 0 0 0 2.7 KB
#7859 WriteAndFlushEnrichedTraces netcoreapp3.1 1.41ms 3.11μs 12μs 0 0 0 2.7 KB
#7859 WriteAndFlushEnrichedTraces net472 1.73ms 1.68μs 6.51μs 0 0 0 3.26 KB
Benchmarks.Trace.Asm.AppSecBodyBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master AllCycleSimpleBody net6.0 1.1μs 6ns 36.5ns 0 0 0 1.22 KB
master AllCycleSimpleBody netcoreapp3.1 1.37μs 7.69ns 52.7ns 0 0 0 1.2 KB
master AllCycleSimpleBody net472 1μs 0.0683ns 0.255ns 0.191 0 0 1.23 KB
master AllCycleMoreComplexBody net6.0 7.31μs 33.6ns 134ns 0 0 0 4.72 KB
master AllCycleMoreComplexBody netcoreapp3.1 8.93μs 46ns 221ns 0 0 0 4.62 KB
master AllCycleMoreComplexBody net472 7.7μs 2.54ns 9.83ns 0.733 0 0 4.74 KB
master ObjectExtractorSimpleBody net6.0 320ns 1.8ns 12.4ns 0 0 0 280 B
master ObjectExtractorSimpleBody netcoreapp3.1 405ns 1.95ns 7.8ns 0 0 0 272 B
master ObjectExtractorSimpleBody net472 302ns 0.0715ns 0.258ns 0.0441 0 0 281 B
master ObjectExtractorMoreComplexBody net6.0 6.33μs 25.9ns 100ns 0 0 0 3.78 KB
master ObjectExtractorMoreComplexBody netcoreapp3.1 7.79μs 39.3ns 180ns 0 0 0 3.69 KB
master ObjectExtractorMoreComplexBody net472 6.68μs 4.87ns 18.2ns 0.601 0 0 3.8 KB
#7859 AllCycleSimpleBody net6.0 1.06μs 6.08ns 47.5ns 0 0 0 1.22 KB
#7859 AllCycleSimpleBody netcoreapp3.1 1.41μs 7.55ns 43.4ns 0 0 0 1.2 KB
#7859 AllCycleSimpleBody net472 1.01μs 0.594ns 2.06ns 0.192 0 0 1.23 KB
#7859 AllCycleMoreComplexBody net6.0 7.24μs 39ns 221ns 0 0 0 4.72 KB
#7859 AllCycleMoreComplexBody netcoreapp3.1 9.13μs 3.33ns 12.9ns 0 0 0 4.62 KB
#7859 AllCycleMoreComplexBody net472 7.78μs 3.66ns 13.2ns 0.738 0 0 4.74 KB
#7859 ObjectExtractorSimpleBody net6.0 319ns 0.0858ns 0.309ns 0 0 0 280 B
#7859 ObjectExtractorSimpleBody netcoreapp3.1 403ns 2.24ns 13.5ns 0 0 0 272 B
#7859 ObjectExtractorSimpleBody net472 312ns 0.0392ns 0.146ns 0.044 0 0 281 B
#7859 ObjectExtractorMoreComplexBody net6.0 6.36μs 31.3ns 121ns 0 0 0 3.78 KB
#7859 ObjectExtractorMoreComplexBody netcoreapp3.1 7.87μs 40.1ns 184ns 0 0 0 3.69 KB
#7859 ObjectExtractorMoreComplexBody net472 6.71μs 1.07ns 3.85ns 0.572 0 0 3.8 KB
Benchmarks.Trace.Asm.AppSecEncoderBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EncodeArgs net6.0 76.1μs 185ns 716ns 0 0 0 32.4 KB
master EncodeArgs netcoreapp3.1 98.2μs 268ns 1.04μs 0 0 0 32.4 KB
master EncodeArgs net472 110μs 13.2ns 49.5ns 4.93 0 0 32.5 KB
master EncodeLegacyArgs net6.0 144μs 264ns 1.02μs 0 0 0 2.14 KB
master EncodeLegacyArgs netcoreapp3.1 196μs 43.9ns 164ns 0 0 0 2.14 KB
master EncodeLegacyArgs net472 261μs 31.9ns 124ns 0 0 0 2.14 KB
#7859 EncodeArgs net6.0 77.2μs 64.4ns 241ns 0 0 0 32.4 KB
#7859 EncodeArgs netcoreapp3.1 98.7μs 17ns 65.8ns 0 0 0 32.4 KB
#7859 EncodeArgs net472 109μs 21.5ns 83.4ns 4.91 0 0 32.5 KB
#7859 EncodeLegacyArgs net6.0 147μs 57.9ns 209ns 0 0 0 2.14 KB
#7859 EncodeLegacyArgs netcoreapp3.1 200μs 49.5ns 185ns 0 0 0 2.14 KB
#7859 EncodeLegacyArgs net472 263μs 26.4ns 102ns 0 0 0 2.14 KB
Benchmarks.Trace.Asm.AppSecWafBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master RunWafRealisticBenchmark net6.0 438μs 797ns 2.98μs 0 0 0 4.55 KB
master RunWafRealisticBenchmark netcoreapp3.1 474μs 4.68μs 45.3μs 0 0 0 4.48 KB
master RunWafRealisticBenchmark net472 500μs 564ns 2.03μs 0 0 0 0 b
master RunWafRealisticBenchmarkWithAttack net6.0 329μs 1.5μs 5.82μs 0 0 0 2.24 KB
master RunWafRealisticBenchmarkWithAttack netcoreapp3.1 350μs 3.18μs 30.5μs 0 0 0 2.22 KB
master RunWafRealisticBenchmarkWithAttack net472 369μs 507ns 1.83μs 0 0 0 0 b
#7859 RunWafRealisticBenchmark net6.0 428μs 1.34μs 4.63μs 0 0 0 4.55 KB
#7859 RunWafRealisticBenchmark netcoreapp3.1 467μs 2.18μs 11.7μs 0 0 0 4.48 KB
#7859 RunWafRealisticBenchmark net472 516μs 222ns 769ns 0 0 0 0 b
#7859 RunWafRealisticBenchmarkWithAttack net6.0 331μs 1.75μs 9.74μs 0 0 0 2.24 KB
#7859 RunWafRealisticBenchmarkWithAttack netcoreapp3.1 347μs 3.08μs 29.2μs 0 0 0 2.22 KB
#7859 RunWafRealisticBenchmarkWithAttack net472 372μs 233ns 841ns 0 0 0 0 b
Benchmarks.Trace.AspNetCoreBenchmark - Unknown 🤷 More allocations ⚠️

More allocations ⚠️ in #7859

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.AspNetCoreBenchmark.SendRequest‑netcoreapp3.1 21.25 KB 21.39 KB 146 B 0.69%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendRequest net6.0 85.2μs 48.8ns 176ns 0 0 0 19.03 KB
master SendRequest netcoreapp3.1 97.7μs 362ns 2.45μs 0 0 0 21.25 KB
master SendRequest net472 0ns 0ns 0ns 0 0 0 0 b
#7859 SendRequest net6.0 82.9μs 112ns 419ns 0 0 0 19.03 KB
#7859 SendRequest netcoreapp3.1 98μs 558ns 3.98μs 0 0 0 21.39 KB
#7859 SendRequest net472 0ns 0ns 0ns 0 0 0 0 b
Benchmarks.Trace.CharSliceBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master OriginalCharSlice net6.0 1.93ms 863ns 3.34μs 0 0 0 640 KB
master OriginalCharSlice netcoreapp3.1 3.88ms 1.04μs 3.76μs 0 0 0 640 KB
master OriginalCharSlice net472 2.71ms 768ns 2.77μs 0 0 0 638.98 KB
master OptimizedCharSlice net6.0 1.62ms 1.06μs 4.12μs 0 0 0 0 b
master OptimizedCharSlice netcoreapp3.1 2.75ms 1.44μs 5.18μs 0 0 0 0 b
master OptimizedCharSlice net472 2.06ms 5.97μs 23.1μs 0 0 0 0 b
master OptimizedCharSliceWithPool net6.0 1.06ms 920ns 3.32μs 0 0 0 0 b
master OptimizedCharSliceWithPool netcoreapp3.1 1.91ms 1.1μs 4.11μs 0 0 0 0 b
master OptimizedCharSliceWithPool net472 1.13ms 293ns 1.1μs 0 0 0 0 b
#7859 OriginalCharSlice net6.0 1.96ms 1.29μs 4.65μs 0 0 0 640 KB
#7859 OriginalCharSlice netcoreapp3.1 3.93ms 998ns 3.73μs 0 0 0 640.05 KB
#7859 OriginalCharSlice net472 2.67ms 1μs 3.61μs 0 0 0 638.98 KB
#7859 OptimizedCharSlice net6.0 1.5ms 317ns 1.14μs 0 0 0 0 b
#7859 OptimizedCharSlice netcoreapp3.1 2.81ms 908ns 3.27μs 0 0 0 0 b
#7859 OptimizedCharSlice net472 1.94ms 869ns 3.36μs 0 0 0 0 b
#7859 OptimizedCharSliceWithPool net6.0 1.07ms 1.22μs 4.74μs 0 0 0 0 b
#7859 OptimizedCharSliceWithPool netcoreapp3.1 1.9ms 1.41μs 5.27μs 0 0 0 0 b
#7859 OptimizedCharSliceWithPool net472 1.13ms 320ns 1.15μs 0 0 0 0 b
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark - Slower ⚠️ More allocations ⚠️

Slower ⚠️ in #7859

Benchmark diff/base Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces‑netcoreapp3.1 1.132 721,424.11 816,589.66 several?

More allocations ⚠️ in #7859

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces‑net472 55.58 KB 56.39 KB 807 B 1.45%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 698μs 3.92μs 24.8μs 0 0 0 41.69 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 736μs 4.18μs 31.3μs 0 0 0 41.95 KB
master WriteAndFlushEnrichedTraces net472 841μs 3.98μs 14.9μs 4.46 0 0 55.58 KB
#7859 WriteAndFlushEnrichedTraces net6.0 648μs 550ns 2.13μs 0 0 0 41.79 KB
#7859 WriteAndFlushEnrichedTraces netcoreapp3.1 826μs 4.92μs 49.2μs 0 0 0 41.76 KB
#7859 WriteAndFlushEnrichedTraces net472 852μs 993ns 3.58μs 8.33 4.17 0 56.39 KB
Benchmarks.Trace.DbCommandBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master ExecuteNonQuery net6.0 1.93μs 5.62ns 21.8ns 0 0 0 1.02 KB
master ExecuteNonQuery netcoreapp3.1 2.61μs 4.42ns 17.1ns 0 0 0 1.02 KB
master ExecuteNonQuery net472 2.75μs 4.27ns 16.6ns 0.15 0 0 987 B
#7859 ExecuteNonQuery net6.0 2.01μs 8.07ns 31.2ns 0 0 0 1.02 KB
#7859 ExecuteNonQuery netcoreapp3.1 2.61μs 7.29ns 28.2ns 0 0 0 1.02 KB
#7859 ExecuteNonQuery net472 2.72μs 5.47ns 21.2ns 0.149 0 0 987 B
Benchmarks.Trace.ElasticsearchBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master CallElasticsearch net6.0 1.75μs 8.82ns 41.4ns 0 0 0 1.01 KB
master CallElasticsearch netcoreapp3.1 2.35μs 8.45ns 31.6ns 0 0 0 1.02 KB
master CallElasticsearch net472 3.39μs 3.52ns 13.6ns 0.151 0 0 1.01 KB
master CallElasticsearchAsync net6.0 1.72μs 5.65ns 21.1ns 0 0 0 984 B
master CallElasticsearchAsync netcoreapp3.1 2.49μs 6.14ns 23.8ns 0 0 0 1.07 KB
master CallElasticsearchAsync net472 3.54μs 1.85ns 7.18ns 0.158 0 0 1.07 KB
#7859 CallElasticsearch net6.0 1.74μs 7.72ns 29.9ns 0 0 0 1.01 KB
#7859 CallElasticsearch netcoreapp3.1 2.34μs 8.4ns 32.6ns 0 0 0 1.02 KB
#7859 CallElasticsearch net472 3.52μs 2.57ns 9.97ns 0.157 0 0 1.01 KB
#7859 CallElasticsearchAsync net6.0 1.84μs 0.679ns 2.63ns 0 0 0 984 B
#7859 CallElasticsearchAsync netcoreapp3.1 2.46μs 7.27ns 28.2ns 0 0 0 1.07 KB
#7859 CallElasticsearchAsync net472 3.63μs 2.28ns 8.82ns 0.162 0 0 1.07 KB
Benchmarks.Trace.GraphQLBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master ExecuteAsync net6.0 1.91μs 8.24ns 30.8ns 0 0 0 952 B
master ExecuteAsync netcoreapp3.1 2.47μs 6.65ns 25.8ns 0 0 0 952 B
master ExecuteAsync net472 2.68μs 4.53ns 17.6ns 0.135 0 0 915 B
#7859 ExecuteAsync net6.0 1.94μs 4.71ns 18.2ns 0 0 0 952 B
#7859 ExecuteAsync netcoreapp3.1 2.41μs 8.7ns 30.1ns 0 0 0 952 B
#7859 ExecuteAsync net472 2.67μs 1.45ns 5.42ns 0.132 0 0 915 B
Benchmarks.Trace.HttpClientBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendAsync net6.0 6.95μs 8.49ns 32.9ns 0 0 0 2.34 KB
master SendAsync netcoreapp3.1 8.41μs 29.7ns 115ns 0 0 0 2.89 KB
master SendAsync net472 12.2μs 11.2ns 43.3ns 0.49 0 0 3.14 KB
#7859 SendAsync net6.0 7.2μs 7.53ns 26.1ns 0 0 0 2.34 KB
#7859 SendAsync netcoreapp3.1 8.69μs 6.78ns 26.3ns 0 0 0 2.89 KB
#7859 SendAsync net472 12.4μs 9.93ns 38.5ns 0.495 0 0 3.14 KB
Benchmarks.Trace.Iast.StringAspectsBenchmark - Same speed ✔️ Fewer allocations 🎉

Fewer allocations 🎉 in #7859

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑netcoreapp3.1 276.66 KB 250.48 KB -26.18 KB -9.46%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StringConcatBenchmark net6.0 50.4μs 628ns 6.19μs 0 0 0 42.51 KB
master StringConcatBenchmark netcoreapp3.1 51.1μs 302ns 2.85μs 0 0 0 42.54 KB
master StringConcatBenchmark net472 56.7μs 279ns 1.15μs 0 0 0 49.15 KB
master StringConcatAspectBenchmark net6.0 467μs 1.75μs 7.02μs 0 0 0 257.69 KB
master StringConcatAspectBenchmark netcoreapp3.1 490μs 7.39μs 73.5μs 0 0 0 276.66 KB
master StringConcatAspectBenchmark net472 419μs 1.75μs 6.53μs 0 0 0 270.34 KB
#7859 StringConcatBenchmark net6.0 44.3μs 235ns 1.72μs 0 0 0 42.51 KB
#7859 StringConcatBenchmark netcoreapp3.1 51.9μs 284ns 1.58μs 0 0 0 42.54 KB
#7859 StringConcatBenchmark net472 56μs 278ns 1.18μs 0 0 0 49.15 KB
#7859 StringConcatAspectBenchmark net6.0 505μs 1.76μs 6.11μs 0 0 0 257.74 KB
#7859 StringConcatAspectBenchmark netcoreapp3.1 503μs 1.56μs 8.1μs 0 0 0 250.48 KB
#7859 StringConcatAspectBenchmark net472 406μs 2.09μs 9.57μs 0 0 0 270.34 KB
Benchmarks.Trace.ILoggerBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 2.7μs 12.3ns 49.3ns 0 0 0 1.69 KB
master EnrichedLog netcoreapp3.1 3.51μs 17.7ns 81.2ns 0 0 0 1.7 KB
master EnrichedLog net472 3.82μs 4.76ns 18.4ns 0.248 0 0 1.6 KB
#7859 EnrichedLog net6.0 2.7μs 0.998ns 3.73ns 0 0 0 1.69 KB
#7859 EnrichedLog netcoreapp3.1 3.59μs 18ns 80.7ns 0 0 0 1.7 KB
#7859 EnrichedLog net472 3.91μs 4.07ns 15.2ns 0.254 0 0 1.6 KB
Benchmarks.Trace.Log4netBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 124μs 199ns 772ns 0 0 0 4.31 KB
master EnrichedLog netcoreapp3.1 129μs 220ns 794ns 0 0 0 4.31 KB
master EnrichedLog net472 171μs 406ns 1.57μs 0 0 0 4.51 KB
#7859 EnrichedLog net6.0 128μs 311ns 1.2μs 0 0 0 4.31 KB
#7859 EnrichedLog netcoreapp3.1 133μs 263ns 1.02μs 0 0 0 4.31 KB
#7859 EnrichedLog net472 173μs 296ns 1.15μs 0 0 0 4.51 KB
Benchmarks.Trace.NLogBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 5.02μs 14.9ns 57.8ns 0 0 0 2.24 KB
master EnrichedLog netcoreapp3.1 6.78μs 25.8ns 96.4ns 0 0 0 2.26 KB
master EnrichedLog net472 7.57μs 3.81ns 13.8ns 0.303 0 0 2.05 KB
#7859 EnrichedLog net6.0 5.02μs 15.1ns 58.4ns 0 0 0 2.24 KB
#7859 EnrichedLog netcoreapp3.1 6.75μs 28.4ns 110ns 0 0 0 2.26 KB
#7859 EnrichedLog net472 7.62μs 7.56ns 27.2ns 0.305 0 0 2.05 KB
Benchmarks.Trace.RedisBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendReceive net6.0 1.97μs 5.91ns 22.9ns 0 0 0 1.18 KB
master SendReceive netcoreapp3.1 2.63μs 13.4ns 53.4ns 0 0 0 1.19 KB
master SendReceive net472 3.02μs 7.36ns 28.5ns 0.177 0 0 1.17 KB
#7859 SendReceive net6.0 1.95μs 10.6ns 55.2ns 0 0 0 1.18 KB
#7859 SendReceive netcoreapp3.1 2.63μs 1.7ns 6.15ns 0 0 0 1.19 KB
#7859 SendReceive net472 3μs 4.6ns 17.8ns 0.18 0 0 1.17 KB
Benchmarks.Trace.SerilogBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 4.48μs 3.13ns 12.1ns 0 0 0 1.58 KB
master EnrichedLog netcoreapp3.1 5.64μs 10ns 38.8ns 0 0 0 1.63 KB
master EnrichedLog net472 6.55μs 5.93ns 23ns 0.292 0 0 2.03 KB
#7859 EnrichedLog net6.0 4.42μs 2.88ns 11.2ns 0 0 0 1.58 KB
#7859 EnrichedLog netcoreapp3.1 5.72μs 13.6ns 52.7ns 0 0 0 1.63 KB
#7859 EnrichedLog net472 6.53μs 10.6ns 40.9ns 0.294 0 0 2.03 KB
Benchmarks.Trace.SpanBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartFinishSpan net6.0 794ns 4.03ns 16.1ns 0 0 0 576 B
master StartFinishSpan netcoreapp3.1 966ns 5.2ns 27ns 0 0 0 576 B
master StartFinishSpan net472 905ns 0.138ns 0.518ns 0.0907 0 0 578 B
master StartFinishScope net6.0 926ns 4.69ns 21.5ns 0 0 0 696 B
master StartFinishScope netcoreapp3.1 1.19μs 1.86ns 7.2ns 0 0 0 696 B
master StartFinishScope net472 1.1μs 0.969ns 3.75ns 0.0992 0 0 658 B
master StartFinishTwoScopes net6.0 1.77μs 0.61ns 2.2ns 0 0 0 1.19 KB
master StartFinishTwoScopes netcoreapp3.1 2.16μs 10.1ns 41.4ns 0 0 0 1.19 KB
master StartFinishTwoScopes net472 2.17μs 1.88ns 7.03ns 0.163 0 0 1.08 KB
#7859 StartFinishSpan net6.0 797ns 3.9ns 17.4ns 0 0 0 576 B
#7859 StartFinishSpan netcoreapp3.1 967ns 4.92ns 23.6ns 0 0 0 576 B
#7859 StartFinishSpan net472 905ns 0.273ns 0.984ns 0.0908 0 0 578 B
#7859 StartFinishScope net6.0 958ns 0.169ns 0.61ns 0 0 0 696 B
#7859 StartFinishScope netcoreapp3.1 1.17μs 6.26ns 31.9ns 0 0 0 696 B
#7859 StartFinishScope net472 1.1μs 0.485ns 1.88ns 0.0995 0 0 658 B
#7859 StartFinishTwoScopes net6.0 1.79μs 8.98ns 42.1ns 0 0 0 1.19 KB
#7859 StartFinishTwoScopes netcoreapp3.1 2.26μs 1.38ns 5.34ns 0 0 0 1.19 KB
#7859 StartFinishTwoScopes net472 2.09μs 2.8ns 10.9ns 0.168 0 0 1.08 KB
Benchmarks.Trace.TraceAnnotationsBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master RunOnMethodBegin net6.0 1.09μs 0.666ns 2.58ns 0 0 0 696 B
master RunOnMethodBegin netcoreapp3.1 1.42μs 5.49ns 20.6ns 0 0 0 696 B
master RunOnMethodBegin net472 1.46μs 0.237ns 0.888ns 0.103 0 0 658 B
#7859 RunOnMethodBegin net6.0 1.05μs 5ns 19.4ns 0 0 0 696 B
#7859 RunOnMethodBegin netcoreapp3.1 1.44μs 7.36ns 29.4ns 0 0 0 696 B
#7859 RunOnMethodBegin net472 1.47μs 0.791ns 3.06ns 0.103 0 0 658 B

@dd-trace-dotnet-ci-bot
Copy link

dd-trace-dotnet-ci-bot bot commented Nov 24, 2025

Execution-Time Benchmarks Report ⏱️

Execution-time results for samples comparing This PR (7859) and master.

✅ No regressions detected - check the details below

Full Metrics Comparison

FakeDbCommand

Metric Master (Mean ± 95% CI) Current (Mean ± 95% CI) Change Status
.NET Framework 4.8 - Baseline
duration75.83 ± (75.55 - 76.16) ms75.04 ± (75.26 - 76.08) ms-1.0%
.NET Framework 4.8 - Bailout
duration78.99 ± (78.82 - 79.41) ms79.27 ± (79.26 - 80.09) ms+0.4%✅⬆️
.NET Framework 4.8 - CallTarget+Inlining+NGEN
duration1057.40 ± (1058.45 - 1068.29) ms1076.42 ± (1078.55 - 1090.51) ms+1.8%✅⬆️
.NET Core 3.1 - Baseline
process.internal_duration_ms22.89 ± (22.81 - 22.96) ms22.69 ± (22.62 - 22.77) ms-0.8%
process.time_to_main_ms87.43 ± (87.06 - 87.80) ms86.87 ± (86.45 - 87.29) ms-0.6%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.90 ± (10.89 - 10.90) MB10.92 ± (10.91 - 10.92) MB+0.2%✅⬆️
runtime.dotnet.threads.count12 ± (12 - 12)12 ± (12 - 12)+0.0%
.NET Core 3.1 - Bailout
process.internal_duration_ms22.90 ± (22.82 - 22.97) ms22.73 ± (22.66 - 22.80) ms-0.7%
process.time_to_main_ms88.10 ± (87.77 - 88.43) ms88.27 ± (87.80 - 88.74) ms+0.2%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.94 ± (10.94 - 10.94) MB10.96 ± (10.96 - 10.96) MB+0.2%✅⬆️
runtime.dotnet.threads.count13 ± (13 - 13)13 ± (13 - 13)+0.0%
.NET Core 3.1 - CallTarget+Inlining+NGEN
process.internal_duration_ms223.89 ± (222.16 - 225.62) ms221.11 ± (219.84 - 222.38) ms-1.2%
process.time_to_main_ms500.05 ± (498.87 - 501.23) ms501.72 ± (500.41 - 503.03) ms+0.3%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed47.83 ± (47.81 - 47.85) MB47.90 ± (47.88 - 47.92) MB+0.1%✅⬆️
runtime.dotnet.threads.count28 ± (28 - 28)28 ± (28 - 28)+0.0%
.NET 6 - Baseline
process.internal_duration_ms21.69 ± (21.63 - 21.76) ms21.57 ± (21.49 - 21.65) ms-0.6%
process.time_to_main_ms75.84 ± (75.52 - 76.16) ms76.05 ± (75.66 - 76.44) ms+0.3%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.60 ± (10.60 - 10.60) MB10.64 ± (10.64 - 10.64) MB+0.4%✅⬆️
runtime.dotnet.threads.count10 ± (10 - 10)10 ± (10 - 10)+0.0%
.NET 6 - Bailout
process.internal_duration_ms21.75 ± (21.67 - 21.83) ms21.68 ± (21.59 - 21.76) ms-0.3%
process.time_to_main_ms77.53 ± (77.17 - 77.88) ms78.58 ± (78.17 - 78.99) ms+1.4%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.65 ± (10.65 - 10.66) MB10.74 ± (10.74 - 10.74) MB+0.8%✅⬆️
runtime.dotnet.threads.count11 ± (11 - 11)11 ± (11 - 11)+0.0%
.NET 6 - CallTarget+Inlining+NGEN
process.internal_duration_ms212.13 ± (210.92 - 213.34) ms211.13 ± (209.97 - 212.30) ms-0.5%
process.time_to_main_ms467.85 ± (466.76 - 468.95) ms470.43 ± (469.28 - 471.58) ms+0.6%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed48.06 ± (48.04 - 48.08) MB48.04 ± (48.01 - 48.07) MB-0.0%
runtime.dotnet.threads.count28 ± (28 - 28)28 ± (28 - 28)-0.0%
.NET 8 - Baseline
process.internal_duration_ms19.78 ± (19.71 - 19.84) ms20.15 ± (20.07 - 20.23) ms+1.9%✅⬆️
process.time_to_main_ms74.68 ± (74.32 - 75.04) ms76.05 ± (75.66 - 76.44) ms+1.8%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed7.65 ± (7.64 - 7.66) MB7.65 ± (7.65 - 7.66) MB+0.0%✅⬆️
runtime.dotnet.threads.count10 ± (10 - 10)10 ± (10 - 10)+0.0%
.NET 8 - Bailout
process.internal_duration_ms19.66 ± (19.59 - 19.72) ms19.90 ± (19.83 - 19.98) ms+1.3%✅⬆️
process.time_to_main_ms75.68 ± (75.37 - 76.00) ms77.33 ± (76.88 - 77.78) ms+2.2%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed7.70 ± (7.70 - 7.71) MB7.72 ± (7.71 - 7.73) MB+0.2%✅⬆️
runtime.dotnet.threads.count11 ± (11 - 11)11 ± (11 - 11)+0.0%
.NET 8 - CallTarget+Inlining+NGEN
process.internal_duration_ms189.46 ± (188.56 - 190.36) ms195.93 ± (194.81 - 197.05) ms+3.4%✅⬆️
process.time_to_main_ms449.97 ± (448.92 - 451.01) ms461.40 ± (460.10 - 462.70) ms+2.5%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed36.32 ± (36.29 - 36.36) MB36.45 ± (36.42 - 36.49) MB+0.4%✅⬆️
runtime.dotnet.threads.count27 ± (27 - 27)27 ± (27 - 27)+0.1%✅⬆️

HttpMessageHandler

Metric Master (Mean ± 95% CI) Current (Mean ± 95% CI) Change Status
.NET Framework 4.8 - Baseline
duration193.77 ± (193.60 - 194.35) ms193.25 ± (193.19 - 194.08) ms-0.3%
.NET Framework 4.8 - Bailout
duration197.31 ± (197.17 - 197.75) ms196.54 ± (196.35 - 196.91) ms-0.4%
.NET Framework 4.8 - CallTarget+Inlining+NGEN
duration1116.06 ± (1120.27 - 1129.06) ms1113.87 ± (1113.10 - 1119.35) ms-0.2%
.NET Core 3.1 - Baseline
process.internal_duration_ms189.51 ± (189.13 - 189.89) ms188.69 ± (188.28 - 189.10) ms-0.4%
process.time_to_main_ms81.72 ± (81.49 - 81.96) ms80.83 ± (80.62 - 81.03) ms-1.1%
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed16.15 ± (16.12 - 16.18) MB16.05 ± (16.02 - 16.08) MB-0.6%
runtime.dotnet.threads.count20 ± (20 - 20)20 ± (19 - 20)-0.6%
.NET Core 3.1 - Bailout
process.internal_duration_ms188.37 ± (188.05 - 188.70) ms187.64 ± (187.34 - 187.93) ms-0.4%
process.time_to_main_ms82.76 ± (82.62 - 82.91) ms82.04 ± (81.90 - 82.18) ms-0.9%
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed16.16 ± (16.13 - 16.19) MB16.15 ± (16.12 - 16.18) MB-0.1%
runtime.dotnet.threads.count21 ± (21 - 21)21 ± (21 - 21)+0.1%✅⬆️
.NET Core 3.1 - CallTarget+Inlining+NGEN
process.internal_duration_ms403.09 ± (400.43 - 405.75) ms396.31 ± (393.99 - 398.64) ms-1.7%
process.time_to_main_ms475.20 ± (474.53 - 475.87) ms474.76 ± (474.12 - 475.41) ms-0.1%
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed58.86 ± (58.74 - 58.97) MB58.60 ± (58.47 - 58.73) MB-0.4%
runtime.dotnet.threads.count29 ± (29 - 29)30 ± (29 - 30)+0.2%✅⬆️
.NET 6 - Baseline
process.internal_duration_ms192.34 ± (191.96 - 192.73) ms192.35 ± (192.01 - 192.70) ms+0.0%✅⬆️
process.time_to_main_ms70.53 ± (70.35 - 70.70) ms70.11 ± (69.94 - 70.28) ms-0.6%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed16.33 ± (16.23 - 16.43) MB16.14 ± (16.01 - 16.27) MB-1.2%
runtime.dotnet.threads.count19 ± (19 - 19)18 ± (18 - 19)-2.2%
.NET 6 - Bailout
process.internal_duration_ms194.99 ± (194.50 - 195.48) ms191.57 ± (191.30 - 191.84) ms-1.8%
process.time_to_main_ms72.51 ± (72.31 - 72.70) ms71.07 ± (70.98 - 71.16) ms-2.0%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed16.48 ± (16.45 - 16.50) MB16.10 ± (15.95 - 16.25) MB-2.3%
runtime.dotnet.threads.count20 ± (20 - 20)20 ± (20 - 20)-1.6%
.NET 6 - CallTarget+Inlining+NGEN
process.internal_duration_ms410.98 ± (408.75 - 413.21) ms417.64 ± (415.69 - 419.59) ms+1.6%✅⬆️
process.time_to_main_ms444.17 ± (443.49 - 444.86) ms455.33 ± (453.87 - 456.80) ms+2.5%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed59.10 ± (58.96 - 59.23) MB59.38 ± (59.32 - 59.45) MB+0.5%✅⬆️
runtime.dotnet.threads.count29 ± (29 - 30)30 ± (29 - 30)+0.2%✅⬆️
.NET 8 - Baseline
process.internal_duration_ms190.95 ± (190.68 - 191.22) ms191.71 ± (191.29 - 192.13) ms+0.4%✅⬆️
process.time_to_main_ms70.10 ± (69.92 - 70.27) ms69.85 ± (69.68 - 70.03) ms-0.3%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed11.82 ± (11.79 - 11.84) MB11.74 ± (11.72 - 11.76) MB-0.6%
runtime.dotnet.threads.count18 ± (18 - 18)18 ± (18 - 18)+0.4%✅⬆️
.NET 8 - Bailout
process.internal_duration_ms190.42 ± (190.15 - 190.70) ms193.85 ± (193.35 - 194.35) ms+1.8%✅⬆️
process.time_to_main_ms71.15 ± (71.03 - 71.26) ms71.77 ± (71.57 - 71.98) ms+0.9%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed11.84 ± (11.81 - 11.86) MB11.76 ± (11.73 - 11.78) MB-0.7%
runtime.dotnet.threads.count19 ± (19 - 19)19 ± (19 - 19)+0.3%✅⬆️
.NET 8 - CallTarget+Inlining+NGEN
process.internal_duration_ms365.86 ± (364.42 - 367.29) ms371.94 ± (370.19 - 373.70) ms+1.7%✅⬆️
process.time_to_main_ms432.55 ± (431.96 - 433.15) ms439.25 ± (438.39 - 440.12) ms+1.5%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed48.00 ± (47.98 - 48.03) MB47.89 ± (47.85 - 47.93) MB-0.2%
runtime.dotnet.threads.count29 ± (29 - 29)29 ± (29 - 29)-0.4%
Comparison explanation

Execution-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:

  • Welch test with statistical test for significance of 5%
  • Only results indicating a difference greater than 5% and 5 ms are considered.

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 charts
FakeDbCommand (.NET Framework 4.8)
gantt
    title Execution time (ms) FakeDbCommand (.NET Framework 4.8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7859) - mean (76ms)  : 69, 82
    master - mean (76ms)  : 71, 80

    section Bailout
    This PR (7859) - mean (80ms)  : 74, 86
    master - mean (79ms)  : 75, 83

    section CallTarget+Inlining+NGEN
    This PR (7859) - mean (1,085ms)  : 993, 1176
    master - mean (1,063ms)  : 990, 1137

Loading
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 (7859) - mean (117ms)  : 109, 125
    master - mean (118ms)  : 112, 124

    section Bailout
    This PR (7859) - mean (119ms)  : 110, 127
    master - mean (118ms)  : 111, 125

    section CallTarget+Inlining+NGEN
    This PR (7859) - mean (764ms)  : 732, 797
    master - mean (764ms)  : 729, 799

Loading
FakeDbCommand (.NET 6)
gantt
    title Execution time (ms) FakeDbCommand (.NET 6)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7859) - mean (105ms)  : 97, 113
    master - mean (104ms)  : 99, 110

    section Bailout
    This PR (7859) - mean (107ms)  : 98, 117
    master - mean (106ms)  : 98, 114

    section CallTarget+Inlining+NGEN
    This PR (7859) - mean (710ms)  : 679, 741
    master - mean (707ms)  : 673, 741

Loading
FakeDbCommand (.NET 8)
gantt
    title Execution time (ms) FakeDbCommand (.NET 8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7859) - mean (105ms)  : 96, 114
    master - mean (103ms)  : 95, 111

    section Bailout
    This PR (7859) - mean (106ms)  : 96, 116
    master - mean (104ms)  : 97, 110

    section CallTarget+Inlining+NGEN
    This PR (7859) - mean (699ms)  : 656, 741
    master - mean (672ms)  : 639, 704

Loading
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 (7859) - mean (194ms)  : 189, 198
    master - mean (194ms)  : 190, 198

    section Bailout
    This PR (7859) - mean (197ms)  : 194, 199
    master - mean (197ms)  : 195, 200

    section CallTarget+Inlining+NGEN
    This PR (7859) - mean (1,116ms)  : 1072, 1161
    master - mean (1,125ms)  : 1060, 1190

Loading
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 (7859) - mean (278ms)  : 273, 283
    master - mean (280ms)  : 274, 285

    section Bailout
    This PR (7859) - mean (278ms)  : 274, 282
    master - mean (280ms)  : 275, 285

    section CallTarget+Inlining+NGEN
    This PR (7859) - mean (906ms)  : 859, 952
    master - mean (919ms)  : 866, 972

Loading
HttpMessageHandler (.NET 6)
gantt
    title Execution time (ms) HttpMessageHandler (.NET 6)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7859) - mean (271ms)  : 266, 275
    master - mean (271ms)  : 265, 278

    section Bailout
    This PR (7859) - mean (271ms)  : 267, 274
    master - mean (276ms)  : 264, 289

    section CallTarget+Inlining+NGEN
    This PR (7859) - mean (905ms)  : 857, 953
    master - mean (896ms)  : 861, 931

Loading
HttpMessageHandler (.NET 8)
gantt
    title Execution time (ms) HttpMessageHandler (.NET 8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7859) - mean (271ms)  : 264, 278
    master - mean (271ms)  : 267, 275

    section Bailout
    This PR (7859) - mean (276ms)  : 267, 284
    master - mean (271ms)  : 268, 274

    section CallTarget+Inlining+NGEN
    This PR (7859) - mean (844ms)  : 796, 891
    master - mean (830ms)  : 804, 856

Loading

@tonyredondo tonyredondo changed the title [Debugger] Add agent-less support to Exception Replay [Debugger-Test Optimization] Add agent-less support to ER Nov 25, 2025
@tylfin
Copy link
Member

tylfin commented Dec 1, 2025

Is this something we'll eventually need to support across the board? If so, we should probably add an accompanying system-test to confirm parity

Copy link
Member

@andrewlock andrewlock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of minor suggestions, but overall LGTM, only potential issue is the new process for adding configurations.

No integration tests though - is it possible to add any (may need to be a separate PR I realise)

Comment on lines +182 to +192

/// <summary>
/// Configuration key for enabling or disabling agentless Exception Replay uploads.
/// Default value is false.
/// </summary>
public const string ExceptionReplayAgentlessEnabled = "DD_EXCEPTION_REPLAY_AGENTLESS_ENABLED";

/// <summary>
/// Configuration key for overriding the agentless Exception Replay intake URL.
/// Default value is derived from DD_SITE (https://debugger-intake.&lt;site&gt;/api/v2/debugger).
/// </summary>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't add the keys here directly, right @anna-git? They need to be added to the supported-configurations.json and supported-configurations-docs.yaml files instead

// Set up the snapshots sink.
var snapshotSlicer = SnapshotSlicer.Create(debuggerSettings);
_snapshotSink = SnapshotSink.Create(debuggerSettings, snapshotSlicer);
// TODO: respond to changes in exporter settings
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would leave this warning, because it's still true 😉

if (string.IsNullOrWhiteSpace(settings.AgentlessApiKey))
{
Log.Error("Exception Replay agentless uploads enabled but DD_API_KEY is not set. Disabling Exception Replay.");
throw new InvalidOperationException("Exception Replay agentless mode requires DD_API_KEY.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need/want to throw here, or should we just return null and bail out in the callee without throwing? We've already logged the error, so I don't think it's necessary?


if (string.IsNullOrWhiteSpace(settings.AgentlessApiKey))
{
Log.Error("Exception Replay agentless uploads enabled but DD_API_KEY is not set. Disabling Exception Replay.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if we get a lot of value reporting this to telemetry?

Suggested change
Log.Error("Exception Replay agentless uploads enabled but DD_API_KEY is not set. Disabling Exception Replay.");
Log.ErrorSkipTelemetry("Exception Replay agentless uploads enabled but DD_API_KEY is not set. Disabling Exception Replay.");


if (!TryResolveAgentlessEndpoint(settings, out var baseUri, out var relativePath))
{
Log.Error("Exception Replay agentless uploads enabled but a valid intake URL could not be determined. Disabling Exception Replay.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to report this one to telemetry? It's probably just customer misconfiguration, right? 🤔

Suggested change
Log.Error("Exception Replay agentless uploads enabled but a valid intake URL could not be determined. Disabling Exception Replay.");
Log.ErrorSkipTelemetry("Exception Replay agentless uploads enabled but a valid intake URL could not be determined. Disabling Exception Replay.");

Comment on lines +68 to +79
ExceptionReplayTransportInfo transportInfo;

var snapshotUploadApi = DebuggerUploadApiFactory.CreateSnapshotUploadApi(apiFactory, discoveryService, gitMetadataTagsProvider);
try
{
transportInfo = ExceptionReplayTransportFactory.Create(tracer.Settings, Settings, discoveryService);
}
catch (InvalidOperationException ex)
{
Log.Error(ex, "Exception Replay transport could not be initialized in agentless mode. Disabling Exception Replay.");
_isDisabled = true;
return;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you take my suggestion below of not throwing, then this becomes:

Suggested change
ExceptionReplayTransportInfo transportInfo;
var snapshotUploadApi = DebuggerUploadApiFactory.CreateSnapshotUploadApi(apiFactory, discoveryService, gitMetadataTagsProvider);
try
{
transportInfo = ExceptionReplayTransportFactory.Create(tracer.Settings, Settings, discoveryService);
}
catch (InvalidOperationException ex)
{
Log.Error(ex, "Exception Replay transport could not be initialized in agentless mode. Disabling Exception Replay.");
_isDisabled = true;
return;
}
var transportInfo = ExceptionReplayTransportFactory.Create(tracer.Settings, Settings, discoveryService);
if (transportInfo is null)
{
_isDisabled = true;
return;
}

which seems preferable to me

: base(apiRequestFactory, gitMetadataTagsProvider)
{
discoveryService.SubscribeToChanges(c =>
if (!string.IsNullOrEmpty(staticEndpoint))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StringUtil for nullable annotations in .NET FX 😄

Suggested change
if (!string.IsNullOrEmpty(staticEndpoint))
if (!StringUtil.IsNullOrEmpty(staticEndpoint))

Comment on lines +86 to +94
var nestedType = typeof(ExceptionReplayTransportFactory)
.GetNestedType("HeaderInjectingApiRequestFactory", BindingFlags.NonPublic);
nestedType.Should().NotBeNull();
var ctor = nestedType!.GetConstructor(
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
binder: null,
new[] { typeof(IApiRequestFactory), typeof(string) },
modifiers: null);
ctor.Should().NotBeNull();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just make it internal if you want to test it 😛

public Task DisposeAsync() => Task.CompletedTask;
}

private sealed class RecordingApiRequestFactory : IApiRequestFactory
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure we already have test implementations you could use instead? 🤔

Comment on lines +432 to +433
"DD_EXCEPTION_REPLAY_AGENTLESS_ENABLED": "dd_exception_replay_agentless_enabled",
"DD_EXCEPTION_REPLAY_AGENTLESS_URL": "dd_exception_replay_agentless_url",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to add these to the dd-go version too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants