Skip to content

Add dd-autoinstrumentation CLI with LLM-native structured output#8313

Merged
vandonr merged 21 commits into
masterfrom
steven/auto-instrumentation-gen-cli-v2
Jul 9, 2026
Merged

Add dd-autoinstrumentation CLI with LLM-native structured output#8313
vandonr merged 21 commits into
masterfrom
steven/auto-instrumentation-gen-cli-v2

Conversation

@bouwkast

@bouwkast bouwkast commented Mar 16, 2026

Copy link
Copy Markdown
Collaborator

Summary of changes

Adds a new CLI tool (dd-autoinstrumentation) for auto-instrumentation code generation, designed
for scriptable and AI-agent-driven workflows with structured JSON output.

Reason for change

Creating integrations currently requires either the GUI or manual boilerplate. A CLI with structured
JSON output enables LLM agents to autonomously discover types/methods in an assembly, generate
instrumentation code, and recover from errors — all without human intervention.

Implementation details

New Datadog.AutoInstrumentation.Generator.Cli project with two commands:

inspect — assembly discovery

  • --list-types: lists all non-compiler-generated types with visibility, kind, method count
  • --list-methods <type>: lists instrumentable methods with parameters, async detection, overload
    index/count

generate — code generation

  • Resolves method from assembly/type/method with overload disambiguation (--overload-index,
    --parameter-types)
  • Smart defaults auto-detect async/static/void methods (disable with --no-auto-detect)
  • Configuration via --set key=value, --config '{json}', or --config-file path.json
  • Shortcut flags: --no-method-begin, --no-method-end, --async-method-end

--json flag (global) — all output (success and error) as structured JSON on stdout with:

  • Machine-readable error codes (FILE_NOT_FOUND, TYPE_NOT_FOUND, AMBIGUOUS_OVERLOAD,
    BAD_ASSEMBLY, etc.)
  • AMBIGUOUS_OVERLOAD includes full overload list in response data for immediate retry
  • inspect output includes overloadIndex/overloadCount so agents know upfront if disambiguation
    is needed

Nuke integrationRunInstrumentationGeneratorCli target with direct parameters and
--generator-args passthrough.

Documentation:

  • docs/development/InstrumentationGenerator.md — comprehensive reference for both GUI and CLI
  • docs/development/for-ai/InstrumentationGenerator-CLI.md — LLM-focused reference with full JSON
    schemas, error recovery patterns, and recommended autonomous workflow

Test coverage

No automated tests in this PR — this is a developer/AI tooling utility, not a production code path.
Manual testing performed against real assemblies for all commands, error paths, and JSON output.

Other details

#8312

🤖 Generated with Claude Code

@bouwkast bouwkast added the AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos label Mar 16, 2026
@bouwkast
bouwkast force-pushed the steven/auto-instrumentation-gen-cli-v2 branch from 78661d7 to fc5fd18 Compare March 16, 2026 19:33
@pr-commenter

pr-commenter Bot commented Mar 16, 2026

Copy link
Copy Markdown

Benchmarks

Benchmark execution time: 2026-07-09 13:14:50

Comparing candidate commit 8adb8f4 in PR branch steven/auto-instrumentation-gen-cli-v2 with baseline commit e972123 in branch master.

📊 Benchmarking dashboard

Found 2 performance improvements and 1 performance regressions! Performance is the same for 69 metrics, 0 unstable metrics, 66 known flaky benchmarks, 60 flaky benchmarks without significant changes.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TracerBenchmark.StartRootSpan net472

  • 🟩 throughput [+8961.351op/s; +10123.996op/s] or [+5.039%; +5.693%]

scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TracerBenchmark.StartSpan_SetActive net472

  • 🟩 throughput [+9597.240op/s; +10302.374op/s] or [+5.830%; +6.259%]

scenario:Benchmarks.Trace.HttpClientBenchmark.SendAsync net472

  • 🟥 throughput [-5808.563op/s; -5341.563op/s] or [-6.631%; -6.098%]

Known flaky benchmarks

These benchmarks are marked as flaky and will not trigger a failure. Modify FLAKY_BENCHMARKS_REGEX to control which benchmarks are marked as flaky.

scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_GetContext_Sampled net472

  • 🟥 throughput [-14245.122op/s; -12621.187op/s] or [-7.174%; -6.356%]

scenario:Benchmarks.Trace.ActivityBenchmark.StartStopWithChild net472

  • 🟥 throughput [-7216.078op/s; -6403.024op/s] or [-8.556%; -7.592%]

scenario:Benchmarks.Trace.AgentWriterBenchmark.WriteAndFlushEnrichedTraces net472

  • 🟥 execution_time [+310.866ms; +318.512ms] or [+154.263%; +158.057%]
  • 🟥 throughput [-43.171op/s; -39.481op/s] or [-7.767%; -7.103%]

scenario:Benchmarks.Trace.AgentWriterBenchmark.WriteAndFlushEnrichedTraces net6.0

  • 🟥 execution_time [+378.966ms; +380.444ms] or [+299.406%; +300.574%]
  • 🟩 throughput [+98.161op/s; +104.105op/s] or [+12.942%; +13.726%]

scenario:Benchmarks.Trace.AgentWriterBenchmark.WriteAndFlushEnrichedTraces netcoreapp3.1

  • 🟥 execution_time [+391.389ms; +394.194ms] or [+346.365%; +348.847%]

scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleMoreComplexBody net472

  • 🟥 allocated_mem [+1.308KB; +1.308KB] or [+27.528%; +27.540%]

scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleMoreComplexBody net6.0

  • 🟥 allocated_mem [+471 bytes; +472 bytes] or [+9.976%; +9.987%]

scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleMoreComplexBody netcoreapp3.1

  • 🟥 allocated_mem [+1.272KB; +1.272KB] or [+27.500%; +27.510%]

scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleSimpleBody net472

  • 🟥 allocated_mem [+1.307KB; +1.307KB] or [+105.743%; +105.758%]
  • 🟥 throughput [-275052.539op/s; -271183.300op/s] or [-28.084%; -27.689%]

scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleSimpleBody net6.0

  • 🟥 allocated_mem [+471 bytes; +472 bytes] or [+38.557%; +38.566%]
  • 🟩 execution_time [-26.730ms; -21.875ms] or [-11.921%; -9.755%]

scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleSimpleBody netcoreapp3.1

  • 🟥 allocated_mem [+1.272KB; +1.272KB] or [+105.288%; +105.304%]
  • 🟥 throughput [-163408.507op/s; -145965.428op/s] or [-23.479%; -20.972%]

scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.ObjectExtractorMoreComplexBody net6.0

  • 🟩 throughput [+8790.682op/s; +11759.978op/s] or [+5.593%; +7.483%]

scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.ObjectExtractorMoreComplexBody netcoreapp3.1

  • 🟩 throughput [+10657.324op/s; +13323.432op/s] or [+8.490%; +10.614%]

scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.ObjectExtractorSimpleBody net6.0

  • 🟩 throughput [+473050.907op/s; +488359.289op/s] or [+15.774%; +16.284%]

scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.ObjectExtractorSimpleBody netcoreapp3.1

  • 🟩 execution_time [-19.096ms; -14.758ms] or [-8.803%; -6.803%]
  • 🟩 throughput [+205082.095op/s; +258802.699op/s] or [+8.140%; +10.273%]

scenario:Benchmarks.Trace.Asm.AppSecEncoderBenchmark.EncodeArgs net472

  • 🟥 execution_time [+299.043ms; +299.808ms] or [+149.422%; +149.804%]

scenario:Benchmarks.Trace.Asm.AppSecEncoderBenchmark.EncodeArgs net6.0

  • 🟥 execution_time [+300.921ms; +304.959ms] or [+151.755%; +153.792%]

scenario:Benchmarks.Trace.Asm.AppSecEncoderBenchmark.EncodeArgs netcoreapp3.1

  • 🟥 execution_time [+299.461ms; +301.848ms] or [+150.845%; +152.048%]

scenario:Benchmarks.Trace.Asm.AppSecEncoderBenchmark.EncodeLegacyArgs net472

  • 🟥 execution_time [+295.652ms; +296.898ms] or [+145.213%; +145.824%]

scenario:Benchmarks.Trace.Asm.AppSecEncoderBenchmark.EncodeLegacyArgs net6.0

  • 🟥 execution_time [+292.117ms; +294.991ms] or [+142.805%; +144.210%]

scenario:Benchmarks.Trace.Asm.AppSecEncoderBenchmark.EncodeLegacyArgs netcoreapp3.1

  • 🟥 execution_time [+303.255ms; +306.197ms] or [+151.566%; +153.037%]

scenario:Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmark net6.0

  • 🟥 execution_time [+22.946µs; +49.911µs] or [+5.263%; +11.447%]
  • 🟥 throughput [-243.402op/s; -122.129op/s] or [-10.582%; -5.310%]

scenario:Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmarkWithAttack net6.0

  • 🟥 execution_time [+23.475µs; +47.106µs] or [+7.494%; +15.039%]
  • 🟥 throughput [-437.691op/s; -238.849op/s] or [-13.644%; -7.446%]

scenario:Benchmarks.Trace.AspNetCoreBenchmark.SendRequest net472

  • 🟥 execution_time [+299.073ms; +299.879ms] or [+149.268%; +149.670%]

scenario:Benchmarks.Trace.AspNetCoreBenchmark.SendRequest net6.0

  • 🟥 execution_time [+418.446ms; +426.217ms] or [+454.659%; +463.102%]
  • 🟩 throughput [+647.203op/s; +871.765op/s] or [+5.318%; +7.163%]

scenario:Benchmarks.Trace.AspNetCoreBenchmark.SendRequest netcoreapp3.1

  • unstable execution_time [+273.411ms; +336.982ms] or [+207.598%; +255.867%]

scenario:Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces net472

  • unstable execution_time [+341.046ms; +378.512ms] or [+156.810%; +174.036%]
  • 🟥 throughput [-516.106op/s; -480.297op/s] or [-46.764%; -43.520%]

scenario:Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces net6.0

  • unstable execution_time [+201.908ms; +335.165ms] or [+86.045%; +142.833%]
  • 🟥 throughput [-676.084op/s; -592.575op/s] or [-45.095%; -39.525%]

scenario:Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces netcoreapp3.1

  • 🟥 execution_time [+347.653ms; +360.635ms] or [+207.937%; +215.702%]
  • 🟥 throughput [-416.651op/s; -380.568op/s] or [-29.011%; -26.498%]

scenario:Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSlice net472

  • 🟩 execution_time [-119.315µs; -104.090µs] or [-6.004%; -5.238%]
  • 🟩 throughput [+27.944op/s; +32.210op/s] or [+5.553%; +6.400%]

scenario:Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSlice netcoreapp3.1

  • unstable throughput [+16.568op/s; +61.260op/s] or [+4.762%; +17.609%]

scenario:Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSliceWithPool net6.0

  • 🟩 execution_time [-112.123µs; -56.003µs] or [-10.399%; -5.194%]
  • 🟩 throughput [+57.136op/s; +123.362op/s] or [+6.161%; +13.301%]

scenario:Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSliceWithPool netcoreapp3.1

  • unstable execution_time [-327.117µs; -61.253µs] or [-17.525%; -3.282%]
  • unstable throughput [+62.645op/s; +213.886op/s] or [+11.693%; +39.923%]

