Add exception.type to OTel exception span events; sanitize event attributes#25972
Add exception.type to OTel exception span events; sanitize event attributes#25972
Conversation
…vent attributes - Extract colon-prefixed type from error messages (e.g., "push_to_pull_request_branch:...") as "gh-aw.push_to_pull_request_branch"; fall back to "gh-aw.AgentError" - Strip the type prefix from exception.message when extracted - Extend sanitizeOTLPPayload to sanitize span.events[].attributes (redact sensitive keys, truncate long values) — closes the gap where event attributes bypassed redaction - Add 7 new tests covering type extraction, fallback, invalid prefixes, and event attribute sanitization Agent-Logs-Url: https://github.com/github/gh-aw/sessions/71aeea08-33f4-412c-8716-0866e880672e Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR updates OTLP exception span events emitted by sendJobConclusionSpan to include exception.type (per OTel semantic conventions) and closes a redaction gap by sanitizing span.events[].attributes in sanitizeOTLPPayload.
Changes:
- Emit
exception.typealongsideexception.messagefor exception events, with type extraction from colon-prefixed error messages and a fallback type. - Extend
sanitizeOTLPPayloadto apply attribute redaction/truncation tospan.events[].attributes. - Add/extend tests covering event-attribute sanitization and
exception.typeextraction/fallback behavior.
Show a summary per file
| File | Description |
|---|---|
| actions/setup/js/send_otlp_span.cjs | Adds event-attribute sanitization and emits exception.type for exception span events. |
| actions/setup/js/send_otlp_span.test.cjs | Adds tests for event attribute sanitization and exception type extraction/fallback cases. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 2/2 changed files
- Comments generated: 1
| // Extract colon-prefixed type when available ("push_to_pull_request_branch:...") | ||
| const colonIdx = msg.indexOf(":"); | ||
| const exceptionType = colonIdx > 0 && colonIdx < 64 && /^[a-z_][a-z0-9_.]*$/i.test(msg.slice(0, colonIdx)) ? `gh-aw.${msg.slice(0, colonIdx)}` : "gh-aw.AgentError"; | ||
| const exceptionMessage = (colonIdx > 0 && exceptionType !== "gh-aw.AgentError" ? msg.slice(colonIdx + 1).trim() : msg).slice(0, MAX_ATTR_VALUE_LENGTH); |
There was a problem hiding this comment.
The prefix validation regex is case-insensitive (/i), but the PR description/spec says the identifier must match ^[a-z_][a-z0-9_.]*$ (lowercase only). As-is, messages like Push_To_PR:... would be treated as a valid type and emitted as gh-aw.Push_To_PR, which can lead to inconsistent exception.type values and diverges from the documented behavior. Consider removing the i flag (or normalizing the extracted prefix to lowercase before validation/emission) and adding a test to cover uppercase prefixes (either expected rejection or normalization).
🧪 Test Quality Sentinel ReportTest Quality Score: 90/100✅ Excellent test quality
Test Classification Details📋 All 7 new test functions (click to expand)
Modified tests (3 existing tests had
Flagged Tests — Minor Issues Only
|
| Component | Points | Notes |
|---|---|---|
| Behavioral Coverage (40 pts) | 40 | All 7 new tests are design tests |
| Error/Edge Case Coverage (30 pts) | 30 | All 7 include error paths or boundary conditions |
| Low Duplication (20 pts) | 20 | No duplicate clusters detected |
| Proportional Growth (10 pts) | 0 | Inflation flag triggered (6.17:1); context-appropriate but mechanically penalized |
| Total | 90 |
Verdict
✅ Check passed. 0% of new tests are implementation tests (threshold: 30%). All 7 new tests verify observable outputs and behavioral contracts of the new
exception.typeextraction logic and event-attribute sanitization.
📖 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.
🧪 Test quality analysis by Test Quality Sentinel · ● 454K · ◷
There was a problem hiding this comment.
✅ Test Quality Sentinel: 90/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%). All 7 new tests verify behavioral contracts of the exception.type extraction and event-attribute sanitization features. Minor suggestions posted in the comment above.
|
@copilot review all comments |
…ping Addresses review feedback: the regex accepts mixed-case prefixes but the extracted type is now lowercased before emission, ensuring consistent exception.type values (e.g., "Push_To_PR:..." → "gh-aw.push_to_pr"). Adds a test covering uppercase prefix normalization. Agent-Logs-Url: https://github.com/github/gh-aw/sessions/d1e40e6f-5461-4f60-a911-7dda914b4b87 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Addressed the review feedback about the case-insensitive regex in |
Exception span events in
sendJobConclusionSpanonly emitexception.message—exception.typeis never set, violating OTel semantic conventions and preventing backends (Tempo, Honeycomb, Datadog) from classifying/grouping errors. Separately,sanitizeOTLPPayloadredactsspan.attributesbut skipsspan.events[].attributes, so exception messages bypass sensitive-key redaction.Changes
Add
exception.typeextraction — parse colon-prefixed error messages (push_to_pull_request_branch:Cannot push...→ typegh-aw.push_to_pull_request_branch, messageCannot push...). Falls back togh-aw.AgentErrorwhen no valid identifier prefix exists (must match^[a-z_][a-z0-9_.]*$, length < 64). Mixed-case prefixes are accepted but normalized to lowercase for consistent grouping (e.g.,Push_To_PR:...→gh-aw.push_to_pr).Sanitize event attributes — extend
sanitizeOTLPPayloadto applysanitizeAttrs()tospan.events[].attributes, closing the redaction gap.8 new tests covering type extraction, lowercase normalization, fallback cases, and event attribute sanitization. All 159 tests pass.