[codex] Verify ProjectReference autoinstrumentation assets - #1
Conversation
A triage (reading the actual code, not file names) found the branch is mostly real: the feature code is correct and hallucination-free, 14/19 verifiers are genuine behavioral checks (NativeAOT publish + golden diff, real OTLP-protobuf wire round-trip, IL2xxx/IL3xxx publish-warning gates), and the golden fixtures are produced by real harnesses, not hand-authored. Remove only the genuine ceremony: - docs/score-100-justification.md + tools/verify-score-100-justification.py — self-assigned "100/100" prose graded by a token-grep + 900-word floor; its benchmark numbers even contradict the committed reports it cites. - tools/verify-rfc-artifact.py — token-greps the RFC markdown for literal phrases (and a hardcoded date that already drifted). The RFC doc itself stays. - tools/verify-benchmark-report.py + tools/run-hotpath-benchmarks.sh + docs/benchmarks/*-report-github.md — token-grep over committed, hardware-pinned BenchmarkDotNet result exports that are never re-measured. The benchmark PROJECT under benchmarks/ stays. - .github/workflows/aot-warning-gate.yml — byte-identical to smoketest.yml (both run `bash tools/smoketest.sh`); keep one. Also trim the 3 deleted scripts out of verify-aot-autoinstrumentation-goal.py's COMMANDS chain and drop the dangling score-doc / verify-rfc-artifact references from the RFC. Build stays green (0/0); goal-gate still references only existing scripts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9a4c2f37bd
ℹ️ 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".
| private static object ToTagValue(IEnumerable<string> values) | ||
| { | ||
| if (values is string[] array) | ||
| return array.Length is 1 ? array[0] : array; |
There was a problem hiding this comment.
Keep captured header tags as arrays
For configured HTTP headers with exactly one value, this now returns a scalar string instead of the previous values.ToArray() representation. The OpenTelemetry HTTP semantic conventions define http.request.header.<key> / http.response.header.<key> as string[], including single-value headers (spec), so OTLP output and backends that validate array-typed captured headers will regress whenever a configured header has only one value. Keep emitting a one-element array here, and apply the same fix to the other new single-value header/metadata capture paths.
Useful? React with 👍 / 👎.
| if (!IsEnabled()) | ||
| return; |
There was a problem hiding this comment.
Avoid sampling spans when conformance is off
With the default QYL_CONFORMANCE_ENABLED unset, this opt-out happens only after QylInstrumentation.Activate() has already registered an ActivityListener that samples AllDataAndRecorded. In a hosted app with no external qyl listener, that internal listener still makes QylActivitySource.HasListeners() true, so every intercepted trace/log path allocates and populates Activities only to return here; this keeps the production hot-path cost that this change is trying to disable. Gate listener registration on the same conformance opt-in instead of returning after span creation.
Useful? React with 👍 / 👎.
| local consumer="$2" | ||
| local matches | ||
|
|
||
| matches="$(grep -Eo '\\b(IL2[0-9]{3}|IL3[0-9]{3}|IL4[0-9]{3}|CA[0-9]{4})\\b' "$log" | sort -u || true)" |
There was a problem hiding this comment.
Fix the AOT warning grep pattern
In this shell string the doubled backslashes are passed to grep -E as \\b, so the pattern looks for a literal backslash plus b rather than a word boundary; for example, printf 'IL3000\n' | grep -Eo '\\b(IL3[0-9]{3})\\b' produces no match. As a result, this smoke gate reports warnings=0 even when the publish log contains IL2xxx/IL3xxx/IL4xxx/CA warnings that the workflow is supposed to fail on.
Useful? React with 👍 / 👎.
…sets The slim-history rebuild of main (PR #2) orphaned the original working branch, which then received nine more commits (2026-06-09 → 06-11 04:02) that never reached the new main: HttpClient effective-request metadata resolution, header-capture fallback path (new QylCaptureHelpers), status-handling tightening, verifier simplification into shared verify_helpers.py, and the extracted WebApiAotDemo Program.cs that the rebuild had dropped while keeping its golden report. Three-way merged the two genuinely diverged files: ModuleInitializerBoot (night listener-table refactor + main's sober XML docs) and the source generator (night dispatch-table refactor + main's ANcpLua.Roslyn.Utilities adoption). Skipped docs/pr1-remaining.md — completed-checklist evidence for the already-merged PR #1; its tracked changes land with this commit. Also filed the drafted NServiceBus AOT upstream issue under docs/upstream/ instead of leaving it untracked at the repo root. Verified: dotnet build (0 warnings), verify-generator-snapshots, verify-public-api-baseline, verify-source-interceptor-consumer all ok. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…trument (CODE RED #1/#2/#10) (#22) An adversarial OTel-compliance + honesty audit rated this code 3/10. This lands the verified subset of the confirmed HIGH/MEDIUM defects. #1 (HIGH, ~0-duration lie): the HttpClient/AspNetCore/gRPC DiagnosticListeners created their span on the framework's *.Stop event via the 2-arg StartActivity (StartTimeUtc=now) and immediately disposed it, so every emitted span had ~0 duration instead of the real operation latency. New internal QylActivitySource.StartAtAmbientStart(name, kind) stamps the span to the ambient framework Activity's real StartTimeUtc (parented to it for trace correlation), with a now-stamped fallback when there is no ambient activity. All three listeners switched to it. #2 (HIGH, dishonest doc): DiagnosticListenerSubscriber claimed it "publishes the same span shapes" — false while durations were fabricated. Doc now states the actual mechanism (reacts on *.Stop, stamps to ambient start for real duration). #10 (MEDIUM, metrics-semconv): dotnet.thread_pool.thread.count was an unitless ObservableGauge<int>; per OTel semconv it is an (Observable)UpDownCounter with UCUM unit {thread}. Switched instrument type + added unit. Verified: core.slnf Release 0/0; verify-webapi-aot-demo passes (fixture unchanged — the attribute shape is identical; note the fixture is duration-insensitive, which is itself tracked as a separate finding). No PublicAPI change (all internal/private). NOT in this commit (separate verified increments): #3 double-count between the listener and interceptor lanes (+ the fixture that masks it), #4/#11 OTLP Events/Links/Status.Message dropped on ingest, #6 url.scheme, #7 http.request.method_original on the interceptor path, #9 Azure span name ignores methodName. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
build/package assets alongsidebuildTransitive/so direct package layout is explicit without double-compiling the intercepts attribute.CurrentHolder, and adding a null guard at the signal instrumentation boundary.QYL_CONFORMANCE_ENABLED=1orAddQylAutoInstrumentation(o => o.EnableConformanceProcessor = true)and verify default-off/env-on/hosting-on behavior.tools/smoketest.shplus a GitHub Actions smoke workflow that builds PackageReference and ProjectReference consumers, runs both under JIT and NativeAOT, asserts generated interceptor output, and diffs deterministic stdout against a golden fixture.Microsoft.CodeAnalysis.PublicApiAnalyzersfor the five runtime/package projects, commit shipped public API baselines, and verify the baseline files in the combined goal gate.docs/rfc/0001-interceptor-substrate.mdas the upstream/contribution artifact for the AOT-native[InterceptsLocation]substrate, plustools/verify-rfc-artifact.pyso the RFC minimum contract is part of the goal gate.tools/verify-generator-snapshots.py; the combined goal gate now fails on generated interceptor or generated contract drift.docs/coverage-matrix.md, generated from the 60-item source-of-truth YAML plus the current generator/runtime bindings, and maketools/verify-contract-coverage-report.pyfail if the matrix is stale.tools/verify-webapi-aot-demo.pyplusqyl-webapi-aot-demoCI. It packs the current NuGets, creates a .NET 10 minimal Web API with ASP.NET Core, HttpClient, EFCore Sqlite compiled model, and SqlClient error-path instrumentation, publishes NativeAOT, runs the binary, and compares canonical telemetry output against a golden JSON file while failing on qyl-owned AOT analyzer warnings.tools/verify-otlp-golden-fixtures.pyplustools/Qyl.AutoInstrumentation.OtlpGoldenFixtures/golden/webapi-aot-traces.otlp.json; it maps the NativeAOT WebAPI proof signals into deterministic OTLP-shapedresourceSpans/scopeSpans/spansJSON and fails on output drift.Qyl.AutoInstrumentation.SourceGeneratorsnow generates XML docs, treats CS1591 as an error, documents the interceptor generator, andtools/verify-xml-doc-enforcement.pyverifies the gate.Validation
bash tools/smoketest.shpython3 tools/verify-public-api-baseline.py && dotnet build Qyl.AutoInstrumentation.slnx -c Release -v quietdotnet build Qyl.AutoInstrumentation.slnx -c Release -v quiet && python3 tools/verify-environment-options-behavior.py && python3 tools/verify-conformance-opt-in.py && python3 tools/verify-source-interceptor-consumer.pypython3 tools/verify-rfc-artifact.py && python3 tools/verify-aot-autoinstrumentation-goal.pypython3 tools/verify-generator-snapshots.pypython3 tools/verify-contract-coverage-report.pypython3 tools/verify-webapi-aot-demo.pypython3 tools/verify-otlp-golden-fixtures.pypython3 tools/verify-xml-doc-enforcement.pyKnown notes
ProjectReferenceremains intentionally documented as unsupported for zero-code interception because MSBuild resolves it as a reference assembly, not analyzer/build assets. The supported source-tree path is explicit runtime ProjectReference + analyzer/build-asset wiring.Qyl.AutoInstrumentation.csprojcurrently reports 343 missing public-doc entries, mostly generated-interceptor runtime bridge methods/constants.docs/score-100-justification.mdremain outside this PR so far.