Milestones
List view
**Target state: avroc is observable, and a code generation run is a span inside whatever build asked for it.** v0.2.0 made every boundary a third party touches a file or an executable. This milestone makes what happens between those boundaries visible, and it settles that question the same way — with a contract rather than an implementation detail. - **Tracing, not a logging protocol.** avroc's structured log answers "what went wrong". It cannot answer "where did the time go", and it says nothing to a CI pipeline that would like code generation to appear inside its own trace. OpenTelemetry is the answer to both, configured entirely from the standard `OTEL_*` environment variables an operator already sets. - **The stderr diagnostic protocol is deleted.** avroc analyses a generator's **exit status and nothing else**, and passes standard error through to its own. The `<severity>: <message>` format, its parser (`internal/avroc/diagnostic.go`), its producer (`internal/plugin.DiagnosticHandler`) and its normative section all go. A channel that means something is a channel that misfiles everything else written to it — including an SDK reporting a failed export — and once generators emit OTel log records, attribution comes back richer than a parsed prefix ever was. - **Trace context crosses the fork.** avroc sets `TRACEPARENT` and `TRACESTATE` on every generator process from that invocation's span, so a generator's spans nest under the invocation that produced them. SDK *configuration* already reaches a generator by ordinary inheritance; *context* cannot, because it is per-invocation. The carrier is a de facto convention rather than a ratified specification, and `docs/plugin/SPEC.md` says so in those words. - **Generators participate.** `internal/plugin.Main` opens a span per invocation, and `avroc-gen-go` opens one per schema and per file. This is what forces the determinism check to learn the difference between reading the clock and putting the clock in a file — a narrow, named exemption for a package that cannot reach `plugin.FileWriter`, with the negative case checked. - **Propagation is checked, not assumed.** A dropped span context still generates correct output and still exits zero, so the only way to know it works is a check that fails when it does not. `dagger call` runs the example through a collector backed by Tempo (both from `z5labs/devex/daggerverse`) and asserts the trace's structure end to end. ### What breaks relative to v0.2.0 **The diagnostic format.** v0.2.0 specified `<severity>: <message>` on standard error, parsed by avroc into its structured log at the level the severity named. Any generator written against it must be rewritten — which in practice means deleting the handler and writing to stderr however it likes, since nothing parses it any more. **Nothing else.** The argument vector, the descriptor, the `--plugin-info` handshake, the output directory and merge, the prune record and the determinism rule are all unchanged. A generator that ignores `TRACEPARENT` is fully conformant and behaves exactly as it did. ### Deferred, deliberately OTel **logs** (the `slog` bridge, and with it any per-generator tagging of inherited stderr — log records carry their own resource, so the transform may never be worth building) and **metrics**. Traces first: they are the signal that justifies the propagation work, and settling provider construction and flush-on-exit once makes both of the others small.
No due date•12/12 issues closed