Skip to content

Consumer demos + sourcegen multi-line example doc-comment fix - #3

Merged
ANcpLua merged 3 commits into
mainfrom
demos-and-sourcegen-docfix
Jun 4, 2026
Merged

Consumer demos + sourcegen multi-line example doc-comment fix#3
ANcpLua merged 3 commits into
mainfrom
demos-and-sourcegen-docfix

Conversation

@ANcpLua

@ANcpLua ANcpLua commented Jun 4, 2026

Copy link
Copy Markdown
Owner

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 + EventsEmitter emitted 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 the gen_ai incubating attributes. New SourceWriter.AppendExample splits + ///-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 via gen_ai markers, using generated GenAi.Attribute* constants on a per-turn span and the generated CreateGenAiClientTokenUsageHistogram() Meter factory) + Tournament.Demos (minimal worker). Both are self-contained dockerised samples → opt out of CPM + XML-doc gating (mirrors eng/build/_build.csproj).
  • refactor(docsgen) — drop unreachable try/catch around Activator.CreateInstance in DescriptorCatalog (every analyzer/code-fix has a public parameterless ctor).

Verification

  • Full solution build: 0 / 0 (TreatWarningsAsErrors)
  • SourceGeneration snapshot tests: 60 / 60 — byte-identity preserved
  • ./build.sh CheckDocs: passes — confirms the removed try/catch was dead code and docs aren't stale
  • AOT publish of Telemetry.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

ANcpLua and others added 3 commits June 4, 2026 02:26
… 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>
@ANcpLua
ANcpLua merged commit 7d960ed into main Jun 4, 2026
2 checks passed
@ANcpLua
ANcpLua deleted the demos-and-sourcegen-docfix branch June 4, 2026 01:07

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

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

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 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 👍 / 👎.

Comment on lines +8 to +9
COPY ["src/Telemetry.Example/Telemetry.Example.csproj", "src/Telemetry.Example/"]
RUN dotnet restore "src/Telemetry.Example/Telemetry.Example.csproj"

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 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();

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 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 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant