Skip to content

Emit per-test-target OTel spans with test status in BES tracing sink - #1369

Open
thesayyn wants to merge 2 commits into
mainfrom
claude/axl-cli-otel-test-spans-52xxpx
Open

Emit per-test-target OTel spans with test status in BES tracing sink#1369
thesayyn wants to merge 2 commits into
mainfrom
claude/axl-cli-otel-test-spans-52xxpx

Conversation

@thesayyn

@thesayyn thesayyn commented Aug 4, 2026

Copy link
Copy Markdown
Member

The BES→OTel tracing sink only spanned action events (the TestRunner spawn, which reports the spawn's exit code — 0 for a spawn that merely ran) and dropped TestSummary/TestResult via the catch-all arm. Failing tests were invisible in OTel: every TestRunner span carried exit_code=0 and no error status.

Changes (crates/axl-runtime/src/engine/bazel/sink/tracing.rs):

  • New test span from TestSummary — the authoritative per-target outcome: status (BlazeTestStatus), run/shard/attempt counts, cached count, real wall-clock timing, and otel.status_code=error on FAILED/TIMEOUT/FAILED_TO_BUILD/REMOTE_FAILURE/TOOL_HALTED_BEFORE_TESTING.
  • New test_attempt span from TestResult — per shard/run/attempt status + timing.
  • otel.status_code on failed action spans.
  • Every other BES event kind recorded as a lightweight bes_event span-event (high-volume Progress/NamedSetOfFiles intentionally skipped) so nothing is silently dropped.

Unit tests cover the status→span-status mapping.

🤖 Generated with Claude Code


Generated by Claude Code

The Bazel BES→OTel tracing sink only spanned the `action` events (the
TestRunner spawn, which reports the spawn's exit code — 0 for a spawn that
merely executed) and dropped `TestSummary`/`TestResult` via the catch-all
arm. Failing tests were therefore invisible in OTel: every TestRunner span
carried exit_code 0 and no error status.

Add dedicated spans:
- `test` (from TestSummary): the authoritative per-target outcome, carrying
  the BlazeTestStatus, run/shard/attempt counts, cached count, real
  wall-clock timing (first_start_time..last_stop_time), and
  otel.status_code=error on FAILED/TIMEOUT/FAILED_TO_BUILD/REMOTE_FAILURE/
  TOOL_HALTED_BEFORE_TESTING.
- `test_attempt` (from TestResult): per shard/run/attempt status + timing.

Also set otel.status_code on failed `action` spans, and record every other
BES event kind as a lightweight `bes_event` span-event (the high-volume
Progress and NamedSetOfFiles streams are intentionally skipped) so no
meaningful build event is silently dropped.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3b84c5ecae

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread crates/axl-runtime/src/engine/bazel/sink/tracing.rs Outdated
@aspect-workflows

aspect-workflows Bot commented Aug 4, 2026

Copy link
Copy Markdown

✨ Aspect Workflows Tasks

📅 Tue Aug 4 21:08:23 UTC 2026

❌ 4 failed tasks

  • ❌ delivery-uncacheable [delivery] · ⏱ 35.6s · ✨ Aspect · 🐙 GitHub Actions
    💬 failed in deliver · Delivery failed (1 delivery fail)
  • ❌ format-gha-debug [format] · ⏱ 1m 22s · 🐙 GitHub Actions · ☑️ Check
    💬 failed in diff · Format failed (1 file needs format)
  • ❌ format-format-repeat-task [format] · ⏱ 1m 27s · 🐙 GitHub Actions · ☑️ Check
    💬 failed in diff · Format failed (1 file needs format)
  • ❌ format-gha [format] · ⏱ 1m 24s · 🐙 GitHub Actions · ☑️ Check
    💬 failed in diff · Format failed (1 file needs format)

⚠️ 3 flagged tasks

  • ⚠️ delivery-gha-debug [delivery] · ⏱ 35.6s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Delivery complete (1 delivered · 2 warn · 4 skipped)
  • ⚠️ delivery-gha [delivery] · ⏱ 45.6s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Delivery complete (1 delivered · 2 warn · 4 skipped)
  • ⚠️ delivery-uncacheable-warn [delivery] · ⏱ 13.8s · ✨ Aspect · 🐙 GitHub Actions
    💬 Delivery complete (1 warn)

✅ 22 successful tasks

  • ✅ axl-smoke-gha-bootstrap [build] · ⏱ 21.9s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel build complete (1 built)
  • ✅ run-axl-smoke [run] · ⏱ 33.2s · 🐙 GitHub Actions · ☑️ Check
    💬 Ran //examples/deliverable:py_deliverable
  • ✅ run-axl-smoke-2 [run] · ⏱ 41.9s · 🐙 GitHub Actions · ☑️ Check
    💬 Ran //examples/deliverable:sh_deliverable
  • ✅ axl-tests-gha-bootstrap [build] · ⏱ 22.7s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel build complete (1 built)
  • ✅ build-gha-debug [build] · ⏱ 7m 5s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel build complete (172 built)
  • ✅ build-gha [build] · ⏱ 7m 50s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel build complete (172 built)
  • ✅ build-gha-ephemeral [build] · ⏱ 47.8s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel build complete (10 built)
  • ✅ buildifier-gha-debug [buildifier] · ⏱ 33.1s · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ buildifier-gha [buildifier] · ⏱ 44.2s · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ delivery-no-remote-exec [delivery] · ⏱ 7.7s · ✨ Aspect · 🐙 GitHub Actions
    💬 Delivery complete (no deliveries)
  • ✅ gazelle-gha-debug [gazelle] · ⏱ 28.3s · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ gazelle-from-source-gha-debug [gazelle] · ⏱ 1m 57s · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ gazelle-from-source-gha [gazelle] · ⏱ 1m 48s · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ gazelle-gha [gazelle] · ⏱ 45.9s · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ init-shell [build] · ⏱ 23.7s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel build complete (10 built)
  • ✅ lint-gha-debug [lint] · ⏱ 42.2s · 🐙 GitHub Actions · ☑️ Check
    💬 Lint complete (clean)
  • ✅ lint-gha [lint] · ⏱ 51.9s · 🐙 GitHub Actions · ☑️ Check
    💬 Lint complete (clean)
  • ✅ test-gha-debug [test] · ⏱ 6m 33s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (26/26 passed · 23 cached)
  • ✅ test-gha-coverage [test] · ⏱ 28s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed · 1 cached)
  • ✅ test-gha-target-pattern-file [test] · ⏱ 22.6s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed · 1 cached)
  • ✅ test-gha [test] · ⏱ 6m 37s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (26/26 passed · 26 cached)
  • ✅ test-gha-ephemeral [test] · ⏱ 38.8s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)

