22from functools import wraps
33
44import sentry_sdk
5+ import sentry_sdk .traces
6+ from sentry_sdk .consts import OP
57from sentry_sdk .integrations import DidNotEnable , Integration
8+ from sentry_sdk .integrations ._wsgi_common import _filter_headers
69from sentry_sdk .integrations .aws_lambda import _make_request_event_processor
10+ from sentry_sdk .integrations .cloud_resource_context import (
11+ CLOUD_PLATFORM ,
12+ CLOUD_PROVIDER ,
13+ )
14+ from sentry_sdk .traces import SegmentSource
715from sentry_sdk .tracing import TransactionSource
16+ from sentry_sdk .tracing_utils import has_span_streaming_enabled
817from sentry_sdk .utils import (
918 capture_internal_exceptions ,
1019 event_from_exception ,
@@ -40,18 +49,38 @@ def __call__(self, event: "Any", context: "Any") -> "Any":
4049 scope .add_event_processor (
4150 _make_request_event_processor (event , context , configured_time )
4251 )
43- try :
44- return ChaliceEventSourceHandler .__call__ (self , event , context )
45- except Exception :
46- exc_info = sys .exc_info ()
47- event , hint = event_from_exception (
48- exc_info ,
49- client_options = client .options ,
50- mechanism = {"type" : "chalice" , "handled" : False },
51- )
52- sentry_sdk .capture_event (event , hint = hint )
53- client .flush ()
54- reraise (* exc_info )
52+
53+ if has_span_streaming_enabled (client .options ):
54+ with sentry_sdk .traces .start_span (
55+ name = context .function_name ,
56+ parent_span = None ,
57+ 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 )
71+ else :
72+ try :
73+ return ChaliceEventSourceHandler .__call__ (self , event , context )
74+ except Exception :
75+ exc_info = sys .exc_info ()
76+ sentry_event , hint = event_from_exception (
77+ exc_info ,
78+ client_options = client .options ,
79+ mechanism = {"type" : "chalice" , "handled" : False },
80+ )
81+ sentry_sdk .capture_event (sentry_event , hint = hint )
82+ client .flush ()
83+ reraise (* exc_info )
5584
5685
5786def _get_view_function_response (
@@ -63,38 +92,78 @@ def wrapped_view_function(**function_args: "Any") -> "Any":
6392 with sentry_sdk .isolation_scope () as scope :
6493 with capture_internal_exceptions ():
6594 configured_time = app .lambda_context .get_remaining_time_in_millis ()
66- scope .set_transaction_name (
67- app .lambda_context .function_name ,
68- source = TransactionSource .COMPONENT ,
69- )
70-
7195 scope .add_event_processor (
7296 _make_request_event_processor (
7397 app .current_request .to_dict (),
7498 app .lambda_context ,
7599 configured_time ,
76100 )
77101 )
78- try :
79- return view_function (** function_args )
80- except Exception as exc :
81- if isinstance (exc , ChaliceViewError ):
82- raise
83- exc_info = sys .exc_info ()
84- event , hint = event_from_exception (
85- exc_info ,
86- client_options = client .options ,
87- mechanism = {"type" : "chalice" , "handled" : False },
102+
103+ if has_span_streaming_enabled (client .options ):
104+ aws_context = app .lambda_context
105+ request_dict = app .current_request .to_dict ()
106+ headers = request_dict .get ("headers" , {}) or {}
107+
108+ header_attrs : "Dict[str, Any]" = {}
109+ for header , value in _filter_headers (
110+ headers , use_annotated_value = False
111+ ).items ():
112+ header_attrs [f"http.request.header.{ header .lower ()} " ] = value
113+
114+ additional_attrs : "Dict[str, Any]" = {}
115+ if "method" in request_dict :
116+ additional_attrs ["http.request.method" ] = request_dict ["method" ]
117+
118+ with sentry_sdk .traces .start_span (
119+ name = aws_context .function_name ,
120+ parent_span = None ,
121+ attributes = {
122+ ** _get_lambda_span_attributes (aws_context ),
123+ ** header_attrs ,
124+ ** additional_attrs ,
125+ },
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 ()
140+ raise
141+ else :
142+ scope .set_transaction_name (
143+ app .lambda_context .function_name ,
144+ source = TransactionSource .COMPONENT ,
88145 )
89- sentry_sdk .capture_event (event , hint = hint )
90- client .flush ()
91- raise
146+ try :
147+ return view_function (** function_args )
148+ except Exception as exc :
149+ if isinstance (exc , ChaliceViewError ):
150+ raise
151+ exc_info = sys .exc_info ()
152+ sentry_event , hint = event_from_exception (
153+ exc_info ,
154+ client_options = client .options ,
155+ mechanism = {"type" : "chalice" , "handled" : False },
156+ )
157+ sentry_sdk .capture_event (sentry_event , hint = hint )
158+ client .flush ()
159+ raise
92160
93161 return wrapped_view_function # type: ignore
94162
95163
96164class ChaliceIntegration (Integration ):
97165 identifier = "chalice"
166+ origin = f"auto.function.{ identifier } "
98167
99168 @staticmethod
100169 def setup_once () -> None :
@@ -129,3 +198,25 @@ def sentry_event_response(
129198 RestAPIEventHandler ._get_view_function_response = sentry_event_response
130199 # for everything else (like events)
131200 chalice .app .EventSourceHandler = EventSourceHandler
201+
202+
203+ def _get_lambda_span_attributes (aws_context : "Any" ) -> "Dict[str, Any]" :
204+ invoked_arn = aws_context .invoked_function_arn
205+ split_invoked_arn = invoked_arn .split (":" )
206+ aws_region = split_invoked_arn [3 ] if len (split_invoked_arn ) > 3 else "unknown"
207+
208+ return {
209+ "sentry.op" : OP .FUNCTION_AWS ,
210+ "sentry.origin" : ChaliceIntegration .origin ,
211+ "sentry.span.source" : SegmentSource .COMPONENT ,
212+ "cloud.platform" : CLOUD_PLATFORM .AWS_LAMBDA ,
213+ "cloud.provider" : CLOUD_PROVIDER .AWS ,
214+ "faas.name" : aws_context .function_name ,
215+ "cloud.region" : aws_region ,
216+ "cloud.resource_id" : invoked_arn ,
217+ "aws.lambda.invoked_arn" : invoked_arn ,
218+ "faas.invocation_id" : aws_context .aws_request_id ,
219+ "faas.version" : aws_context .function_version ,
220+ "aws.log.group.names" : [aws_context .log_group_name ],
221+ "aws.log.stream.names" : [aws_context .log_stream_name ],
222+ }
0 commit comments