π‘ OTel Instrumentation Improvement: add gh-aw.event_name as a span attribute
Analysis Date: 2026-04-11
Priority: Medium
Effort: Small (< 2h)
Problem
github.event_name (the GitHub Actions triggering event β issue_comment, pull_request, push, workflow_dispatch, etc.) is added to the resource attributes of every span, but there is no corresponding span attribute carrying the event type.
The existing gh-aw.* span attributes follow a deliberate mirroring pattern:
| Resource attribute |
Span attribute |
github.repository |
gh-aw.repository β
|
github.run_id |
gh-aw.run.id β
|
github.event_name |
(missing) β |
The gap means that to filter setup/conclusion spans by event type, an engineer must use backend-specific resource-attribute syntax rather than the consistent gh-aw.* span attribute namespace.
Affected functions (both in actions/setup/js/send_otlp_span.cjs):
sendJobSetupSpan β reads GITHUB_EVENT_NAME at line 483 but pushes it only to resourceAttributes (line 506), never to attributes
sendJobConclusionSpan β same pattern: reads eventName at line 679 but pushes it only to resourceAttributes (line 750)
Why This Matters (DevOps Perspective)
Filtering by event type is the most common first step when triaging a spike in failures. The question "are issue_comment-triggered jobs failing more than workflow_dispatch ones?" requires grouping spans by event type.
- Grafana Tempo: resource attributes require
resource.attributes["github.event_name"] syntax, a different filter path from span attributes
- Sentry: span attributes surface as first-class tags; resource attributes are merged at ingestion and may require different query prefixes
- Honeycomb: column-based β resource attributes that aren't promoted to columns require manual schema setup
With gh-aw.event_name in span attributes, any backend supports a straightforward WHERE gh-aw.event_name = 'issue_comment' filter without special configuration, matching the ergonomics already established by gh-aw.repository and gh-aw.run.id.
MTTR impact: When a new workflow misbehaves only on specific event types, an engineer today must know to look in resource attributes β a non-obvious extra step. With this attribute in the span, the event type is immediately visible in any span detail view.
Current Behavior
// Current: actions/setup/js/send_otlp_span.cjs (sendJobSetupSpan, lines 487β514)
const attributes = [
buildAttr("gh-aw.job.name", jobName),
buildAttr("gh-aw.workflow.name", workflowName),
buildAttr("gh-aw.run.id", runId), // mirrors github.run_id resource attr β
buildAttr("gh-aw.run.attempt", runAttempt),
buildAttr("gh-aw.run.actor", actor),
buildAttr("gh-aw.repository", repository), // mirrors github.repository resource attr β
// gh-aw.event_name is NOT here β
];
// ...
const resourceAttributes = [
buildAttr("github.repository", repository),
buildAttr("github.run_id", runId),
// ...
];
if (eventName) {
resourceAttributes.push(buildAttr("github.event_name", eventName)); // resource only
}
Proposed Change
// Proposed addition to sendJobSetupSpan (actions/setup/js/send_otlp_span.cjs)
const attributes = [
buildAttr("gh-aw.job.name", jobName),
buildAttr("gh-aw.workflow.name", workflowName),
buildAttr("gh-aw.run.id", runId),
buildAttr("gh-aw.run.attempt", runAttempt),
buildAttr("gh-aw.run.actor", actor),
buildAttr("gh-aw.repository", repository),
];
if (engineId) {
attributes.push(buildAttr("gh-aw.engine.id", engineId));
}
// ADD THIS:
if (eventName) {
attributes.push(buildAttr("gh-aw.event_name", eventName));
}
Apply the same addition to sendJobConclusionSpan (around line 714, after the existing conditional gh-aw.job.name push):
// In sendJobConclusionSpan β add after the existing attribute pushes
if (eventName) {
attributes.push(buildAttr("gh-aw.event_name", eventName));
}
Expected Outcome
After this change:
- In Grafana / Honeycomb / Sentry / Datadog:
gh-aw.event_name surfaces as a first-class span attribute, enabling GROUP BY gh-aw.event_name on setup and conclusion spans without special resource-attribute configuration
- In the JSONL mirror:
gh-aw.event_name appears in the spans[0].attributes array of every otel.jsonl entry, making event type immediately readable in artifact-based debugging
- For on-call engineers: filtering a span search to
gh-aw.event_name = issue_comment narrows scope in one click, matching the ergonomics of existing gh-aw.* filters
Implementation Steps
Evidence from Live Sentry Data
Sentry MCP tools were not available in this analysis environment, so live span payloads could not be sampled. The gap is confirmed by static code analysis:
send_otlp_span.cjs line 483: const eventName = process.env.GITHUB_EVENT_NAME || "";
send_otlp_span.cjs line 506: resourceAttributes.push(buildAttr("github.event_name", eventName)); β resource only
send_otlp_span.test.cjs line 1022β1033: existing test confirms github.event_name is in resource attributes β no parallel test exists for a span attribute
The design intent of mirroring resource attributes into the gh-aw.* span namespace is already established (gh-aw.repository / github.repository, gh-aw.run.id / github.run_id), making this an obvious completion of the existing pattern.
Related Files
actions/setup/js/send_otlp_span.cjs β primary change site (both sendJobSetupSpan and sendJobConclusionSpan)
actions/setup/js/send_otlp_span.test.cjs β add assertions for new span attribute
Generated by the Daily OTel Instrumentation Advisor workflow
Generated by Daily OTel Instrumentation Advisor Β· β 214.4K Β· β·
π‘ OTel Instrumentation Improvement: add
gh-aw.event_nameas a span attributeAnalysis Date: 2026-04-11
Priority: Medium
Effort: Small (< 2h)
Problem
github.event_name(the GitHub Actions triggering event βissue_comment,pull_request,push,workflow_dispatch, etc.) is added to the resource attributes of every span, but there is no corresponding span attribute carrying the event type.The existing
gh-aw.*span attributes follow a deliberate mirroring pattern:github.repositorygh-aw.repositoryβgithub.run_idgh-aw.run.idβgithub.event_nameThe gap means that to filter setup/conclusion spans by event type, an engineer must use backend-specific resource-attribute syntax rather than the consistent
gh-aw.*span attribute namespace.Affected functions (both in
actions/setup/js/send_otlp_span.cjs):sendJobSetupSpanβ readsGITHUB_EVENT_NAMEat line 483 but pushes it only toresourceAttributes(line 506), never toattributessendJobConclusionSpanβ same pattern: readseventNameat line 679 but pushes it only toresourceAttributes(line 750)Why This Matters (DevOps Perspective)
Filtering by event type is the most common first step when triaging a spike in failures. The question "are
issue_comment-triggered jobs failing more thanworkflow_dispatchones?" requires grouping spans by event type.resource.attributes["github.event_name"]syntax, a different filter path from span attributesWith
gh-aw.event_namein span attributes, any backend supports a straightforwardWHERE gh-aw.event_name = 'issue_comment'filter without special configuration, matching the ergonomics already established bygh-aw.repositoryandgh-aw.run.id.MTTR impact: When a new workflow misbehaves only on specific event types, an engineer today must know to look in resource attributes β a non-obvious extra step. With this attribute in the span, the event type is immediately visible in any span detail view.
Current Behavior
Proposed Change
Apply the same addition to
sendJobConclusionSpan(around line 714, after the existing conditionalgh-aw.job.namepush):Expected Outcome
After this change:
gh-aw.event_namesurfaces as a first-class span attribute, enablingGROUP BY gh-aw.event_nameon setup and conclusion spans without special resource-attribute configurationgh-aw.event_nameappears in thespans[0].attributesarray of everyotel.jsonlentry, making event type immediately readable in artifact-based debugginggh-aw.event_name = issue_commentnarrows scope in one click, matching the ergonomics of existinggh-aw.*filtersImplementation Steps
actions/setup/js/send_otlp_span.cjs, insidesendJobSetupSpan(around line 494), addif (eventName) attributes.push(buildAttr("gh-aw.event_name", eventName));actions/setup/js/send_otlp_span.cjs, insidesendJobConclusionSpan(around line 714), add the same conditional pushactions/setup/js/send_otlp_span.test.cjs, add assertions to thesendJobSetupSpanandsendJobConclusionSpantest suites:span.attributescontains{ key: "gh-aw.event_name", value: { stringValue: "workflow_dispatch" } }whenGITHUB_EVENT_NAMEis setspan.attributesdoes not containgh-aw.event_namewhenGITHUB_EVENT_NAMEis not setcd actions/setup/js && npx vitest runto confirm tests passmake fmtto ensure formattingEvidence from Live Sentry Data
Sentry MCP tools were not available in this analysis environment, so live span payloads could not be sampled. The gap is confirmed by static code analysis:
send_otlp_span.cjsline 483:const eventName = process.env.GITHUB_EVENT_NAME || "";send_otlp_span.cjsline 506:resourceAttributes.push(buildAttr("github.event_name", eventName));β resource onlysend_otlp_span.test.cjsline 1022β1033: existing test confirmsgithub.event_nameis in resource attributes β no parallel test exists for a span attributeThe design intent of mirroring resource attributes into the
gh-aw.*span namespace is already established (gh-aw.repository/github.repository,gh-aw.run.id/github.run_id), making this an obvious completion of the existing pattern.Related Files
actions/setup/js/send_otlp_span.cjsβ primary change site (bothsendJobSetupSpanandsendJobConclusionSpan)actions/setup/js/send_otlp_span.test.cjsβ add assertions for new span attributeGenerated by the Daily OTel Instrumentation Advisor workflow