scenario:Benchmarks.Trace.CharSliceBenchmark.OriginalCharSlice net6.0

  • 🟩 execution_time [-174.639µs; -124.551µs] or [-8.847%; -6.309%]
  • 🟩 throughput [+36.017op/s; +49.377op/s] or [+7.110%; +9.747%]

scenario:Benchmarks.Trace.ElasticsearchBenchmark.CallElasticsearch net472

  • 🟥 execution_time [+303.289ms; +304.816ms] or [+152.730%; +153.500%]

scenario:Benchmarks.Trace.ElasticsearchBenchmark.CallElasticsearch net6.0

  • 🟥 execution_time [+299.759ms; +301.201ms] or [+150.210%; +150.933%]

scenario:Benchmarks.Trace.ElasticsearchBenchmark.CallElasticsearch netcoreapp3.1

  • 🟥 execution_time [+302.857ms; +306.344ms] or [+152.143%; +153.894%]

scenario:Benchmarks.Trace.ElasticsearchBenchmark.CallElasticsearchAsync net472

  • 🟥 execution_time [+300.729ms; +303.219ms] or [+151.016%; +152.266%]

scenario:Benchmarks.Trace.ElasticsearchBenchmark.CallElasticsearchAsync net6.0

  • 🟥 execution_time [+296.929ms; +309.385ms] or [+146.818%; +152.977%]

scenario:Benchmarks.Trace.ElasticsearchBenchmark.CallElasticsearchAsync netcoreapp3.1

  • 🟥 execution_time [+300.737ms; +306.027ms] or [+152.427%; +155.108%]

scenario:Benchmarks.Trace.GraphQLBenchmark.ExecuteAsync net472

  • 🟥 execution_time [+301.039ms; +303.192ms] or [+151.095%; +152.175%]

scenario:Benchmarks.Trace.GraphQLBenchmark.ExecuteAsync net6.0

  • 🟥 execution_time [+299.096ms; +302.278ms] or [+149.072%; +150.658%]
  • 🟩 throughput [+43931.752op/s; +56854.427op/s] or [+8.723%; +11.289%]

scenario:Benchmarks.Trace.GraphQLBenchmark.ExecuteAsync netcoreapp3.1

  • 🟥 execution_time [+302.090ms; +306.303ms] or [+150.287%; +152.383%]

scenario:Benchmarks.Trace.ILoggerBenchmark.EnrichedLog net6.0

  • 🟩 execution_time [-16.905ms; -13.230ms] or [-7.861%; -6.152%]
  • 🟩 throughput [+20058.574op/s; +27568.827op/s] or [+5.503%; +7.563%]

scenario:Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark net472

  • unstable execution_time [+13.920µs; +59.654µs] or [+3.438%; +14.735%]

scenario:Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark net6.0

  • 🟩 allocated_mem [-16.896KB; -16.873KB] or [-6.163%; -6.155%]
  • unstable execution_time [-29031.525ns; +28554.284ns] or [-5.738%; +5.644%]
  • unstable throughput [-102.510op/s; +97.927op/s] or [-5.115%; +4.887%]

scenario:Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark netcoreapp3.1

  • unstable execution_time [-32396.869ns; +30479.826ns] or [-5.614%; +5.282%]

scenario:Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark net6.0

  • 🟥 execution_time [+5.481µs; +9.554µs] or [+12.955%; +22.583%]
  • 🟥 throughput [-4472.099op/s; -2680.046op/s] or [-18.826%; -11.282%]

scenario:Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark netcoreapp3.1

  • unstable execution_time [-13.691µs; -5.227µs] or [-21.242%; -8.109%]
  • unstable throughput [+1382.240op/s; +3154.410op/s] or [+8.480%; +19.353%]

scenario:Benchmarks.Trace.Log4netBenchmark.EnrichedLog net472

  • 🟥 execution_time [+302.283ms; +303.375ms] or [+152.791%; +153.343%]

scenario:Benchmarks.Trace.Log4netBenchmark.EnrichedLog net6.0

  • 🟥 execution_time [+302.418ms; +305.910ms] or [+153.930%; +155.707%]

scenario:Benchmarks.Trace.Log4netBenchmark.EnrichedLog netcoreapp3.1

  • 🟥 execution_time [+298.724ms; +301.911ms] or [+149.548%; +151.144%]

scenario:Benchmarks.Trace.RedisBenchmark.SendReceive net6.0

  • 🟩 throughput [+32123.748op/s; +34952.491op/s] or [+6.080%; +6.616%]

scenario:Benchmarks.Trace.SerilogBenchmark.EnrichedLog net472

  • 🟥 execution_time [+299.289ms; +301.030ms] or [+149.169%; +150.036%]

scenario:Benchmarks.Trace.SerilogBenchmark.EnrichedLog net6.0

  • 🟥 execution_time [+301.712ms; +302.903ms] or [+151.505%; +152.104%]

scenario:Benchmarks.Trace.SerilogBenchmark.EnrichedLog netcoreapp3.1

  • 🟥 execution_time [+303.552ms; +305.865ms] or [+153.942%; +155.115%]

scenario:Benchmarks.Trace.SingleSpanAspNetCoreBenchmark.SingleSpanAspNetCore net472

  • 🟥 execution_time [+300.099ms; +301.380ms] or [+149.691%; +150.330%]
  • 🟩 throughput [+61200620.002op/s; +61547310.687op/s] or [+44.570%; +44.823%]

scenario:Benchmarks.Trace.SingleSpanAspNetCoreBenchmark.SingleSpanAspNetCore net6.0

  • 🟥 execution_time [+414.151ms; +421.476ms] or [+515.071%; +524.180%]

scenario:Benchmarks.Trace.SingleSpanAspNetCoreBenchmark.SingleSpanAspNetCore netcoreapp3.1

  • 🟥 execution_time [+298.539ms; +299.673ms] or [+148.904%; +149.470%]

