Skip to content

ADR-0003: Write one wide event per stage run, in OpenTelemetry shape, as local JSON lines

Status: Accepted

Date: October 2026

People need to query the record afterwards, for example to see which stage costs the most or why runs stop at the gate. Cyclix takes tens of issues a week, and an issue can take days to reach a merge.

  • Each stage run writes one wide event. A wide event holds everything needed to understand one piece of work, and is written once, when the work ends.
  • Each event is a log record in the OpenTelemetry data model. Field names follow OpenTelemetry where it has one (gen_ai.*, vcs.*, cicd.*). Cyclix’s own fields start with cyclix.. Every line records the schema version.
  • Events go to a local file under the state directory, one JSON object per line. Cyclix ships no query tool.
  • Each stage run is its own trace. Every event carries cyclix.issue.id, so grouping by it shows an issue’s whole life.
  • Keep every event. Do not sample.
  • Events hold IDs and numbers, never content. The writer refuses a string over 500 characters.
  • One query follows an issue through the stages.
  • Tools built for OpenTelemetry can read the events with little change.
  • The writer refuses a key that is not in the schema. Add a new key to Engine first, then to events/schema.py.
  • A change to the schema raises the version.

Many small events, one per step the code takes. Rejected. The log should say what happened to the work, not what the code did.

One trace per issue. Rejected. Tracing tools are built for spans that last seconds or minutes, not days.

Sampling. Rejected. At tens of issues a week, keeping every event costs little.