| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
can we target next instead of main here and also fix the diff to pass lint? |
Sorry, something went wrong.
Spans exported to SGP always showed status=SUCCESS even when the operation they represent failed. The SGP span defaults status to "SUCCESS" and only flips to "ERROR" inside its own __exit__ context manager, but the agentex processor builds SGP spans via create_span(...) and flushes them directly, so __exit__ never runs. The Trace.span()/AsyncTrace.span() context managers also ended spans in a bare finally, so a body exception was never recorded. Capture the exception in both context managers and carry it on the span so the SGP processor can map it: - add span_error.py with set_span_error/get_span_error, storing the failure under the reserved span.data["__error__"] key (the Span model is generated from the OpenAPI spec and has no status/error field; data is a real field that survives model_copy(deep=True) and round-trips to both stores) - Trace.span()/AsyncTrace.span(): except -> set_span_error(span, exc); raise - _build_sgp_span(): when an error is present, set sgp_span.status = "ERROR" plus error/error.type/error.message metadata (matching SGP's native __exit__ shape) Exceptions still propagate; asyncio.CancelledError/KeyboardInterrupt are not flagged (control flow, not failures). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
| Back | FazBrowse Home | New Git URL |
Problem
Spans exported to SGP always show status=SUCCESS, even when the operation they represent failed.
Root cause, in three parts:
Net effect: a failing operation is indistinguishable from a successful one in SGP.
Fix (SDK-only, no schema/backend change)
Capture → carry → map:
Exceptions still propagate unchanged. asyncio.CancelledError / KeyboardInterrupt are intentionally not flagged (control flow, not failures) — broaden the except to BaseException if that changes.
Tests
tests/lib/core/tracing/test_span_error.py:
ruff check clean; new + existing tracing tests pass (40 passed).
🤖 Generated with Claude Code
Greptile Summary
This PR fixes a bug where all spans exported to SGP always showed status=SUCCESS, even when the operation they represented failed. The root cause was that the agentex processor builds SGP spans via create_span and flushes them directly, bypassing the __exit__ context manager that normally flips status to ERROR.
Confidence Score: 5/5
Safe to merge. The change only touches the tracing layer, exceptions always re-propagate unchanged, and the success path is unaffected.
The fix is well-scoped: error capture happens before the span is flushed, the error key survives model_copy(deep=True) and recursive_model_dump, and the SGP status mapping is exercised by both the new unit tests and the existing tracing test suite (40 pass). No mutation of span identity fields, no change to public API surfaces, and no risk to callers that don't catch exceptions themselves.
No files require special attention.
Important Files Changed
Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant UC as User Code participant CM as Trace.span() / AsyncTrace.span() participant SE as span_error.py participant ES as end_span() participant SGP as _build_sgp_span() UC->>CM: enter context manager CM->>CM: start_span() CM-->>UC: yield span alt Exception raised in body UC-->>CM: raise Exception CM->>SE: set_span_error(span, exc) Note over SE: span.data["__error__"] = {type, message} CM->>CM: re-raise CM->>ES: finally: end_span(span) ES->>SGP: on_span_end(span) SGP->>SE: get_span_error(span) SE-->>SGP: "{type, message}" SGP->>SGP: sgp_span.set_error(error_type, error_message) Note over SGP: sgp_span.status = ERROR SGP->>SGP: sgp_span.flush() else Success UC-->>CM: normal return CM->>ES: finally: end_span(span) ES->>SGP: on_span_end(span) SGP->>SE: get_span_error(span) returns None Note over SGP: sgp_span.status stays SUCCESS SGP->>SGP: sgp_span.flush() end%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant UC as User Code participant CM as Trace.span() / AsyncTrace.span() participant SE as span_error.py participant ES as end_span() participant SGP as _build_sgp_span() UC->>CM: enter context manager CM->>CM: start_span() CM-->>UC: yield span alt Exception raised in body UC-->>CM: raise Exception CM->>SE: set_span_error(span, exc) Note over SE: span.data["__error__"] = {type, message} CM->>CM: re-raise CM->>ES: finally: end_span(span) ES->>SGP: on_span_end(span) SGP->>SE: get_span_error(span) SE-->>SGP: "{type, message}" SGP->>SGP: sgp_span.set_error(error_type, error_message) Note over SGP: sgp_span.status = ERROR SGP->>SGP: sgp_span.flush() else Success UC-->>CM: normal return CM->>ES: finally: end_span(span) ES->>SGP: on_span_end(span) SGP->>SE: get_span_error(span) returns None Note over SGP: sgp_span.status stays SUCCESS SGP->>SGP: sgp_span.flush() endReviews (3): Last reviewed commit: "fix(tracing): capture span body exceptio..." | Re-trigger Greptile