Skip to content

Commit d637c2f

Browse files
committed
1 parent 6df89ee commit d637c2f

2 files changed

Lines changed: 62 additions & 30 deletions

File tree

sentry_sdk/integrations/chalice.py

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
CLOUD_PLATFORM,
1212
CLOUD_PROVIDER,
1313
)
14-
from sentry_sdk.traces import SegmentSource
14+
from sentry_sdk.traces import SegmentSource, SpanStatus
1515
from sentry_sdk.tracing import TransactionSource
1616
from sentry_sdk.tracing_utils import has_span_streaming_enabled
1717
from sentry_sdk.utils import (
@@ -51,23 +51,27 @@ def __call__(self, event: "Any", context: "Any") -> "Any":
5151
)
5252

5353
if has_span_streaming_enabled(client.options):
54-
with sentry_sdk.traces.start_span(
54+
span = sentry_sdk.traces.start_span(
5555
name=context.function_name,
5656
parent_span=None,
5757
attributes=_get_lambda_span_attributes(context),
58-
):
59-
try:
60-
return ChaliceEventSourceHandler.__call__(self, event, context)
61-
except Exception:
62-
exc_info = sys.exc_info()
63-
sentry_event, hint = event_from_exception(
64-
exc_info,
65-
client_options=client.options,
66-
mechanism={"type": "chalice", "handled": False},
67-
)
68-
sentry_sdk.capture_event(sentry_event, hint=hint)
69-
client.flush()
70-
reraise(*exc_info)
58+
)
59+
try:
60+
return ChaliceEventSourceHandler.__call__(self, event, context)
61+
except Exception:
62+
exc_info = sys.exc_info()
63+
span.status = SpanStatus.ERROR.value
64+
sentry_event, hint = event_from_exception(
65+
exc_info,
66+
client_options=client.options,
67+
mechanism={"type": "chalice", "handled": False},
68+
)
69+
sentry_sdk.capture_event(sentry_event, hint=hint)
70+
reraise(*exc_info)
71+
finally:
72+
span.end()
73+
client.flush()
74+
7175
else:
7276
try:
7377
return ChaliceEventSourceHandler.__call__(self, event, context)
@@ -115,29 +119,32 @@ def wrapped_view_function(**function_args: "Any") -> "Any":
115119
if "method" in request_dict:
116120
additional_attrs["http.request.method"] = request_dict["method"]
117121

118-
with sentry_sdk.traces.start_span(
122+
span = sentry_sdk.traces.start_span(
119123
name=aws_context.function_name,
120124
parent_span=None,
121125
attributes={
122126
**_get_lambda_span_attributes(aws_context),
123127
**header_attrs,
124128
**additional_attrs,
125129
},
126-
):
127-
try:
128-
return view_function(**function_args)
129-
except Exception as exc:
130-
if isinstance(exc, ChaliceViewError):
131-
raise
132-
exc_info = sys.exc_info()
133-
sentry_event, hint = event_from_exception(
134-
exc_info,
135-
client_options=client.options,
136-
mechanism={"type": "chalice", "handled": False},
137-
)
138-
sentry_sdk.capture_event(sentry_event, hint=hint)
139-
client.flush()
130+
)
131+
try:
132+
return view_function(**function_args)
133+
except Exception as exc:
134+
if isinstance(exc, ChaliceViewError):
140135
raise
136+
exc_info = sys.exc_info()
137+
span.status = SpanStatus.ERROR.value
138+
sentry_event, hint = event_from_exception(
139+
exc_info,
140+
client_options=client.options,
141+
mechanism={"type": "chalice", "handled": False},
142+
)
143+
sentry_sdk.capture_event(sentry_event, hint=hint)
144+
raise
145+
finally:
146+
span.end()
147+
client.flush()
141148
else:
142149
scope.set_transaction_name(
143150
app.lambda_context.function_name,

tests/integrations/chalice/test_chalice.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ def test_span_streaming_basic(
236236
assert attrs["aws.log.stream.names"] == ["2024/01/01/[$LATEST]abcdef1234567890"]
237237
assert attrs["http.request.method"] == "GET"
238238
assert attrs["http.request.header.x-custom-header"] == "test-value"
239+
assert span["status"] == "ok"
239240

240241

241242
def test_span_streaming_error(
@@ -263,6 +264,29 @@ def test_span_streaming_error(
263264
attrs = segment_spans[0]["attributes"]
264265
assert attrs["sentry.op"] == "function.aws"
265266
assert attrs["sentry.origin"] == "auto.function.chalice"
267+
assert segment_spans[0]["status"] == "error"
268+
269+
270+
def test_span_streaming_error_flush_ordering(
271+
sentry_init,
272+
capture_items,
273+
):
274+
"""The handler's own client.flush() must send the segment span.
275+
276+
If flush runs before the span ends, the segment won't be in the
277+
transport without an extra sentry_sdk.flush() call after the request.
278+
On Lambda, the worker can freeze right after the response, so there's
279+
no second chance.
280+
"""
281+
app = _make_span_streaming_app(sentry_init)
282+
client = RequestHandler(app)
283+
items = capture_items("span")
284+
285+
response = client.get("/boom")
286+
assert response.status_code == 500
287+
288+
segment_spans = [s.payload for s in items if s.payload.get("is_segment")]
289+
assert len(segment_spans) == 1
266290

267291

268292
def test_span_streaming_scheduled_event(
@@ -328,3 +352,4 @@ def every_hour(event):
328352
assert attrs["faas.version"] == "$LATEST"
329353
assert attrs["aws.log.group.names"] == ["/aws/lambda/lambda_name"]
330354
assert attrs["aws.log.stream.names"] == ["2024/01/01/[$LATEST]abcdef1234567890"]
355+
assert segment_spans[0]["status"] == "error"

0 commit comments

Comments
 (0)