The Monday I stopped opening the Actions REST API
The last time somebody asked me which workflows in our org were the slow ones, I ended up in a spreadsheet stitched together from three tabs of the Actions REST API. I would like that afternoon back. So when George Sims dropped a post on the CNCF blog today about tracing GitHub Actions without touching a single workflow file, I read it twice and then I read it again with a terminal open.
The pitch is exactly what it sounds like. You do not add a step to every workflow. You do not fork a reusable action. You listen, once, at the org level, to what GitHub is already telling you.
How the receiver plugs in
The moving part is the OpenTelemetry Collector's githubreceiver, a contrib component the post is upfront about calling alpha. You point GitHub's org-level webhook at the collector and subscribe to workflow_run and workflow_job events. The receiver converts those events straight into OTLP spans and ships them to whatever trace backend you already run. Sims names Tempo, Jaeger and Datadog as options he has seen work.
There is no per-repo yaml to keep in sync, which is the entire appeal for me. If someone spins up a new repo tomorrow, its runs show up in the same traces without a PR. The one setup wrinkle: the webhook has to reach the collector, so you need a publicly addressable endpoint and org-admin access to add the webhook.
What the traces actually look like
The receiver builds a hierarchy that mirrors how you already think about a run. The workflow is the outer span. Jobs sit under it as children. Steps sit under the jobs. Trace and span IDs are hashed deterministically from the workflow's run ID, so a retry of the same run lines up on the same trace instead of scattering across the backend.
For me the interesting thing is what this makes cheap. "Which job in this workflow is dragging the whole thing out" becomes a flame graph you look at, not a query you write. "How long are jobs sitting queued before a runner picks them up" is a span attribute, not a REST-page you scrape. If you have ever tried to answer either of those questions across a busy org, you know the difference is measured in coffees.
Where the rough edges show up
A few things Sims flags, and one I noticed reading through.
The receiver has a metrics side, populated by scrapers, not webhooks. If you want the traces path only, the collector config still fails validation without at least a dummy scraper entry. That is the kind of thing you hit at minute forty-five of a green-field setup and remember for the rest of your career.
Alpha means alpha. The config shape is allowed to move, and if you build a lot of downstream tooling on the exact span attributes you are getting today you are signing up for maintenance later. GitHub Enterprise Server is called out as unvalidated, so if you are on GHES instead of github.com, plan to be the person who finds the bugs.
And the org-admin webhook requirement is a real gate. In some orgs that is a five-minute conversation, in others it is a quarter of governance work. Worth surfacing before you promise anyone a dashboard.
What I am watching next
Two things. First, whether the githubreceiver graduates past alpha, because I am not the only person who would like to build alerting on top of these spans without hedging on schema drift. Second, whether other CI systems get the same treatment in the collector's contrib tree. The receiver's approach, treating provider webhooks as a spans source instead of asking every pipeline author to instrument their own runs, is one of those quiet ideas that starts to look obvious once you have it. If you try it against your own org, I would love to hear what your first flame graph told you that a dashboard did not.
Top comments (0)