Consumer demos + sourcegen multi-line example doc-comment fix - #3
Conversation
… comments WriteExamplesComment and EventsEmitter emitted each example straight into a single AppendDocLine, without splitting on the example's own newlines. A multi-line value (e.g. gen_ai.retrieval.documents' JSON-array example) leaked its raw lines — including a closing brace — into compilable source, which closed the generated class early and produced 40x CS9348 in any consumer that projected the gen_ai incubating attributes. Add SourceWriter.AppendExample, which splits the example and ///-prefixes every line, and route both example writers through it. Summary/remarks were already safe (they pre-split via SplitLines); examples were the only doc path taking a raw registry value to a single AppendDocLine. Single-line examples are byte-identical (60/60 snapshot tests pass). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Telemetry.Example is an OpenTelemetry + Agent Framework console demo that dogfoods the source generator: it declares gen_ai marker partials (SemConv.cs) and uses the generated GenAi.Attribute* constants on a per-turn span plus the generated CreateGenAiClientTokenUsageHistogram() Meter factory in Program.cs. Tournament.Demos is a minimal worker-service demo. Both are self-contained dockerised samples, so they opt out of the repo's Central Package Management and XML-doc gating (mirroring eng/build/_build.csproj) rather than registering demo-only deps in the shared Directory.Packages.props. Worker.cs uses a source-generated [LoggerMessage] delegate to satisfy the repo's CA1848/CA1727/CA1873 analyzers. slnx adds both projects; compose.yaml and .dockerignore support container runs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
BuildIdToClassMap and the code-fix branch of BuildClassMaps wrapped Activator.CreateInstance in catch-and-skip blocks for "analyzers with non-default ctors". Every analyzer/code-fix in the assembly has a public parameterless ctor (Roslyn requires it to instantiate them), so the catches were unreachable. CheckDocs still passes, confirming nothing throws on construction. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c372f4dc09
ℹ️ 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".
|
|
||
| FROM build AS publish | ||
| ARG BUILD_CONFIGURATION=Release | ||
| RUN dotnet publish "./Telemetry.Example.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false |
There was a problem hiding this comment.
Publish the AOT sample with a Linux RID
In this Docker build path, Telemetry.Example.csproj has <PublishAot>true</PublishAot>, but the publish command asks for a portable DLL with /p:UseAppHost=false and does not specify a Linux RID. Native AOT publishing is platform-specific/self-contained, so docker compose build telemetry.example either fails on SDKs that reject PublishAot without a RID or produces output inconsistent with the final dotnet Telemetry.Example.dll entrypoint; publish with an explicit Linux RID/apphost and run the native executable instead.
Useful? React with 👍 / 👎.
|
|
||
| FROM build AS publish | ||
| ARG BUILD_CONFIGURATION=Release | ||
| RUN dotnet publish "./Tournament.Demos.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false |
There was a problem hiding this comment.
Publish the AOT worker with a Linux RID
In this Docker build path, Tournament.Demos.csproj has <PublishAot>true</PublishAot>, but the publish command asks for a portable DLL with /p:UseAppHost=false and does not specify a Linux RID. Native AOT publishing is platform-specific/self-contained, so docker compose build tournament.demos either fails on SDKs that reject PublishAot without a RID or produces output inconsistent with the final dotnet Tournament.Demos.dll entrypoint; publish with an explicit Linux RID/apphost and run the native executable instead.
Useful? React with 👍 / 👎.
| COPY ["src/Telemetry.Example/Telemetry.Example.csproj", "src/Telemetry.Example/"] | ||
| RUN dotnet restore "src/Telemetry.Example/Telemetry.Example.csproj" |
There was a problem hiding this comment.
Copy the analyzer project before Docker restore
When building the telemetry.example image, this layer only copies Telemetry.Example.csproj, but that project has a ProjectReference to ../Qyl.OpenTelemetry.SemanticConventions.SourceGeneration/Qyl.OpenTelemetry.SemanticConventions.SourceGeneration.csproj. The very next dotnet restore runs before COPY . ., so the referenced generator project is absent from /src and Docker restores fail before reaching the build; copy the referenced project and shared props before restore or move restore after the full context copy.
Useful? React with 👍 / 👎.
| using Microsoft.Extensions.Hosting; | ||
| using Microsoft.Extensions.Logging; | ||
|
|
||
| var configuration = new ConfigurationBuilder().AddUserSecrets<Program>().Build(); |
There was a problem hiding this comment.
Add a user-secrets id before loading secrets
When running Telemetry.Example, this calls AddUserSecrets<Program>(), but Telemetry.Example.csproj does not define a UserSecretsId or otherwise emit a UserSecretsIdAttribute. The non-optional overload throws during startup when that attribute is missing, so the demo exits before it can read the OpenAI settings; add a UserSecretsId to the project or use an optional/environment-backed configuration path.
Useful? React with 👍 / 👎.
Summary
Wiring the source generator into a real consumer (
Telemetry.Example) surfaced a generator correctness bug, not just a docs gap. Fixes the bug, adds two consumer demos, and removes dead code in the docs generator.Commits
fix(sourcegen)—WriteExamplesComment+EventsEmitteremitted example values without splitting on the example's own newlines. A multi-line value (e.g.gen_ai.retrieval.documents' JSON-array example) leaked raw lines — including a closing}— into compilable source, closing the generated class early → 40× CS9348 for any consumer projecting thegen_aiincubating attributes. NewSourceWriter.AppendExamplesplits +///-prefixes every line; both example writers route through it. Single-line examples are byte-identical.feat(examples)—Telemetry.Example(OTel + Agent Framework console demo that dogfoods the generator viagen_aimarkers, using generatedGenAi.Attribute*constants on a per-turn span and the generatedCreateGenAiClientTokenUsageHistogram()Meter factory) +Tournament.Demos(minimal worker). Both are self-contained dockerised samples → opt out of CPM + XML-doc gating (mirrorseng/build/_build.csproj).refactor(docsgen)— drop unreachabletry/catcharoundActivator.CreateInstanceinDescriptorCatalog(every analyzer/code-fix has a public parameterless ctor).Verification
TreatWarningsAsErrors)./build.sh CheckDocs: passes — confirms the removedtry/catchwas dead code and docs aren't staleTelemetry.Example(osx-arm64): zero AOT/trim warnings, native Mach-O arm64 executable — proves the generated code (consts +Activity.SetTag+Histogram.Record, zero reflection,[Conditional]-stripped markers) is AOT-clean🤖 Generated with Claude Code