scenario:Benchmarks.Trace.SpanBenchmark.StartFinishScope net6.0

  • 🟩 throughput [+97281.497op/s; +106380.645op/s] or [+9.083%; +9.932%]

scenario:Benchmarks.Trace.SpanBenchmark.StartFinishScope netcoreapp3.1

  • 🟩 throughput [+43512.377op/s; +63864.235op/s] or [+5.036%; +7.392%]

scenario:Benchmarks.Trace.SpanBenchmark.StartFinishSpan net6.0

  • 🟩 throughput [+68036.180op/s; +99728.429op/s] or [+5.266%; +7.719%]

scenario:Benchmarks.Trace.SpanBenchmark.StartFinishSpan netcoreapp3.1

  • 🟩 throughput [+78824.448op/s; +88616.188op/s] or [+7.829%; +8.801%]

scenario:Benchmarks.Trace.SpanBenchmark.StartFinishTwoScopes net6.0

  • 🟩 throughput [+57149.004op/s; +62874.370op/s] or [+10.377%; +11.417%]

scenario:Benchmarks.Trace.SpanBenchmark.StartFinishTwoScopes netcoreapp3.1

  • 🟩 throughput [+24959.717op/s; +34772.125op/s] or [+5.587%; +7.783%]

scenario:Benchmarks.Trace.TraceAnnotationsBenchmark.RunOnMethodBegin net6.0

  • 🟩 throughput [+76221.046op/s; +95685.254op/s] or [+8.516%; +10.690%]

Known flaky benchmarks without significant changes:

  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan net472
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan net6.0
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan netcoreapp3.1
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_AddEvent_Sampled net472
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_AddEvent_Sampled net6.0
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_AddEvent_Sampled netcoreapp3.1
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_GetContext_Sampled net6.0
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_GetContext_Sampled netcoreapp3.1
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_SetAttributes_Sampled net472
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_SetAttributes_Sampled net6.0
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_SetAttributes_Sampled netcoreapp3.1
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_SetStatus_Sampled net472
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_SetStatus_Sampled net6.0
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_SetStatus_Sampled netcoreapp3.1
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_UpdateName_Sampled net472
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_UpdateName_Sampled net6.0
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.ActivityBenchmark.StartSpan_UpdateName_Sampled netcoreapp3.1
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan net472
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan net6.0
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan netcoreapp3.1
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_AddEvent_Sampled net472
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_AddEvent_Sampled net6.0
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_AddEvent_Sampled netcoreapp3.1
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_GetContext_Sampled net472
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_GetContext_Sampled net6.0
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_GetContext_Sampled netcoreapp3.1
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_RecordException_Sampled net472
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_RecordException_Sampled net6.0
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_RecordException_Sampled netcoreapp3.1
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_SetAttributes_Sampled net472
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_SetAttributes_Sampled net6.0
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_SetAttributes_Sampled netcoreapp3.1
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_SetStatus_Sampled net472
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_SetStatus_Sampled net6.0
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_SetStatus_Sampled netcoreapp3.1
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_UpdateName_Sampled net472
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_UpdateName_Sampled net6.0
  • scenario:Benchmarks.OpenTelemetry.InstrumentedApi.Trace.TelemetrySpanBenchmark.StartSpan_UpdateName_Sampled netcoreapp3.1
  • scenario:Benchmarks.Trace.ActivityBenchmark.StartStopWithChild net6.0
  • scenario:Benchmarks.Trace.ActivityBenchmark.StartStopWithChild netcoreapp3.1
  • scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.ObjectExtractorMoreComplexBody net472
  • scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.ObjectExtractorSimpleBody net472
  • scenario:Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmark net472
  • scenario:Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmark netcoreapp3.1
  • scenario:Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmarkWithAttack net472
  • scenario:Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmarkWithAttack netcoreapp3.1
  • scenario:Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSlice net6.0
  • scenario:Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSliceWithPool net472
  • scenario:Benchmarks.Trace.CharSliceBenchmark.OriginalCharSlice net472
  • scenario:Benchmarks.Trace.CharSliceBenchmark.OriginalCharSlice netcoreapp3.1
  • scenario:Benchmarks.Trace.ILoggerBenchmark.EnrichedLog net472
  • scenario:Benchmarks.Trace.ILoggerBenchmark.EnrichedLog netcoreapp3.1
  • scenario:Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark net472
  • scenario:Benchmarks.Trace.RedisBenchmark.SendReceive net472
  • scenario:Benchmarks.Trace.RedisBenchmark.SendReceive netcoreapp3.1
  • scenario:Benchmarks.Trace.SpanBenchmark.StartFinishScope net472
  • scenario:Benchmarks.Trace.SpanBenchmark.StartFinishSpan net472
  • scenario:Benchmarks.Trace.SpanBenchmark.StartFinishTwoScopes net472
  • scenario:Benchmarks.Trace.TraceAnnotationsBenchmark.RunOnMethodBegin net472
  • scenario:Benchmarks.Trace.TraceAnnotationsBenchmark.RunOnMethodBegin netcoreapp3.1

@dd-trace-dotnet-ci-bot

dd-trace-dotnet-ci-bot Bot commented Mar 16, 2026

Copy link
Copy Markdown

Execution-Time Benchmarks Report ⏱️

