1919
2020
2121def otel_attributes_to_dict (otel_attrs ):
22- # type: (List[ Mapping[str, Any] ]) -> Mapping[str, Any]
22+ # type: (Mapping[str, Any]) -> Mapping[str, Any]
2323 def _convert_attr (attr ):
2424 # type: (Mapping[str, Union[str, float, bool]]) -> Any
25- if "boolValue" in attr :
26- return bool ( attr ["boolValue" ])
27- if "doubleValue" in attr :
28- return float ( attr ["doubleValue" ])
29- if "intValue" in attr :
30- return int ( attr ["intValue" ])
31- if attr ["stringValue " ].startswith ("{" ):
25+ if attr [ "type" ] == "boolean" :
26+ return attr ["value" ]
27+ if attr [ "type" ] == "double" :
28+ return attr ["value" ]
29+ if attr [ "type" ] == "integer" :
30+ return attr ["value" ]
31+ if attr ["value " ].startswith ("{" ):
3232 try :
3333 return json .loads (attr ["stringValue" ])
3434 except ValueError :
3535 pass
36- return str (attr ["stringValue " ])
36+ return str (attr ["value " ])
3737
38- return {item [ "key" ] : _convert_attr (item [ "value" ] ) for item in otel_attrs }
38+ return {k : _convert_attr (v ) for ( k , v ) in otel_attrs . items () }
3939
4040
4141def envelopes_to_logs (envelopes : List [Envelope ]) -> List [Log ]:
4242 res = [] # type: List[Log]
4343 for envelope in envelopes :
4444 for item in envelope .items :
45- if item .type == "otel_log" :
46- log_json = item .payload .json
47- log = {
48- "severity_text" : log_json ["severityText" ],
49- "severity_number" : log_json ["severityNumber" ],
50- "body" : log_json ["body" ]["stringValue" ],
51- "attributes" : otel_attributes_to_dict (log_json ["attributes" ]),
52- "time_unix_nano" : int (log_json ["timeUnixNano" ]),
53- "trace_id" : None ,
54- } # type: Log
55- if "traceId" in log_json :
56- log ["trace_id" ] = log_json ["traceId" ]
57- res .append (log )
45+ if item .type == "log" :
46+ for log_json in item .payload .json ["items" ]:
47+ log = {
48+ "severity_text" : log_json ["attributes" ]["sentry.severity_text" ][
49+ "value"
50+ ],
51+ "severity_number" : int (
52+ log_json ["attributes" ]["sentry.severity_number" ]["value" ]
53+ ),
54+ "body" : log_json ["body" ],
55+ "attributes" : otel_attributes_to_dict (log_json ["attributes" ]),
56+ "time_unix_nano" : int (float (log_json ["timestamp" ]) * 1e9 ),
57+ "trace_id" : log_json ["trace_id" ],
58+ } # type: Log
59+ res .append (log )
5860 return res
5961
6062
@@ -347,7 +349,6 @@ def test_logging_errors(sentry_init, capture_envelopes):
347349 error_event_2 = envelopes [1 ].items [0 ].payload .json
348350 assert error_event_2 ["level" ] == "error"
349351
350- print (envelopes )
351352 logs = envelopes_to_logs (envelopes )
352353 assert logs [0 ]["severity_text" ] == "error"
353354 assert "sentry.message.template" not in logs [0 ]["attributes" ]
@@ -365,6 +366,36 @@ def test_logging_errors(sentry_init, capture_envelopes):
365366 assert len (logs ) == 2
366367
367368
369+ def test_log_strips_project_root (sentry_init , capture_envelopes ):
370+ """
371+ The python logger should strip project roots from the log record path
372+ """
373+ sentry_init (
374+ _experiments = {"enable_logs" : True },
375+ project_root = "/custom/test" ,
376+ )
377+ envelopes = capture_envelopes ()
378+
379+ python_logger = logging .Logger ("test-logger" )
380+ python_logger .handle (
381+ logging .LogRecord (
382+ name = "test-logger" ,
383+ level = logging .WARN ,
384+ pathname = "/custom/test/blah/path.py" ,
385+ lineno = 123 ,
386+ msg = "This is a test log with a custom pathname" ,
387+ args = (),
388+ exc_info = None ,
389+ )
390+ )
391+ get_client ().flush ()
392+
393+ logs = envelopes_to_logs (envelopes )
394+ assert len (logs ) == 1
395+ attrs = logs [0 ]["attributes" ]
396+ assert attrs ["code.file.path" ] == "blah/path.py"
397+
398+
368399def test_auto_flush_logs_after_100 (sentry_init , capture_envelopes ):
369400 """
370401 If you log >100 logs, it should automatically trigger a flush.
0 commit comments