1010from sentry_sdk .consts import OP
1111from sentry_sdk .integrations import Integration
1212from sentry_sdk .integrations ._wsgi_common import _filter_headers
13- from sentry_sdk .scope import should_send_default_pii
13+ from sentry_sdk .integrations .cloud_resource_context import CLOUD_PROVIDER
14+ from sentry_sdk .scope import Scope , should_send_default_pii
15+ from sentry_sdk .traces import SegmentSource
1416from sentry_sdk .tracing import TransactionSource
17+ from sentry_sdk .tracing_utils import has_span_streaming_enabled
1518from sentry_sdk .utils import (
1619 AnnotatedValue ,
1720 TimeoutThread ,
@@ -82,16 +85,26 @@ def sentry_func(
8285 timeout_thread .start ()
8386
8487 headers = {}
88+ header_attributes : "dict[str, Any]" = {}
8589 if hasattr (gcp_event , "headers" ):
8690 headers = gcp_event .headers
91+ for header , header_value in _filter_headers (
92+ headers , use_annotated_value = False
93+ ).items ():
94+ header_attributes [f"http.request.header.{ header .lower ()} " ] = (
95+ # header_value will always be a string because we set `use_annotated_value` to false above
96+ header_value
97+ )
98+
99+ additional_attributes = {}
100+ if hasattr (gcp_event , "method" ):
101+ additional_attributes ["http.request.method" ] = gcp_event .method
102+
103+ if should_send_default_pii () and hasattr (gcp_event , "query_string" ):
104+ additional_attributes ["url.query" ] = gcp_event .query_string .decode (
105+ "utf-8" , errors = "replace"
106+ )
87107
88- transaction = continue_trace (
89- headers ,
90- op = OP .FUNCTION_GCP ,
91- name = environ .get ("FUNCTION_NAME" , "" ),
92- source = TransactionSource .COMPONENT ,
93- origin = GcpIntegration .origin ,
94- )
95108 sampling_context = {
96109 "gcp_env" : {
97110 "function_name" : environ .get ("FUNCTION_NAME" ),
@@ -102,9 +115,50 @@ def sentry_func(
102115 },
103116 "gcp_event" : gcp_event ,
104117 }
105- with sentry_sdk .start_transaction (
106- transaction , custom_sampling_context = sampling_context
107- ):
118+
119+ function_name = environ .get ("FUNCTION_NAME" , "<unknown GCP function>" )
120+
121+ if environ .get ("GCP_PROJECT" ):
122+ additional_attributes ["gcp.project.id" ] = environ .get ("GCP_PROJECT" )
123+
124+ if environ .get ("FUNCTION_IDENTITY" ):
125+ additional_attributes ["faas.identity" ] = environ .get (
126+ "FUNCTION_IDENTITY"
127+ )
128+
129+ if environ .get ("ENTRY_POINT" ):
130+ additional_attributes ["faas.entry_point" ] = environ .get ("ENTRY_POINT" )
131+
132+ if has_span_streaming_enabled (client .options ):
133+ sentry_sdk .traces .continue_trace (headers )
134+ Scope .set_custom_sampling_context (sampling_context )
135+ span_ctx = sentry_sdk .traces .start_span (
136+ name = function_name ,
137+ parent_span = None ,
138+ attributes = {
139+ "sentry.op" : OP .FUNCTION_GCP ,
140+ "sentry.origin" : GcpIntegration .origin ,
141+ "sentry.span.source" : SegmentSource .COMPONENT ,
142+ "cloud.provider" : CLOUD_PROVIDER .GCP ,
143+ "faas.name" : function_name ,
144+ ** header_attributes ,
145+ ** additional_attributes ,
146+ },
147+ )
148+ else :
149+ transaction = continue_trace (
150+ headers ,
151+ op = OP .FUNCTION_GCP ,
152+ name = environ .get ("FUNCTION_NAME" , "" ),
153+ source = TransactionSource .COMPONENT ,
154+ origin = GcpIntegration .origin ,
155+ )
156+
157+ span_ctx = sentry_sdk .start_transaction (
158+ transaction , custom_sampling_context = sampling_context
159+ )
160+
161+ with span_ctx :
108162 try :
109163 return func (functionhandler , gcp_event , * args , ** kwargs )
110164 except Exception :
@@ -181,7 +235,9 @@ def event_processor(event: "Event", hint: "Hint") -> "Optional[Event]":
181235 request ["method" ] = gcp_event .method
182236
183237 if hasattr (gcp_event , "query_string" ):
184- request ["query_string" ] = gcp_event .query_string .decode ("utf-8" )
238+ request ["query_string" ] = gcp_event .query_string .decode (
239+ "utf-8" , errors = "replace"
240+ )
185241
186242 if hasattr (gcp_event , "headers" ):
187243 request ["headers" ] = _filter_headers (gcp_event .headers )
0 commit comments