🛠️ Fix

❌ format (format-gha-debug · format-format-repeat-task · format-gha)

aspect format --severity=info -- crates/axl-runtime/src/engine/bazel/sink/tracing.rs

Install aspect: aspect.build/docs/cli/install

🔁 Reproduce

❌ format (format-gha-debug · format-format-repeat-task · format-gha)

aspect format --severity=fail --base-ref=origin/main

❌ delivery (delivery-uncacheable · delivery-gha-debug · delivery-gha · delivery-uncacheable-warn)

# --mode=always --track-state=false for off-runner with no state backend.
aspect delivery \
  --commit-sha=e44d524b4e337fc4be812ecc9a0570e1bf3fbeb1 \
  --mode=always \
  --track-state=false \
  --dry-run=true

Install aspect: aspect.build/docs/cli/install


⏱ Last updated Tue Aug 4 21:21:46 UTC 2026 · 📊 GitHub API quota 220/15,000 (1% used, resets in 48m)
🚀 Powered by Aspect CLI (v0.0.0-dev)  |  Aspect Build · X · LinkedIn · YouTube

TestSummary/TestResult spans read only the modern `first_start_time`/
`last_stop_time`/`test_attempt_start`/`test_attempt_duration` Timestamp
fields, falling back to `SystemTime::now()` (or zero duration) when they
were absent. Older Bazel versions and cached summaries populate only the
deprecated `*_millis` fields, so those spans were exported at consume time
rather than the real test window.

Prefer the modern Timestamp, then the deprecated millis field (converted
to seconds, matching the OTel layer's `otel.start_time`/`otel.end_time`
seconds contract), then `now`/zero as a last resort.
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants