@@ -37,9 +37,44 @@ class TestSpanErrorHelpers:
3737 def test_set_then_get_on_none_data (self ):
3838 span = _make_span (data = None )
3939 set_span_error (span , ValueError ("boom" ))
40- assert get_span_error (span ) == {"type" : "ValueError" , "message" : "boom" }
40+ assert get_span_error (span ) == {
41+ "type" : "ValueError" ,
42+ "message" : "boom" ,
43+ "category" : "unknown" ,
44+ }
4145 assert isinstance (span .data , dict )
42- assert span .data [SPAN_ERROR_KEY ] == {"type" : "ValueError" , "message" : "boom" }
46+ assert span .data [SPAN_ERROR_KEY ] == {
47+ "type" : "ValueError" ,
48+ "message" : "boom" ,
49+ "category" : "unknown" ,
50+ }
51+
52+ def test_set_uses_explicit_exception_category (self ):
53+ class PlatformFailure (RuntimeError ):
54+ error_category = " PLATFORM "
55+
56+ span = _make_span (data = None )
57+ set_span_error (span , PlatformFailure ("unavailable" ))
58+ assert get_span_error (span ) == {
59+ "type" : "PlatformFailure" ,
60+ "message" : "unavailable" ,
61+ "category" : "platform" ,
62+ }
63+
64+ def test_explicit_category_takes_precedence (self ):
65+ class PlatformFailure (RuntimeError ):
66+ error_category = "platform"
67+
68+ span = _make_span (data = None )
69+ set_span_error (span , PlatformFailure ("bad input" ), error_category = "application" )
70+ assert get_span_error (span )["category" ] == "application" # type: ignore[index]
71+
72+ def test_set_rejects_invalid_exception_category (self ):
73+ exc = RuntimeError ("boom" )
74+ exc .error_category = "infrastructure" # type: ignore[attr-defined]
75+ span = _make_span (data = None )
76+ set_span_error (span , exc )
77+ assert get_span_error (span )["category" ] == "unknown" # type: ignore[index]
4378
4479 def test_set_preserves_existing_dict_keys (self ):
4580 span = _make_span (data = {"__span_type__" : "LLM" })
@@ -76,7 +111,11 @@ def test_sync_span_records_error_and_reraises(self):
76111 captured ["span" ] = span
77112 raise ValueError ("boom" )
78113 err = get_span_error (captured ["span" ])
79- assert err == {"type" : "ValueError" , "message" : "boom" }
114+ assert err == {
115+ "type" : "ValueError" ,
116+ "message" : "boom" ,
117+ "category" : "unknown" ,
118+ }
80119
81120 def test_sync_span_success_has_no_error (self ):
82121 trace = Trace (processors = [], client = MagicMock (), trace_id = "t1" )
@@ -93,7 +132,11 @@ async def test_async_span_records_error_and_reraises(self):
93132 captured ["span" ] = span
94133 raise RuntimeError ("kaboom" )
95134 err = get_span_error (captured ["span" ])
96- assert err == {"type" : "RuntimeError" , "message" : "kaboom" }
135+ assert err == {
136+ "type" : "RuntimeError" ,
137+ "message" : "kaboom" ,
138+ "category" : "unknown" ,
139+ }
97140
98141
99142# ---------------------------------------------------------------------------
@@ -111,7 +154,7 @@ def set_error(
111154 self ,
112155 error_type : str | None = None ,
113156 error_message : str | None = None ,
114- exception : BaseException | None = None ,
157+ exception : BaseException | None = None , # noqa: ARG002
115158 ) -> None :
116159 self .status = "ERROR"
117160 self .metadata ["error" ] = True
@@ -131,14 +174,23 @@ def _env():
131174 def test_error_maps_to_status_error (self ):
132175 from agentex .lib .core .tracing .processors .sgp_tracing_processor import _build_sgp_span
133176
134- span = _make_span (data = {SPAN_ERROR_KEY : {"type" : "ValueError" , "message" : "boom" }})
177+ span = _make_span (
178+ data = {
179+ SPAN_ERROR_KEY : {
180+ "type" : "ValueError" ,
181+ "message" : "boom" ,
182+ "category" : "application" ,
183+ }
184+ }
185+ )
135186 with patch (f"{ PROCESSOR_MODULE } .create_span" , side_effect = _fake_create_span ):
136187 sgp_span = _build_sgp_span (span , self ._env ())
137188
138189 assert sgp_span .status == "ERROR"
139190 assert sgp_span .metadata ["error" ] is True
140191 assert sgp_span .metadata ["error_type" ] == "ValueError"
141192 assert sgp_span .metadata ["error_message" ] == "boom"
193+ assert sgp_span .metadata ["error_category" ] == "application"
142194
143195 def test_no_error_leaves_status_success (self ):
144196 from agentex .lib .core .tracing .processors .sgp_tracing_processor import _build_sgp_span
0 commit comments