Visualize GitHub Actions runs with Meziantou.GitHubActionsTracing

 
 
  • Gérald Barré

I recently released Meziantou.GitHubActionsTracing, a tool that converts GitHub Actions workflow runs into trace data.

In this post, I show how to use it to debug slow or flaky CI pipelines with timeline-based analysis instead of raw logs only.

#Why GitHub Actions runs are hard to diagnose

GitHub Actions logs are great for understanding what happened, but not for quickly seeing where time is spent.

When a workflow is slow, you usually need answers such as:

  • Which job or step consumed most of the total duration?
  • Was the build slow, or were tests slow?
  • Is this a one-off issue, or a recurring pattern?
  • Is it an issue with GitHub infrastructure, or something in my workflow?

With plain logs, this investigation is mostly manual. You jump between jobs, scroll, and estimate durations by hand.

This tool converts a workflow run into trace data so you can inspect it as a timeline, filter noisy spans, and focus on what matters.

#What Meziantou.GitHubActionsTracing exports

The export command accepts:

  • A GitHub Actions workflow run URL
  • A local run-info folder (or zip) previously downloaded with the tool

The generated trace includes jobs, steps, log groups, warnings and errors, MSBuild targets and tasks from binlog data, and TRX/JUnit test results found in artifacts.

You can then export this model in multiple formats:

  • Chromium trace JSON
  • Speedscope JSON
  • Interactive HTML viewer
  • OpenTelemetry (collector or file)

#Installation and requirements

Requirements:

  • .NET 10 SDK
  • GitHub authentication using GITHUB_TOKEN or the GitHub CLI (gh token show)

Install the global tool:

Shell
dotnet tool update --global Meziantou.GitHubActionsTracing

#Quick start: export a run to a timeline

Start with a workflow run URL:

Shell
Meziantou.GitHubActionsTracing export https://github.com/OWNER/REPO/actions/runs/123456 --format html

By default, output files are created in the current directory:

  • trace-<runId>.chromium.json for Chromium
  • trace-<runId>.speedscope.json for Speedscope
  • trace-<runId>.otel.json for OpenTelemetry file output
  • trace-<runId>.html for HTML

#Choosing an export format

  • chromium: timeline exploration in Chromium trace viewers (about://tracing / https://ui.perfetto.dev/).
  • speedscope: profile-style, flamegraph-oriented analysis.
  • html: a self-contained interactive viewer with swimlanes and flamegraph.
  • otel: sends data to an OTLP endpoint. Useful for integration with OpenTelemetry-based monitoring and analysis tools.
  • otel-file: writes OpenTelemetry data to a local file.

Examples:

Shell
Meziantou.GitHubActionsTracing export https://github.com/OWNER/REPO/actions/runs/123456 --format chromium
Meziantou.GitHubActionsTracing export https://github.com/OWNER/REPO/actions/runs/123456 --format speedscope
Meziantou.GitHubActionsTracing export https://github.com/OWNER/REPO/actions/runs/123456 --format html
Meziantou.GitHubActionsTracing export https://github.com/OWNER/REPO/actions/runs/123456 --format otel-file
Meziantou.GitHubActionsTracing export https://github.com/OWNER/REPO/actions/runs/123456 --otel-endpoint http://localhost:4317 --otel-protocol grpc

Sample HTML output:

Sample HTML output from Meziantou.GitHubActionsTracingInteractive HTML swimlane view generated from a GitHub Actions workflow run

If you use OpenTelemetry exporter environment variables, use the EXPORTER_ prefix (for example, EXPORTER_OTEL_EXPORTER_OTLP_ENDPOINT).

#Filtering noisy data

Large workflows can produce a lot of spans. Keep traces readable by filtering short entries and disabling specific span categories.

Shell
Meziantou.GitHubActionsTracing export https://github.com/OWNER/REPO/actions/runs/123456 --format html --minimum-test-duration 00:00:01 --minimum-binlog-duration 00:00:01 --include-binlog --include-tests

If you only want high-level workflow timing, disable detailed build and test spans:

Shell
Meziantou.GitHubActionsTracing export https://github.com/OWNER/REPO/actions/runs/123456 --format chromium --include-binlog false --include-tests false

#Reusing downloaded run information

If you need multiple exports from the same workflow run, download once and reuse locally:

Shell
Meziantou.GitHubActionsTracing download-run-info https://github.com/OWNER/REPO/actions/runs/123456 --output ./run-info
Meziantou.GitHubActionsTracing export ./run-info --chromium-path trace.chromium.json --speedscope-path trace.speedscope.json --html-path trace.html --otel-file-path trace.otel.json

This is useful for offline analysis and for comparing filters and formats without re-downloading artifacts.

#Automate trace export when a workflow completes

You can also automate this in GitHub Actions. Create a workflow triggered by workflow_run with types: [completed], then export traces and upload them as artifacts.

The repository contains a complete example:

The workflow does the following:

  1. Builds the workflow run URL from github.event.workflow_run.id.
  2. Downloads run metadata, logs, and artifacts using download-run-info.
  3. Runs export to generate Chromium, Speedscope, and OpenTelemetry files.
  4. Uploads generated trace files as workflow artifacts.

This pattern gives you ready-to-open trace files for every completed run without manual steps.

#Optional: process runs automatically with the webhook receiver

The repository also contains a webhook receiver app in Meziantou.GitHubActionsTracing.Server/.

Run from source:

PowerShell
dotnet run --project .\Meziantou.GitHubActionsTracing.Server\

A Docker image is available on GitHub Container Registry:

Shell
docker pull ghcr.io/meziantou/meziantou-git-hub-actions-tracing:latest

The service supports:

  • POST /webhooks/github for GitHub workflow_run events
  • POST /workflow-runs to queue a run manually

Configuration is under GitHubActionsTracingWebhook and includes:

  • WebhookSecret for X-Hub-Signature-256 validation
  • Output settings (OtelEndpoint, OtelPath, ChromiumPath, SpeedscopePath, HtmlPath)
  • Filtering settings (MinimumTestDuration, MinimumBinlogDuration, IncludeBinlog, IncludeTests)
  • Repository allow-lists (AllowedRepositoriesExact, AllowedRepositoriesPatterns)

#Additional resources

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?