📡 OTel Instrumentation Improvement: add github.ref_name to span resource attributes
Analysis Date: 2026-04-22
Priority: Medium
Effort: Small (< 1h)
Problem
Every span currently captures github.ref (the full Git ref, e.g. refs/heads/main or refs/pull/123/merge), but never captures GITHUB_REF_NAME — the short, human-readable branch or tag name (e.g. main, v1.2.3, 123/merge). This env var is freely available in every GitHub Actions job via process.env.GITHUB_REF_NAME.
As a result, any query that filters or groups by branch name requires a string-strip operation on the full ref path. Most OTel backends (Grafana Tempo, Honeycomb, Datadog) do not support inline string transformation in their filter UIs, so branch-level dashboards are either impossible or require a derived field workaround.
The codebase already knows about GITHUB_REF_NAME — it is read in actions/setup/js/get_current_branch.cjs (line 32) — but send_otlp_span.cjs never reads it.
Why This Matters (DevOps Perspective)
The most common observability questions for a CI workflow system are:
- "Is the failure rate higher on PRs than on main?"
- "Which feature branch is consuming the most tokens?"
- "Are staging runs on
main slower than on release branches?"
All of these require filtering by branch name. With github.ref = "refs/heads/main" and no github.ref_name, engineers must use workarounds like github.ref contains "heads/main" — which breaks for refs/pull/*/merge PR refs entirely.
Adding github.ref_name unblocks these queries in every backend with zero backend-side configuration. Adding github.head_ref (the source branch for PRs) enables grouping by PR source branch specifically.
Current Behavior
// actions/setup/js/send_otlp_span.cjs — sendJobSetupSpan (lines ~490–528)
const ref = process.env.GITHUB_REF || ""; // "refs/heads/main"
// GITHUB_REF_NAME is never read here
// resource attributes include:
if (ref) {
resourceAttributes.push(buildAttr("github.ref", ref)); // "refs/heads/main"
}
// github.ref_name is missing — no way to filter by "main" directly
The same pattern repeats in sendJobConclusionSpan (lines ~792–806).
Proposed Change
// In both sendJobSetupSpan and sendJobConclusionSpan, after reading `ref`:
const ref = process.env.GITHUB_REF || "";
const refName = process.env.GITHUB_REF_NAME || ""; // "main", "v1.2.3", "123/merge"
const headRef = process.env.GITHUB_HEAD_REF || ""; // PR source branch, e.g. "feature-x"
// Then in the resourceAttributes block:
if (ref) {
resourceAttributes.push(buildAttr("github.ref", ref));
}
if (refName) {
resourceAttributes.push(buildAttr("github.ref_name", refName));
}
if (headRef) {
resourceAttributes.push(buildAttr("github.head_ref", headRef)); // only set for pull_request events
}
This is a ~6-line addition repeated in two functions. The headRef line is optional but high value: for PR workflows, github.head_ref = "feature-xyz" enables grouping by the real feature branch name (not the merge ref 123/merge).
Expected Outcome
After this change:
- In Grafana / Honeycomb / Datadog: Filter spans by
github.ref_name = "main" or group a heatmap by github.ref_name. PR source-branch grouping becomes possible via github.head_ref.
- In the JSONL mirror: Each span line will include
github.ref_name in its resource.attributes, making jq filtering trivial: jq 'select(.resourceSpans[].resource.attributes[] | select(.key == "github.ref_name") | .value.stringValue == "main")'
- For on-call engineers: Can immediately answer "does this failure pattern correlate with a specific branch?" without constructing a complex regex against
github.ref.
Implementation Steps
Evidence from Static Analysis
The gap was confirmed by cross-referencing:
send_otlp_span.cjs lines 489–527 — GITHUB_REF is read and emitted as github.ref; GITHUB_REF_NAME is absent entirely.
actions/setup/js/get_current_branch.cjs line 32 — the same codebase already reads GITHUB_REF_NAME for other purposes, confirming the variable is available at runtime.
- Live Sentry data: The Sentry MCP server returned an empty tools list (endpoint
(host.docker.internal/redacted) returned []), so live span payloads could not be sampled. The recommendation is based solely on static analysis. Once Sentry access is restored, sampling a recent span's resource.attributesarray and confirming the absence ofgithub.ref_name` would validate this finding empirically.
Related Files
actions/setup/js/send_otlp_span.cjs — primary change site (both sendJobSetupSpan and sendJobConclusionSpan)
actions/setup/js/get_current_branch.cjs — demonstrates GITHUB_REF_NAME is already used in the repo
actions/setup/js/action_setup_otlp.cjs — no change needed (delegates to sendJobSetupSpan)
actions/setup/js/action_conclusion_otlp.cjs — no change needed (delegates to sendJobConclusionSpan)
Generated by the Daily OTel Instrumentation Advisor workflow
Generated by Daily OTel Instrumentation Advisor · ● 157.4K · ◷
📡 OTel Instrumentation Improvement: add
github.ref_nameto span resource attributesAnalysis Date: 2026-04-22
Priority: Medium
Effort: Small (< 1h)
Problem
Every span currently captures
github.ref(the full Git ref, e.g.refs/heads/mainorrefs/pull/123/merge), but never capturesGITHUB_REF_NAME— the short, human-readable branch or tag name (e.g.main,v1.2.3,123/merge). This env var is freely available in every GitHub Actions job viaprocess.env.GITHUB_REF_NAME.As a result, any query that filters or groups by branch name requires a string-strip operation on the full ref path. Most OTel backends (Grafana Tempo, Honeycomb, Datadog) do not support inline string transformation in their filter UIs, so branch-level dashboards are either impossible or require a derived field workaround.
The codebase already knows about
GITHUB_REF_NAME— it is read inactions/setup/js/get_current_branch.cjs(line 32) — butsend_otlp_span.cjsnever reads it.Why This Matters (DevOps Perspective)
The most common observability questions for a CI workflow system are:
mainslower than on release branches?"All of these require filtering by branch name. With
github.ref = "refs/heads/main"and nogithub.ref_name, engineers must use workarounds likegithub.ref contains "heads/main"— which breaks forrefs/pull/*/mergePR refs entirely.Adding
github.ref_nameunblocks these queries in every backend with zero backend-side configuration. Addinggithub.head_ref(the source branch for PRs) enables grouping by PR source branch specifically.Current Behavior
The same pattern repeats in
sendJobConclusionSpan(lines ~792–806).Proposed Change
This is a ~6-line addition repeated in two functions. The
headRefline is optional but high value: for PR workflows,github.head_ref = "feature-xyz"enables grouping by the real feature branch name (not the merge ref123/merge).Expected Outcome
After this change:
github.ref_name = "main"or group a heatmap bygithub.ref_name. PR source-branch grouping becomes possible viagithub.head_ref.github.ref_namein itsresource.attributes, makingjqfiltering trivial:jq 'select(.resourceSpans[].resource.attributes[] | select(.key == "github.ref_name") | .value.stringValue == "main")'github.ref.Implementation Steps
actions/setup/js/send_otlp_span.cjs, addconst refName = process.env.GITHUB_REF_NAME || "";andconst headRef = process.env.GITHUB_HEAD_REF || "";in bothsendJobSetupSpan(around line 495) andsendJobConclusionSpan(around line 695)buildAttr("github.ref_name", refName)(conditional on truthy) intoresourceAttributesin both functions, immediately after the existinggithub.refpushbuildAttr("github.head_ref", headRef)(conditional on truthy) for PR event enrichmentsend_otlp_span.test.cjs) to setprocess.env.GITHUB_REF_NAME = "main"and assert the attribute appears in the resource attributes of both setup and conclusion payloadscd actions/setup/js && npx vitest runto confirm tests passmake fmtto ensure formattingEvidence from Static Analysis
The gap was confirmed by cross-referencing:
send_otlp_span.cjslines 489–527 —GITHUB_REFis read and emitted asgithub.ref;GITHUB_REF_NAMEis absent entirely.actions/setup/js/get_current_branch.cjsline 32 — the same codebase already readsGITHUB_REF_NAMEfor other purposes, confirming the variable is available at runtime.(host.docker.internal/redacted) returned[]), so live span payloads could not be sampled. The recommendation is based solely on static analysis. Once Sentry access is restored, sampling a recent span'sresource.attributesarray and confirming the absence ofgithub.ref_name` would validate this finding empirically.Related Files
actions/setup/js/send_otlp_span.cjs— primary change site (bothsendJobSetupSpanandsendJobConclusionSpan)actions/setup/js/get_current_branch.cjs— demonstratesGITHUB_REF_NAMEis already used in the repoactions/setup/js/action_setup_otlp.cjs— no change needed (delegates tosendJobSetupSpan)actions/setup/js/action_conclusion_otlp.cjs— no change needed (delegates tosendJobConclusionSpan)Generated by the Daily OTel Instrumentation Advisor workflow