Moving Beyond the Console
OpenTelemetry (OTel) is a vendor-neutral, open-source standard for generating, collecting, and exporting telemetry data (traces, metrics, and logs). It is maintained by the Cloud Native Computing Foundation (CNCF) and is the industry standard for distributed tracing. While it is most commonly associated with instrumenting backend APIs, it is equally powerful when applied to CI pipelines.
By instrumenting your CI system — using plugins for Jenkins, GitHub Actions, or GitLab CI — every pipeline run generates a Trace. A trace is a tree of Spans, where each span represents one unit of work with a start time, end time, and attached metadata (called attributes or tags).
For a typical CI pipeline, the span hierarchy looks like this:
- Root Span: The entire pipeline run (e.g.,
pipeline: frontend-build). - Child Spans: Each stage within the pipeline (e.g.,
stage: build,stage: test,stage: deploy). - Grandchild Spans: Each step within a stage (e.g.,
step: checkout,step: npm install,step: run unit tests). - Great-grandchild Spans: Individual operations within a step, if instrumented (e.g.,
http.request: POST registry.npmjs.org).
Why This Is Better Than the GitHub or Jenkins UI
The GitHub Actions or Jenkins UI shows you a green or red box with a log tail. A trace shows you the timeline with proportional durations. The difference is the difference between a doctor saying "the patient is sick" versus showing you an MRI.
With a trace in a tool like Grafana Tempo, Honeycomb, or Jaeger, you can:
- Identify the slow step instantly. Instead of reading 2,000 lines of logs, you see that
npm installtook 4 minutes and every other step took under 10 seconds. - Correlate with infrastructure attributes. Each span can carry tags like
runner.id,runner.region,runner.os. You can filter all traces whererunner.region = us-east-1and discover that jobs on that region are consistently 30% slower due to a degraded network link. - Compare across runs. You can overlay the trace from today's slow build against yesterday's fast build and see exactly which span regressed.
- Detect flakiness patterns. A test that passes 95% of the time but fails 5% of the time will show a distinct span pattern in the failing traces — often a timeout on an external HTTP call.
Instrumenting a Pipeline with OTel
Most CI platforms have community or first-party OTel integrations. The general pattern is:
- A plugin or wrapper script starts a root span when the pipeline begins.
- Each stage/job/step is wrapped to create child spans automatically.
- On completion, the trace is exported to an OTel Collector endpoint (e.g.,
http://otel-collector:4317). - The collector forwards the data to your backend (Grafana Tempo, Honeycomb, Datadog, etc.).
For GitHub Actions, the open-telemetry/opentelemetry-collector-contrib project and community actions like inception-health/otel-export-trace-action can export workflow traces. For Jenkins, the opentelemetry-plugin is a mature, first-party solution maintained by the Jenkins project.
Interviewers at platform engineering roles often ask: "How do you debug a slow CI pipeline?" A weak answer is "I look at the logs." A strong answer is: "I instrument the pipeline with OpenTelemetry to generate traces, then use a tool like Grafana Tempo to identify which span accounts for the regression. I also separate queue time from execution time before drawing any conclusions, because they have completely different root causes and fixes."
Key Point: OTel traces are only as useful as the attributes attached to them. A span that just says step: test with a duration is helpful. A span that also carries runner.id=runner-042, runner.region=eu-west-1, git.branch=feature/auth, cache.hit=false, and test.count=1247 is actionable. Invest time in enriching your spans with metadata — this is what separates a useful observability setup from a vanity dashboard.