[WIP] Add CLI-based AutoInstrumentation Generator#8291
[WIP] Add CLI-based AutoInstrumentation Generator#8291
Conversation
Split the Avalonia GUI generator into a 3-project architecture: - Core library (Generator.Core): shared generation logic with zero UI deps - CLI tool (Generator.Cli): scriptable command-line interface via System.CommandLine - Refactored GUI: delegates to Core for all generation The CLI enables scripted/AI-assisted instrumentation workflows — generate CallTarget boilerplate from assembly inspection without the GUI. Integrated into Nuke build system as RunInstrumentationGeneratorCli target. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move option variables to fields, inline execution logic into the handler, and extract config overrides into ApplyCliOverrides. No functional change to CLI behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use JsonSerializer.Serialize with anonymous types instead of manual StringBuilder JSON construction. Eliminates incomplete JsonEscape helper and uses the in-box System.Text.Json (no new dependency for net10.0). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Serialize the entire config object instead of only 3 fields, so LLM consumers can see all auto-detected flag values and know exactly which flags to override on follow-up invocations. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Every enable flag (--async-method-end, --duck-*, etc.) now has a --no-* counterpart that explicitly disables it. Disable flags are applied after enable flags so --no-* always wins, allowing selective override of auto-detected defaults without resorting to --no-auto-detect. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This reverts commit a22f749.
Accepts a JSON string matching the 'configuration' block from --json
output, allowing an LLM to take auto-detected config from a first run,
modify specific fields, and pass it back. Individual CLI flags still
override on top. Replaces the need for --no-* counterparts on every flag.
Example workflow:
1. Run with --json, inspect the configuration block
2. Modify the JSON (e.g., set createOnAsyncMethodEnd to false)
3. Re-run with --config '{"createOnAsyncMethodEnd": false, ...}'
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AssemblyPath, TypeName, MethodName, OutputPath, ParameterTypes, and GeneratorArgs are null when other targets run. Mark them as string? to suppress nullability warnings. The .Requires() guards ensure they are non-null when RunInstrumentationGeneratorCli executes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…d --list-keys Remove all 21 duck-type Option<bool> fields and the 120-line ApplyCliOverrides method from GenerateCommand. Replace with three configuration mechanisms: - --set key=value (repeatable) for fine-grained overrides - --config-file path.json for file-based config (auto-extracts from --json envelope) - --list-keys to discover available configuration keys with defaults Keep --no-method-begin, --no-method-end, --async-method-end as shortcut flags. Add ConfigurationApplier with reflection-based property mapping, case-insensitive lookup, and fuzzy-match suggestions for typos. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
BenchmarksBenchmark execution time: 2026-03-11 22:31:09 Comparing candidate commit 7e1e887 in PR branch Found 10 performance improvements and 11 performance regressions! Performance is the same for 161 metrics, 10 unstable metrics. scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleSimpleBody net6.0
scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleSimpleBody netcoreapp3.1
scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.ObjectExtractorSimpleBody net6.0
scenario:Benchmarks.Trace.Asm.AppSecEncoderBenchmark.EncodeLegacyArgs net6.0
scenario:Benchmarks.Trace.Asm.AppSecEncoderBenchmark.EncodeLegacyArgs netcoreapp3.1
scenario:Benchmarks.Trace.AspNetCoreBenchmark.SendRequest net6.0
scenario:Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces net6.0
scenario:Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces netcoreapp3.1
scenario:Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSliceWithPool netcoreapp3.1
scenario:Benchmarks.Trace.DbCommandBenchmark.ExecuteNonQuery net6.0
scenario:Benchmarks.Trace.ElasticsearchBenchmark.CallElasticsearchAsync net472
scenario:Benchmarks.Trace.GraphQLBenchmark.ExecuteAsync net472
scenario:Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark net6.0
scenario:Benchmarks.Trace.SingleSpanAspNetCoreBenchmark.SingleSpanAspNetCore netcoreapp3.1
scenario:Benchmarks.Trace.SpanBenchmark.StartFinishScope net6.0
scenario:Benchmarks.Trace.SpanBenchmark.StartFinishSpan net6.0
scenario:Benchmarks.Trace.SpanBenchmark.StartFinishSpan netcoreapp3.1
scenario:Benchmarks.Trace.SpanBenchmark.StartFinishTwoScopes net6.0
scenario:Benchmarks.Trace.TraceAnnotationsBenchmark.RunOnMethodBegin netcoreapp3.1
|
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (8291) 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 (8291) - mean (74ms) : 72, 77
master - mean (76ms) : 74, 78
section Bailout
This PR (8291) - mean (78ms) : 77, 80
master - mean (81ms) : 79, 83
section CallTarget+Inlining+NGEN
This PR (8291) - mean (1,090ms) : 1044, 1136
master - mean (1,115ms) : 1069, 1161
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 (8291) - mean (117ms) : 114, 120
master - mean (121ms) : 117, 124
section Bailout
This PR (8291) - mean (118ms) : 116, 121
master - mean (121ms) : 118, 124
section CallTarget+Inlining+NGEN
This PR (8291) - mean (777ms) : 719, 835
master - mean (787ms) : 721, 852
FakeDbCommand (.NET 6)gantt
title Execution time (ms) FakeDbCommand (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8291) - mean (102ms) : 99, 106
master - mean (105ms) : 102, 109
section Bailout
This PR (8291) - mean (104ms) : 101, 107
master - mean (107ms) : 105, 109
section CallTarget+Inlining+NGEN
This PR (8291) - mean (754ms) : 708, 801
master - mean (773ms) : 719, 828
FakeDbCommand (.NET 8)gantt
title Execution time (ms) FakeDbCommand (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8291) - mean (102ms) : 99, 105
master - mean (104ms) : 101, 108
section Bailout
This PR (8291) - mean (103ms) : 101, 105
master - mean (106ms) : 104, 108
section CallTarget+Inlining+NGEN
This PR (8291) - mean (676ms) : 655, 697
master - mean (693ms) : 674, 713
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 (8291) - mean (195ms) : 190, 200
master - mean (197ms) : 190, 204
section Bailout
This PR (8291) - mean (198ms) : 194, 202
master - mean (200ms) : 195, 206
section CallTarget+Inlining+NGEN
This PR (8291) - mean (1,148ms) : 1102, 1195
master - mean (1,170ms) : 1116, 1225
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 (8291) - mean (278ms) : 271, 286
master - mean (279ms) : 273, 286
section Bailout
This PR (8291) - mean (279ms) : 274, 283
master - mean (281ms) : 275, 287
section CallTarget+Inlining+NGEN
This PR (8291) - mean (946ms) : 910, 981
master - mean (954ms) : 908, 999
HttpMessageHandler (.NET 6)gantt
title Execution time (ms) HttpMessageHandler (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8291) - mean (271ms) : 266, 276
master - mean (274ms) : 267, 281
section Bailout
This PR (8291) - mean (272ms) : 268, 276
master - mean (274ms) : 267, 281
section CallTarget+Inlining+NGEN
This PR (8291) - mean (936ms) : 907, 965
master - mean (948ms) : 910, 986
HttpMessageHandler (.NET 8)gantt
title Execution time (ms) HttpMessageHandler (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8291) - mean (269ms) : 261, 278
master - mean (272ms) : 267, 278
section Bailout
This PR (8291) - mean (270ms) : 265, 275
master - mean (272ms) : 267, 277
section CallTarget+Inlining+NGEN
This PR (8291) - mean (835ms) : 820, 851
master - mean (841ms) : 817, 865
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Summary of changes
Currently a WIP, will need some more time
Idea here is to be able to encode our code generation for auto-instrumentations into a CLI
This would allow us to do a couple of things pretty easily:
Reason for change
Implementation details
Test coverage
Other details