1+ import json
12import os
23import random
34import threading
45from datetime import datetime , timezone
56from typing import Optional , List , Callable , TYPE_CHECKING , Any
67
78from sentry_sdk .utils import format_timestamp , safe_repr
8- from sentry_sdk .envelope import Envelope
9+ from sentry_sdk .envelope import Envelope , Item
910
1011if TYPE_CHECKING :
1112 from sentry_sdk ._types import Log
@@ -97,34 +98,36 @@ def flush(self):
9798 self ._flush ()
9899
99100 @staticmethod
100- def _log_to_otel (log ):
101+ def _log_to_transport_format (log ):
101102 # type: (Log) -> Any
102- def format_attribute (key , val ):
103- # type: (str, int | float | str | bool) -> Any
103+ def format_attribute (val ):
104+ # type: (int | float | str | bool) -> Any
104105 if isinstance (val , bool ):
105- return {"key " : key , "value " : { "boolValue" : val } }
106+ return {"value " : val , "type " : "boolean" }
106107 if isinstance (val , int ):
107- return {"key " : key , "value " : { "intValue" : str ( val )} }
108+ return {"value " : str ( val ) , "type " : "integer" }
108109 if isinstance (val , float ):
109- return {"key " : key , "value " : { "doubleValue" : val } }
110+ return {"value " : val , "type " : "double" }
110111 if isinstance (val , str ):
111- return {"key" : key , "value" : {"stringValue" : val }}
112- return {"key" : key , "value" : {"stringValue" : safe_repr (val )}}
113-
114- otel_log = {
115- "severityText" : log ["severity_text" ],
116- "severityNumber" : log ["severity_number" ],
117- "body" : {"stringValue" : log ["body" ]},
118- "timeUnixNano" : str (log ["time_unix_nano" ]),
119- "attributes" : [
120- format_attribute (k , v ) for (k , v ) in log ["attributes" ].items ()
121- ],
112+ return {"value" : val , "type" : "string" }
113+ return {"value" : safe_repr (val ), "type" : "string" }
114+
115+ print (log ["attributes" ])
116+ res = {
117+ "timestamp" : int (log ["time_unix_nano" ]) / 1.0e9 ,
118+ "trace_id" : log .get ("trace_id" , "00000000-0000-0000-0000-000000000000" ),
119+ "level" : str (log ["severity_text" ]),
120+ "body" : str (log ["body" ]),
121+ "attributes" : {
122+ k : format_attribute (v ) for (k , v ) in log ["attributes" ].items ()
123+ },
122124 }
123125
124- if "trace_id" in log :
125- otel_log ["traceId" ] = log ["trace_id" ]
126+ res ["attributes" ]["sentry.severity_number" ] = format_attribute (
127+ log ["severity_number" ]
128+ )
126129
127- return otel_log
130+ return res
128131
129132 def _flush (self ):
130133 # type: (...) -> Optional[Envelope]
@@ -133,10 +136,27 @@ def _flush(self):
133136 headers = {"sent_at" : format_timestamp (datetime .now (timezone .utc ))}
134137 )
135138 with self ._lock :
136- for log in self ._log_buffer :
137- envelope .add_log (self ._log_to_otel (log ))
139+ if len (self ._log_buffer ) == 0 :
140+ return None
141+
142+ envelope .add_item (
143+ Item (
144+ type = "log" ,
145+ content_type = "application/vnd.sentry.items.log+json" ,
146+ headers = {
147+ "item_count" : len (self ._log_buffer ),
148+ },
149+ payload = json .dumps (
150+ {
151+ "items" : [
152+ self ._log_to_transport_format (log )
153+ for log in self ._log_buffer
154+ ]
155+ }
156+ ),
157+ )
158+ )
138159 self ._log_buffer .clear ()
139- if envelope .items :
140- self ._capture_func (envelope )
141- return envelope
142- return None
160+
161+ self ._capture_func (envelope )
162+ return envelope
0 commit comments