Execution-time results for samples comparing This PR (8313) 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
duration69.53 ± (69.59 - 69.89) ms69.96 ± (70.04 - 70.49) ms+0.6%✅⬆️
.NET Framework 4.8 - Bailout
duration74.38 ± (74.30 - 74.61) ms74.02 ± (73.88 - 74.21) ms-0.5%
.NET Framework 4.8 - CallTarget+Inlining+NGEN
duration1079.65 ± (1080.44 - 1087.99) ms1079.85 ± (1081.86 - 1088.60) ms+0.0%✅⬆️
.NET Core 3.1 - Baseline
process.internal_duration_ms21.99 ± (21.96 - 22.02) ms22.13 ± (22.08 - 22.17) ms+0.6%✅⬆️
process.time_to_main_ms80.35 ± (80.18 - 80.52) ms81.16 ± (80.92 - 81.39) ms+1.0%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.93 ± (10.93 - 10.93) MB10.90 ± (10.90 - 10.91) MB-0.3%
runtime.dotnet.threads.count12 ± (12 - 12)12 ± (12 - 12)+0.0%
.NET Core 3.1 - Bailout
process.internal_duration_ms21.95 ± (21.91 - 21.99) ms21.99 ± (21.95 - 22.02) ms+0.2%✅⬆️
process.time_to_main_ms81.81 ± (81.66 - 81.96) ms81.65 ± (81.47 - 81.83) ms-0.2%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.96 ± (10.96 - 10.97) MB10.94 ± (10.94 - 10.95) MB-0.2%
runtime.dotnet.threads.count13 ± (13 - 13)13 ± (13 - 13)+0.0%
.NET Core 3.1 - CallTarget+Inlining+NGEN
process.internal_duration_ms209.99 ± (209.15 - 210.84) ms209.40 ± (208.43 - 210.38) ms-0.3%
process.time_to_main_ms533.27 ± (532.01 - 534.53) ms532.14 ± (530.92 - 533.35) ms-0.2%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed49.27 ± (49.24 - 49.30) MB49.28 ± (49.25 - 49.31) MB+0.0%✅⬆️
runtime.dotnet.threads.count28 ± (28 - 28)28 ± (28 - 28)-0.2%
.NET 6 - Baseline
process.internal_duration_ms21.25 ± (21.20 - 21.31) ms20.87 ± (20.84 - 20.89) ms-1.8%
process.time_to_main_ms72.77 ± (72.50 - 73.04) ms69.59 ± (69.46 - 69.73) ms-4.4%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.64 ± (10.64 - 10.64) MB10.61 ± (10.61 - 10.61) MB-0.3%
runtime.dotnet.threads.count10 ± (10 - 10)10 ± (10 - 10)+0.0%
.NET 6 - Bailout
process.internal_duration_ms20.83 ± (20.80 - 20.86) ms20.84 ± (20.82 - 20.87) ms+0.1%✅⬆️
process.time_to_main_ms71.17 ± (71.01 - 71.33) ms71.11 ± (70.98 - 71.23) ms-0.1%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.75 ± (10.75 - 10.75) MB10.74 ± (10.74 - 10.74) MB-0.1%
runtime.dotnet.threads.count11 ± (11 - 11)11 ± (11 - 11)+0.0%
.NET 6 - CallTarget+Inlining+NGEN
process.internal_duration_ms371.39 ± (369.36 - 373.41) ms372.71 ± (370.35 - 375.06) ms+0.4%✅⬆️
process.time_to_main_ms533.00 ± (531.83 - 534.18) ms536.79 ± (535.25 - 538.32) ms+0.7%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed50.24 ± (50.22 - 50.27) MB50.17 ± (50.15 - 50.19) MB-0.1%
runtime.dotnet.threads.count28 ± (28 - 28)28 ± (28 - 28)+0.1%✅⬆️
.NET 8 - Baseline
process.internal_duration_ms19.15 ± (19.12 - 19.18) ms20.47 ± (20.33 - 20.60) ms+6.9%✅⬆️
process.time_to_main_ms68.68 ± (68.55 - 68.82) ms77.19 ± (76.48 - 77.89) ms+12.4%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed7.68 ± (7.67 - 7.69) MB7.75 ± (7.74 - 7.75) MB+0.8%✅⬆️
runtime.dotnet.threads.count10 ± (10 - 10)10 ± (10 - 10)+0.0%
.NET 8 - Bailout
process.internal_duration_ms18.98 ± (18.95 - 19.00) ms20.70 ± (20.57 - 20.84) ms+9.1%✅⬆️
process.time_to_main_ms69.42 ± (69.30 - 69.54) ms77.90 ± (77.28 - 78.52) ms+12.2%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed7.73 ± (7.72 - 7.73) MB7.75 ± (7.74 - 7.76) MB+0.3%✅⬆️
runtime.dotnet.threads.count11 ± (11 - 11)11 ± (11 - 11)+0.0%
.NET 8 - CallTarget+Inlining+NGEN
process.internal_duration_ms301.42 ± (299.32 - 303.53) ms308.23 ± (303.78 - 312.67) ms+2.3%✅⬆️
process.time_to_main_ms486.11 ± (484.98 - 487.25) ms495.06 ± (492.38 - 497.73) ms+1.8%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed37.77 ± (37.74 - 37.80) MB37.77 ± (37.74 - 37.80) MB-0.0%
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
duration201.65 ± (201.49 - 202.54) ms201.89 ± (201.37 - 202.30) ms+0.1%✅⬆️
.NET Framework 4.8 - Bailout
duration204.93 ± (204.46 - 205.11) ms203.84 ± (203.60 - 204.50) ms-0.5%
.NET Framework 4.8 - CallTarget+Inlining+NGEN
duration1202.81 ± (1203.20 - 1209.45) ms1204.84 ± (1205.31 - 1210.84) ms+0.2%✅⬆️
.NET Core 3.1 - Baseline
process.internal_duration_ms195.95 ± (195.54 - 196.37) ms194.82 ± (194.43 - 195.21) ms-0.6%
process.time_to_main_ms84.88 ± (84.63 - 85.12) ms84.76 ± (84.53 - 84.98) ms-0.1%
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed16.04 ± (16.02 - 16.06) MB16.11 ± (16.09 - 16.13) MB+0.4%✅⬆️
runtime.dotnet.threads.count20 ± (20 - 20)20 ± (19 - 20)+0.1%✅⬆️
.NET Core 3.1 - Bailout
process.internal_duration_ms194.96 ± (194.47 - 195.46) ms194.20 ± (193.84 - 194.56) ms-0.4%
process.time_to_main_ms86.05 ± (85.73 - 86.37) ms85.93 ± (85.70 - 86.17) ms-0.1%
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed16.11 ± (16.08 - 16.14) MB16.12 ± (16.09 - 16.15) MB+0.0%✅⬆️
runtime.dotnet.threads.count21 ± (20 - 21)21 ± (21 - 21)+0.2%✅⬆️
.NET Core 3.1 - CallTarget+Inlining+NGEN
process.internal_duration_ms388.10 ± (386.94 - 389.27) ms386.62 ± (385.31 - 387.93) ms-0.4%
process.time_to_main_ms544.96 ± (543.65 - 546.27) ms543.22 ± (541.93 - 544.50) ms-0.3%
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed58.32 ± (58.15 - 58.50) MB58.42 ± (58.20 - 58.64) MB+0.2%✅⬆️
runtime.dotnet.threads.count30 ± (30 - 30)30 ± (30 - 30)+0.1%✅⬆️
.NET 6 - Baseline
process.internal_duration_ms199.43 ± (198.94 - 199.91) ms200.22 ± (199.79 - 200.64) ms+0.4%✅⬆️
process.time_to_main_ms73.16 ± (72.87 - 73.45) ms73.77 ± (73.52 - 74.02) ms+0.8%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed16.33 ± (16.30 - 16.36) MB16.34 ± (16.32 - 16.37) MB+0.1%✅⬆️
runtime.dotnet.threads.count19 ± (19 - 19)19 ± (19 - 19)+0.2%✅⬆️
.NET 6 - Bailout
process.internal_duration_ms199.25 ± (198.87 - 199.64) ms198.98 ± (198.52 - 199.43) ms-0.1%
process.time_to_main_ms74.09 ± (73.89 - 74.28) ms74.24 ± (74.01 - 74.48) ms+0.2%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed16.45 ± (16.42 - 16.48) MB16.45 ± (16.42 - 16.48) MB+0.0%✅⬆️
runtime.dotnet.threads.count20 ± (20 - 20)20 ± (20 - 20)-1.5%
.NET 6 - CallTarget+Inlining+NGEN
process.internal_duration_ms583.30 ± (580.55 - 586.06) ms586.54 ± (584.16 - 588.91) ms+0.6%✅⬆️
process.time_to_main_ms553.34 ± (552.23 - 554.44) ms555.21 ± (554.05 - 556.38) ms+0.3%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed61.33 ± (61.25 - 61.41) MB61.43 ± (61.33 - 61.52) MB+0.2%✅⬆️
runtime.dotnet.threads.count31 ± (31 - 31)31 ± (31 - 31)+0.0%✅⬆️
.NET 8 - Baseline
process.internal_duration_ms198.12 ± (197.65 - 198.60) ms197.31 ± (196.88 - 197.74) ms-0.4%
process.time_to_main_ms72.96 ± (72.66 - 73.27) ms72.38 ± (72.13 - 72.62) ms-0.8%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed11.70 ± (11.68 - 11.72) MB11.73 ± (11.72 - 11.75) MB+0.3%✅⬆️
runtime.dotnet.threads.count18 ± (18 - 18)18 ± (18 - 18)+0.1%✅⬆️
.NET 8 - Bailout
process.internal_duration_ms195.10 ± (194.59 - 195.61) ms197.23 ± (196.74 - 197.71) ms+1.1%✅⬆️
process.time_to_main_ms73.09 ± (72.85 - 73.34) ms73.59 ± (73.36 - 73.82) ms+0.7%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed11.76 ± (11.74 - 11.78) MB11.75 ± (11.73 - 11.78) MB-0.1%
runtime.dotnet.threads.count19 ± (19 - 19)19 ± (19 - 19)+0.6%✅⬆️
.NET 8 - CallTarget+Inlining+NGEN
process.internal_duration_ms511.24 ± (508.39 - 514.09) ms511.25 ± (507.98 - 514.51) ms+0.0%✅⬆️
process.time_to_main_ms500.87 ± (500.06 - 501.69) ms502.82 ± (501.86 - 503.79) ms+0.4%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed51.12 ± (51.08 - 51.16) MB51.14 ± (51.10 - 51.17) MB+0.0%✅⬆️
runtime.dotnet.threads.count30 ± (30 - 30)30 ± (30 - 30)+0.1%✅⬆️
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 (8313) - mean (70ms)  : 67, 74
    master - mean (70ms)  : 68, 72

    section Bailout
    This PR (8313) - mean (74ms)  : 72, 76
    master - mean (74ms)  : 73, 76

    section CallTarget+Inlining+NGEN
    This PR (8313) - mean (1,085ms)  : 1036, 1135
    master - mean (1,084ms)  : 1029, 1139

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 (8313) - mean (110ms)  : 105, 115
    master - mean (109ms)  : 106, 112

    section Bailout
    This PR (8313) - mean (110ms)  : 108, 112
    master - mean (110ms)  : 107, 113

    section CallTarget+Inlining+NGEN
    This PR (8313) - mean (780ms)  : 757, 803
    master - mean (780ms)  : 752, 809

