Skip to content

Commit b41f443

Browse files
committed
Simplify status mapping
1 parent b230b84 commit b41f443

File tree

2 files changed

+34
-79
lines changed

2 files changed

+34
-79
lines changed

sentry_sdk/opentelemetry/utils.py

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -219,53 +219,50 @@ def infer_description(span: ReadableSpan) -> Optional[str]:
219219

220220

221221
def extract_span_status(span: ReadableSpan) -> tuple[Optional[str], Optional[int]]:
222+
"""
223+
Extract a reasonable Sentry SPANSTATUS and a HTTP status code from the otel span.
224+
OKs are simply OKs.
225+
ERRORs first try to map to HTTP/GRPC statuses via attributes otherwise fallback
226+
on the description if it is a valid status for Sentry.
227+
In the final UNSET case, we try to infer HTTP/GRPC.
228+
"""
222229
span_attributes = span.attributes or {}
223-
status = span.status or None
224-
225-
if status:
226-
inferred_status, http_status = infer_status_from_attributes(span_attributes)
227-
228-
if status.status_code == StatusCode.OK:
229-
return (SPANSTATUS.OK, http_status)
230-
elif status.status_code == StatusCode.ERROR:
231-
if status.description is None:
232-
if inferred_status:
233-
return (inferred_status, http_status)
234-
235-
if http_status is not None:
236-
return (inferred_status, http_status)
237-
238-
if (
239-
status.description is not None
240-
and status.description in GRPC_ERROR_MAP.values()
241-
):
242-
return (status.description, None)
243-
else:
244-
return (SPANSTATUS.UNKNOWN_ERROR, None)
245-
246-
inferred_status, http_status = infer_status_from_attributes(span_attributes)
247-
if inferred_status:
248-
return (inferred_status, http_status)
249-
250-
if status and status.status_code == StatusCode.UNSET:
251-
return (None, None)
230+
status = span.status
231+
http_status = get_http_status_code(span_attributes)
232+
final_status = None
233+
234+
if status.status_code == StatusCode.OK:
235+
final_status = SPANSTATUS.OK
236+
elif status.status_code == StatusCode.ERROR:
237+
inferred_status = infer_status_from_attributes(span_attributes, http_status)
238+
239+
if inferred_status is not None:
240+
final_status = inferred_status
241+
elif (
242+
status.description is not None
243+
and status.description in GRPC_ERROR_MAP.values()
244+
):
245+
final_status = status.description
246+
else:
247+
final_status = SPANSTATUS.UNKNOWN_ERROR
252248
else:
253-
return (SPANSTATUS.UNKNOWN_ERROR, None)
249+
# UNSET case
250+
final_status = infer_status_from_attributes(span_attributes, http_status)
254251

252+
return (final_status, http_status)
255253

256-
def infer_status_from_attributes(
257-
span_attributes: Mapping[str, Any],
258-
) -> tuple[Optional[str], Optional[int]]:
259-
http_status = get_http_status_code(span_attributes)
260254

255+
def infer_status_from_attributes(
256+
span_attributes: Mapping[str, Any], http_status: Optional[int]
257+
) -> Optional[str]:
261258
if http_status:
262-
return (get_span_status_from_http_code(http_status), http_status)
259+
return get_span_status_from_http_code(http_status)
263260

264261
grpc_status = span_attributes.get(SpanAttributes.RPC_GRPC_STATUS_CODE)
265262
if grpc_status:
266-
return (GRPC_ERROR_MAP.get(str(grpc_status), SPANSTATUS.UNKNOWN_ERROR), None)
263+
return GRPC_ERROR_MAP.get(str(grpc_status), SPANSTATUS.UNKNOWN_ERROR)
267264

268-
return (None, None)
265+
return None
269266

270267

271268
def get_http_status_code(span_attributes: Mapping[str, Any]) -> Optional[int]:

tests/opentelemetry/test_utils.py

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -219,31 +219,6 @@ def test_span_data_for_db_query():
219219
@pytest.mark.parametrize(
220220
"kind, status, attributes, expected",
221221
[
222-
(
223-
SpanKind.CLIENT,
224-
None, # None means unknown error
225-
{
226-
"http.method": "POST",
227-
"http.route": "/some/route",
228-
},
229-
{
230-
"status": "unknown_error",
231-
"http_status_code": None,
232-
},
233-
),
234-
(
235-
SpanKind.CLIENT,
236-
None,
237-
{
238-
"http.method": "POST",
239-
"http.route": "/some/route",
240-
"http.status_code": 502, # Take this status in case of None status
241-
},
242-
{
243-
"status": "internal_error",
244-
"http_status_code": 502,
245-
},
246-
),
247222
(
248223
SpanKind.SERVER,
249224
Status(StatusCode.UNSET),
@@ -269,23 +244,6 @@ def test_span_data_for_db_query():
269244
"http_status_code": 502,
270245
},
271246
),
272-
(
273-
SpanKind.SERVER,
274-
None,
275-
{
276-
"http.method": "POST",
277-
"http.route": "/some/route",
278-
"http.status_code": 502,
279-
"http.response.status_code": 503, # this takes precedence over deprecated http.status_code
280-
},
281-
{
282-
"status": "unavailable",
283-
"http_status_code": 503,
284-
# old otel versions won't take the new attribute into account
285-
"status_old": "internal_error",
286-
"http_status_code_old": 502,
287-
},
288-
),
289247
(
290248
SpanKind.SERVER,
291249
Status(StatusCode.UNSET),

0 commit comments

Comments
 (0)