Skip to content

feat: add trigger item context (item_type, item_number, trigger_label) to all OTel spans#29003

Merged
pelikhan merged 2 commits intomainfrom
copilot/otel-improvement-add-trigger-item-context
Apr 29, 2026
Merged

feat: add trigger item context (item_type, item_number, trigger_label) to all OTel spans#29003
pelikhan merged 2 commits intomainfrom
copilot/otel-improvement-add-trigger-item-context

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 28, 2026

Every gh-aw workflow is triggered by a concrete GitHub item (issue, PR, discussion, check run), but neither sendJobSetupSpan nor sendJobConclusionSpan emitted any of that context — making spans impossible to correlate with the triggering item in Grafana/Honeycomb.

Changes

send_otlp_span.cjs

  • Both sendJobSetupSpan and sendJobConclusionSpan now read item_type, item_number, and trigger_label from awInfo.context (already written to /tmp/gh-aw/aw_info.json by buildAwContext()) and conditionally emit them as span attributes:
    • gh-aw.trigger.item_typeissue, pull_request, discussion, check_run, etc.
    • gh-aw.trigger.item_number — sequential number of the triggering item
    • gh-aw.trigger.label — label name for labeled/unlabeled events; omitted otherwise
  • All three attributes are omitted (not emitted as empty strings) when the source field is absent or empty

send_otlp_span.test.cjs

  • 6 new tests (3 per function): attribute emission with/without trigger_label, and clean omission when aw_info.json is absent

Example span attributes on an issue-triggered run:

{ "key": "gh-aw.trigger.item_type",   "value": { "stringValue": "issue" } },
{ "key": "gh-aw.trigger.item_number", "value": { "stringValue": "42"    } }

Add gh-aw.trigger.item_type, gh-aw.trigger.item_number, and
gh-aw.trigger.label span attributes to both sendJobSetupSpan and
sendJobConclusionSpan. These are read from awInfo.context in
aw_info.json, which is written by buildAwContext() and contains
the item_type, item_number, and trigger_label fields resolved from
the GitHub event payload.

Fixes #<issue-number>

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/add39553-beaa-4834-b682-cb9c26b4f0b9

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Add trigger item context to all spans feat: add trigger item context (item_type, item_number, trigger_label) to all OTel spans Apr 29, 2026
Copilot AI requested a review from pelikhan April 29, 2026 00:07
@pelikhan pelikhan marked this pull request as ready for review April 29, 2026 00:19
Copilot AI review requested due to automatic review settings April 29, 2026 00:19
@pelikhan pelikhan merged commit 05e33cf into main Apr 29, 2026
10 checks passed
@pelikhan pelikhan deleted the copilot/otel-improvement-add-trigger-item-context branch April 29, 2026 00:19
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds triggering GitHub item context to OTLP spans so traces can be correlated back to the originating issue/PR/discussion/check in observability backends.

Changes:

  • Enriches sendJobSetupSpan and sendJobConclusionSpan with gh-aw.trigger.item_type, gh-aw.trigger.item_number, and optional gh-aw.trigger.label attributes sourced from aw_info.json.
  • Updates inline documentation to describe the new attributes.
  • Adds unit tests covering attribute emission/omission behavior for both spans.
Show a summary per file
File Description
actions/setup/js/send_otlp_span.cjs Reads trigger context from aw_info.json and conditionally emits it as span attributes for setup and conclusion spans.
actions/setup/js/send_otlp_span.test.cjs Adds tests validating trigger attribute presence/absence (including when aw_info.json is missing).

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (1)

actions/setup/js/send_otlp_span.cjs:725

  • Same normalization concern as in sendJobSetupSpan: these awInfo.context fields are not trimmed. If a caller provides whitespace-only values in aw_context (which is accepted as primitives by generate_aw_info), they will be emitted as non-empty span attributes. Trimming before checking/adding the attributes would prevent spans from being tagged with effectively-empty trigger metadata.
  const itemType = typeof awInfo.context?.item_type === "string" ? awInfo.context.item_type : "";
  const itemNumber = typeof awInfo.context?.item_number === "string" ? awInfo.context.item_number : "";
  const triggerLabel = typeof awInfo.context?.trigger_label === "string" ? awInfo.context.trigger_label : "";
  • Files reviewed: 2/2 changed files
  • Comments generated: 1

Comment on lines +475 to +477
const itemType = typeof awInfo.context?.item_type === "string" ? awInfo.context.item_type : "";
const itemNumber = typeof awInfo.context?.item_number === "string" ? awInfo.context.item_number : "";
const triggerLabel = typeof awInfo.context?.trigger_label === "string" ? awInfo.context.trigger_label : "";
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

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