Loading
FakeDbCommand (.NET 6)
gantt
    title Execution time (ms) FakeDbCommand (.NET 6)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (8313) - mean (96ms)  : 94, 99
    master - mean (101ms)  : 94, 107

    section Bailout
    This PR (8313) - mean (98ms)  : 96, 100
    master - mean (98ms)  : 94, 102

    section CallTarget+Inlining+NGEN
    This PR (8313) - mean (940ms)  : 900, 979
    master - mean (934ms)  : 894, 973

Loading
FakeDbCommand (.NET 8)
gantt
    title Execution time (ms) FakeDbCommand (.NET 8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (8313) - mean (108ms)  : 91, 125
    master - mean (94ms)  : 92, 97

    section Bailout
    This PR (8313) - mean (109ms)  : crit, 94, 124
    master - mean (95ms)  : 93, 97

    section CallTarget+Inlining+NGEN
    This PR (8313) - mean (822ms)  : 729, 916
    master - mean (817ms)  : 783, 851

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 (8313) - mean (202ms)  : 197, 207
    master - mean (202ms)  : 196, 208

    section Bailout
    This PR (8313) - mean (204ms)  : 200, 208
    master - mean (205ms)  : 202, 208

    section CallTarget+Inlining+NGEN
    This PR (8313) - mean (1,208ms)  : 1168, 1248
    master - mean (1,206ms)  : 1162, 1251

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 (8313) - mean (289ms)  : 285, 294
    master - mean (291ms)  : 284, 299

    section Bailout
    This PR (8313) - mean (290ms)  : 285, 295
    master - mean (291ms)  : 283, 298

    section CallTarget+Inlining+NGEN
    This PR (8313) - mean (970ms)  : 944, 995
    master - mean (974ms)  : 949, 999

Loading
HttpMessageHandler (.NET 6)
gantt
    title Execution time (ms) HttpMessageHandler (.NET 6)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (8313) - mean (284ms)  : 277, 291
    master - mean (283ms)  : 275, 290

    section Bailout
    This PR (8313) - mean (283ms)  : 277, 288
    master - mean (283ms)  : 278, 287

    section CallTarget+Inlining+NGEN
    This PR (8313) - mean (1,173ms)  : 1137, 1208
    master - mean (1,169ms)  : 1133, 1206

Loading
HttpMessageHandler (.NET 8)
gantt
    title Execution time (ms) HttpMessageHandler (.NET 8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (8313) - mean (280ms)  : 274, 287
    master - mean (281ms)  : 275, 287

    section Bailout
    This PR (8313) - mean (281ms)  : 273, 289
    master - mean (278ms)  : 271, 285

    section CallTarget+Inlining+NGEN
    This PR (8313) - mean (1,047ms)  : 997, 1098
    master - mean (1,043ms)  : 991, 1095

Loading

@bouwkast
bouwkast force-pushed the steven/auto-instrumentation-gen-cli-v2 branch from fc5fd18 to dd7cbfc Compare April 1, 2026 12:21

> This document is a complete reference for AI agents using the `dd-autoinstrumentation` CLI to generate CallTarget auto-instrumentation code. It covers all commands, options, JSON schemas, error codes, and recommended workflows.

## Quick Start

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

do AI agents really need a "quick start" ? Or is it meant to be both for humans and AIs ?

|---|---|
| `--no-method-begin` | Skip `OnMethodBegin` handler |
| `--no-method-end` | Skip `OnMethodEnd` handler |
| `--async-method-end` | Generate `OnAsyncMethodEnd` handler |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

shouldn't this be automatic for async methods ?

{
Console.WriteLine("Available configuration keys for --set (camelCase, same as --json output):");
Console.WriteLine();
Console.WriteLine(" {0,-45} {1,-10} {2}", "Key", "Type", "Default");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: I assume this -45 and -10 is for whitespace padding. If you want to make it nice always, rather than hardcoding a value, you can iterate once to get the max length before starting to print.

OR you can kee it as is, but truncate long values so that they don't stick out of the array.

Comment on lines +36 to +49
metadata = result.Metadata is { } meta
? new
{
meta.AssemblyName,
meta.TypeName,
meta.MethodName,
meta.ReturnTypeName,
meta.ParameterTypeNames,
meta.MinimumVersion,
meta.MaximumVersion,
meta.IntegrationName,
meta.IntegrationClassName,
meta.IsInterface,
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why do we need this ? Can't we just pass the result.Metadata ?

@bouwkast
bouwkast force-pushed the steven/auto-instrumentation-gen-cli-v2 branch from dd7cbfc to a4c28bd Compare April 28, 2026 18:16
@vandonr

vandonr commented May 7, 2026

Copy link
Copy Markdown
Contributor

I have a feature request, which is to dump all the methods in a dll. This is what the ai toolkit we're developing works with in other languages, it doesn't do back and forth with the tool to get methods.
If I want the same for dotnet, I need to write a wrapper that gets all the types, and then iterates over them to get methods

@bouwkast
bouwkast marked this pull request as ready for review June 1, 2026 12:32
@bouwkast
bouwkast requested review from a team as code owners June 1, 2026 12:32

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d93c81dda

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +347 to +349
var outputText = jsonMode
? JsonOutputFormatter.Format(result, config)
: result.SourceCode!;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Write source files even when JSON mode is enabled

When callers combine --json (which the new agent workflow recommends) with --output path/to/Integration.cs, outputText becomes the JSON envelope and the later File.WriteAllText(output.FullName, outputText) writes that JSON into the .cs file instead of the generated source. This makes the documented output-file workflow produce an unusable integration file whenever structured stdout is requested; keep the file contents as result.SourceCode and emit JSON only to stdout (or reject the combination).

Useful? React with 👍 / 👎.

bouwkast and others added 16 commits June 11, 2026 12:40
Add dd-autoinstrumentation CLI that uses the Core library to generate
integration boilerplate from the command line. Includes --set key=value
configuration, --config-file support, --json output, and Nuke build
integration via RunInstrumentationGeneratorCli target.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
… assembly inspection

Add global --json flag, unified JSON error envelope with machine-readable error codes,
inspect subcommand for type/method discovery, and structured --list-keys output.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
… workflow

Update InstrumentationGenerator.md with inspect command, structured error handling,
and LLM usage sections. Add dedicated LLM reference doc with full JSON schemas,
error recovery patterns, and step-by-step autonomous workflow.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Wrap AssemblyBrowser construction in try-catch so corrupted or non-.NET
DLLs return a structured error instead of crashing the CLI.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Remove --async-method-end flag (auto-detect handles async methods,
  including disabling OnMethodEnd which the flag alone did not do)
- Compute --list-keys column widths from data instead of hardcoding
- Pass result.Metadata directly to the JSON serializer
- Rename "Quick Start" to "Invocation" in the LLM-only doc
System.CommandLine binds Option<string[]> to a single token by default,
so the documented `--parameter-types System.String System.Int32` form
left the second type as an unmatched argument. Set
AllowMultipleArgumentsPerToken=true so all space-separated types after
the option are bound, fixing both the documented invocation and the
RunInstrumentationGeneratorCli Nuke target which appends each type as
a separate token.
When --json was set and generator.Generate() returned Success=false
(e.g., static method on a value type, generic interface), the failure
was serialized via JsonOutputFormatter as a stripped-down
{success, errorMessage} object and the command still exited 0. This
made automation paths — including the recommended LLM workflow and the
RunInstrumentationGeneratorCli Nuke target — treat failed generation
as success.

Route the failure through OutputHelper.WriteError so it emits the same
unified envelope as other errors (command + errorCode + errorMessage)
and exits 1. Drop the now-unreachable failure branch from
JsonOutputFormatter.Format.
ListMethods filtered out every IsSpecialName member, which silently
dropped constructors (.ctor), property accessors (get_*/set_*), event
accessors, and operators. CallTarget integrations in this repo target
all of those (search for MethodName = ".ctor" / "get_" / "set_" under
ClrProfiler/AutoInstrumentation), so any inspect-driven workflow could
not discover them and had no way to recover without already knowing
the name. Drop the special-name filter and keep only the
compiler-generated check; update the LLM doc to match.
In `generate --json --output <file>`, stdout received
"Output written to: <path>" as plain text, breaking the documented
"all output on stdout is JSON" contract for callers combining file
output with machine-readable parsing. Mirror the JSON envelope to
stdout in JSON mode so automation can always parse stdout, while
keeping the human-readable confirmation in plain mode.
The Generator.Cli project only targets net10.0, so the documented
`dotnet run --framework net8.0` invocation fails before reaching the
generator. Omit the flag so dotnet-run picks the project's only TFM.
When the requested --type was absent, ResolveMethod returned null and
ListOverloads returned empty, so the missing-type case fell through to
METHOD_NOT_FOUND. JSON clients are documented to recover from a missing
type by switching to `inspect --list-types`, so they need TYPE_NOT_FOUND
to make that decision.

Add AssemblyBrowser.TypeExists and check it before the overload
lookup. Behavior is now: type missing -> TYPE_NOT_FOUND, type present
but method missing -> METHOD_NOT_FOUND, otherwise AMBIGUOUS_OVERLOAD.
Direct rootCommand.Parse(args).Invoke() let System.CommandLine print
its default help/error text on parse failures (unknown option, missing
required argument, unparseable option value), so JSON-mode callers got
unparseable stdout/stderr despite the --json contract.

Inspect parseResult.Errors before invoking. When --json is set and
errors are present, emit OutputHelper.WriteError with INVALID_ARGUMENT
and the resolved subcommand name so automation can recover. Plain mode
still falls through to Invoke() and prints the default text.
The StartsWith check on "System.Threading.Tasks.Task" classified
TaskScheduler, TaskCompletionSource, TaskFactory, TaskCanceledException,
TaskCreationOptions, TaskStatus, etc. as async return types because
they share the prefix. CallTarget's async handling only applies to
Task / Task<T> / ValueTask / ValueTask<T>, so callers acting on the
isAsync flag could pick the wrong handler shape for those returns.

Add GenerationConfiguration.IsAsyncReturnType that matches only the
exact non-generic names and the dnlib generic forms (Task\`1<...> and
ValueTask\`1<...>), and use it from both the inspect output and the
auto-detect path in CreateForMethod so the two stay in sync. Update
the LLM doc note to reflect the precise rule.
Splitting GeneratorArgs on every space corrupted quoted CLI values:
inline JSON for --config (e.g. '{"k":true}') and paths under
"Program Files" got shredded into separate tokens before the generator
ran, so the wrapper rejected or misapplied otherwise valid invocations.
Add a small shell-style tokenizer that respects single and double
quotes and use it in place of the naive split.
The Generator.Cli .csproj uses <TargetFrameworks> (plural) so dotnet
run rejects the project with "targets multiple frameworks" even
though only net10.0 is listed. Inheriting from tracer/src/Directory
.Build.props makes switching to <TargetFramework> singular pull in
net6.0 instead, so the simpler fix is to keep the flag in the
documented invocation. The for-ai LLM reference already includes it.
Wrapping arguments only when they contain spaces lost embedded quotes
and trailing backslashes, so inline JSON for --config arrived at the
generator with the quotes stripped or paths ending in "\\" misparsed.
Replace the naive join with a PasteArguments-style escape (matches
.NET's ProcessStartInfo.ArgumentList behavior on Windows): wrap when
the arg contains whitespace, quotes, or backslashes, double the
backslashes that precede each embedded quote, and double the trailing
backslashes before the closing quote.
@bouwkast
bouwkast force-pushed the steven/auto-instrumentation-gen-cli-v2 branch from 9d93c81 to 0def04c Compare June 11, 2026 10:44
@datadog-prod-us1-4

This comment has been minimized.

Comment thread tracer/build/_build/Build.Utilities.cs Outdated
@vandonr

vandonr commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

@codex review

@vandonr
vandonr merged commit d56c0bd into master Jul 9, 2026
141 checks passed
@vandonr
vandonr deleted the steven/auto-instrumentation-gen-cli-v2 branch July 9, 2026 13:43
@github-actions github-actions Bot added this to the vNext-v3 milestone Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants