5757 from typing import Union
5858 from typing import TypeVar
5959
60- from sentry_sdk ._types import Event , Hint , SDKInfo
60+ from sentry_sdk ._types import Event , Hint , SDKInfo , Log
6161 from sentry_sdk .integrations import Integration
6262 from sentry_sdk .metrics import MetricsAggregator
6363 from sentry_sdk .scope import Scope
@@ -862,17 +862,6 @@ def capture_log(self, scope, severity_text, severity_number, template, **kwargs)
862862 "sent_at" : format_timestamp (datetime .now (timezone .utc )),
863863 } # type: dict[str, object]
864864
865- def format_attribute (key : str , val : int | float | str | bool ):
866- if isinstance (val , int ):
867- return {"key" : key , "value" : {"int_value" : val }}
868- if isinstance (val , str ):
869- return {"key" : key , "value" : {"string_value" : val }}
870- if isinstance (val , float ):
871- return {"key" : key , "value" : {"double_value" : val }}
872- if isinstance (val , bool ):
873- return {"key" : key , "value" : {"bool_value" : val }}
874- return {"key" : key , "value" : {"string_value" : json .dumps (val )}}
875-
876865 attrs = {
877866 "sentry.message.template" : template ,
878867 }
@@ -885,6 +874,7 @@ def format_attribute(key: str, val: int | float | str | bool):
885874 for k , v in kwargs .items ():
886875 attrs [f"sentry.message.parameters.{ k } " ] = v
887876
877+ # type: Log
888878 log = {
889879 "severity_text" : severity_text ,
890880 "severity_number" : severity_number ,
@@ -901,20 +891,40 @@ def format_attribute(key: str, val: int | float | str | bool):
901891 before_send_log = self .options .get ("before_send_log" )
902892 if before_send_log is not None :
903893 log = before_send_log (log )
894+ if log is None :
895+ return
904896
905- # convert to otel form - otel_log has a different schema than just 'log'
906- log ["body" ] = {"string_value" : log ["body" ]}
907- log ["attributes" ] = [
908- format_attribute (k , v ) for (k , v ) in log ["attributes" ].items ()
909- ]
910-
911- envelope .add_log (log ) # TODO: batch these
897+ def format_attribute (key , val ):
898+ # type: (str, int | float | str | bool) -> Any
899+ if isinstance (val , int ):
900+ return {"key" : key , "value" : {"intValue" : val }}
901+ if isinstance (val , str ):
902+ return {"key" : key , "value" : {"stringValue" : val }}
903+ if isinstance (val , float ):
904+ return {"key" : key , "value" : {"doubleValue" : val }}
905+ if isinstance (val , bool ):
906+ return {"key" : key , "value" : {"boolValue" : val }}
907+ return {"key" : key , "value" : {"stringValue" : json .dumps (val )}}
908+
909+ otel_log = {
910+ "severityText" : log ["severity_text" ],
911+ "severityNumber" : log ["severity_number" ],
912+ "body" : {"stringValue" : log ["body" ]},
913+ "timeUnixNano" : str (log ["time_unix_nano" ]),
914+ }
915+ if isinstance ((attrs := log ["attributes" ]), dict ):
916+ otel_log ["attributes" ] = [
917+ format_attribute (k , v ) for (k , v ) in attrs .items ()
918+ ]
919+ if "trace_id" in log :
920+ otel_log ["traceId" ] = log ["trace_id" ]
921+
922+ envelope .add_log (otel_log ) # TODO: batch these
912923 if self .spotlight :
913924 self .spotlight .capture_envelope (envelope )
914925
915926 if self .transport is not None :
916927 self .transport .capture_envelope (envelope )
917- return None
918928
919929 def capture_session (
920930 self , session # type: Session
0 commit comments