itemType, itemNumber, and triggerLabel are taken verbatim from awInfo.context and later emitted when truthy. If any of these fields are whitespace-only (e.g. " "), they will be emitted as span attributes even though they are effectively empty. Consider normalizing with .trim() (and using the trimmed value for both the if (...) check and the attribute value) so empty/whitespace values are cleanly omitted, matching the stated behavior of omitting empty strings.

This issue also appears on line 723 of the same file.

Suggested change
const itemType = typeof awInfo.context?.item_type === "string" ? awInfo.context.item_type : "";
const itemNumber = typeof awInfo.context?.item_number === "string" ? awInfo.context.item_number : "";
const triggerLabel = typeof awInfo.context?.trigger_label === "string" ? awInfo.context.trigger_label : "";
const itemType = typeof awInfo.context?.item_type === "string" ? awInfo.context.item_type.trim() : "";
const itemNumber = typeof awInfo.context?.item_number === "string" ? awInfo.context.item_number.trim() : "";
const triggerLabel = typeof awInfo.context?.trigger_label === "string" ? awInfo.context.trigger_label.trim() : "";

Copilot uses AI. Check for mistakes.
@github-actions github-actions Bot mentioned this pull request Apr 29, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 80/100

Excellent test quality

Metric Value
New/modified tests analyzed 6
✅ Design tests (behavioral contracts) 6 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 6 (100%)
Duplicate test clusters 0
Test inflation detected Yes (150 test lines / 23 production lines ≈ 6.5:1)
🚨 Coding-guideline violations 0

Test Classification Details

View All 6 Tests
Test File Classification Notes
emits gh-aw.trigger.item_type and gh-aw.trigger.item_number from aw_info.context (setup) send_otlp_span.test.cjs:1575 ✅ Design Verifies OTLP span attributes; also asserts trigger.label is absent when empty
emits gh-aw.trigger.label when trigger_label is non-empty (setup) send_otlp_span.test.cjs:1598 ✅ Design Verifies conditional attribute inclusion — behavioral contract
omits trigger attributes when aw_info.json is absent (setup) send_otlp_span.test.cjs:~1620 ✅ Design Edge case: graceful degradation when config file is missing
emits gh-aw.trigger.item_type and gh-aw.trigger.item_number from aw_info.context (conclusion) send_otlp_span.test.cjs:3275 ✅ Design Same behavioral contract verified for sendJobConclusionSpan
emits gh-aw.trigger.label when trigger_label is non-empty (conclusion) send_otlp_span.test.cjs:3298 ✅ Design Conditional attribute inclusion for conclusion span
omits trigger attributes when aw_info.json is absent (conclusion) send_otlp_span.test.cjs:~3320 ✅ Design Edge case: missing file for conclusion span

⚠️ Test Inflation Note

The test-to-production line ratio is 150:23 (≈ 6.5:1), exceeding the 2:1 threshold. This triggers the mechanical inflation penalty (-10 pts), lowering the score from 90 to 80.

In practice, this is not a quality concern — JavaScript integration tests for OTLP spans legitimately require substantial setup boilerplate (vi.spyOn(fs, 'readFileSync'), vi.stubGlobal('fetch'), env var management). The 23 production lines changed are tightly targeted additions, while the 150 test lines provide thorough behavioral coverage across two span functions. No action needed.


Language Support

Tests analyzed:

  • 🟨 JavaScript (*.test.cjs): 6 tests (vitest) — all new tests in actions/setup/js/send_otlp_span.test.cjs

Verdict

Check passed. 0% of new tests are implementation tests (threshold: 30%). All 6 new tests verify behavioral contracts — they assert on the actual OTLP span attribute payload sent over the wire, covering the happy path (item_type + item_number present), conditional inclusion (trigger_label only when non-empty), and the edge case (missing aw_info.json). Mocking targets (fs.readFileSync, fetch) are external I/O, which is appropriate.


📖 Understanding Test Classifications

Design Tests (High Value) verify what the system does:

  • Assert on observable outputs, return values, or state changes
  • Cover error paths and boundary conditions
  • Would catch a behavioral regression if deleted
  • Remain valid even after internal refactoring

Implementation Tests (Low Value) verify how the system does it:

  • Assert on internal function calls (mocking internals)
  • Only test the happy path with typical inputs
  • Break during legitimate refactoring even when behavior is correct
  • Give false assurance: they pass even when the system is wrong

Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.


References: §25084524194

🧪 Test quality analysis by Test Quality Sentinel · ● 1.1M ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 80/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%). All 6 new tests verify behavioral contracts on OTLP span attributes.

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.

[otel-advisor] OTel improvement: add trigger item context (item_type, item_number, trigger_label) to all spans

3 participants