@@ -30,7 +30,7 @@ def _convert_attr(attr):
3030 return attr ["value" ]
3131 if attr ["value" ].startswith ("{" ):
3232 try :
33- return json .loads (attr ["stringValue " ])
33+ return json .loads (attr ["value " ])
3434 except ValueError :
3535 pass
3636 return str (attr ["value" ])
@@ -393,6 +393,78 @@ def test_log_strips_project_root(sentry_init, capture_envelopes):
393393 assert attrs ["code.file.path" ] == "blah/path.py"
394394
395395
396+ def test_logger_with_all_attributes (sentry_init , capture_envelopes ):
397+ """
398+ The python logger should be able to log all attributes, including extra data.
399+ """
400+ sentry_init (_experiments = {"enable_logs" : True })
401+ envelopes = capture_envelopes ()
402+
403+ python_logger = logging .Logger ("test-logger" )
404+ python_logger .warning (
405+ "log #%d" ,
406+ 1 ,
407+ extra = {"foo" : "bar" , "numeric" : 42 , "more_complex" : {"nested" : "data" }},
408+ )
409+ get_client ().flush ()
410+
411+ logs = envelopes_to_logs (envelopes )
412+
413+ attributes = logs [0 ]["attributes" ]
414+
415+ assert "process.pid" in attributes
416+ assert isinstance (attributes ["process.pid" ], int )
417+ del attributes ["process.pid" ]
418+
419+ assert "sentry.release" in attributes
420+ assert isinstance (attributes ["sentry.release" ], str )
421+ del attributes ["sentry.release" ]
422+
423+ assert "server.address" in attributes
424+ assert isinstance (attributes ["server.address" ], str )
425+ del attributes ["server.address" ]
426+
427+ assert "thread.id" in attributes
428+ assert isinstance (attributes ["thread.id" ], int )
429+ del attributes ["thread.id" ]
430+
431+ assert "code.file.path" in attributes
432+ assert isinstance (attributes ["code.file.path" ], str )
433+ del attributes ["code.file.path" ]
434+
435+ assert "code.function.name" in attributes
436+ assert isinstance (attributes ["code.function.name" ], str )
437+ del attributes ["code.function.name" ]
438+
439+ assert "code.line.number" in attributes
440+ assert isinstance (attributes ["code.line.number" ], int )
441+ del attributes ["code.line.number" ]
442+
443+ assert "process.executable.name" in attributes
444+ assert isinstance (attributes ["process.executable.name" ], str )
445+ del attributes ["process.executable.name" ]
446+
447+ assert "thread.name" in attributes
448+ assert isinstance (attributes ["thread.name" ], str )
449+ del attributes ["thread.name" ]
450+
451+ # Assert on the remaining non-dynamic attributes.
452+ assert attributes == {
453+ "foo" : "bar" ,
454+ "numeric" : 42 ,
455+ "more_complex" : "{'nested': 'data'}" ,
456+ "logger.name" : "test-logger" ,
457+ "sentry.origin" : "auto.logger.log" ,
458+ "sentry.message.template" : "log #%d" ,
459+ "sentry.message.parameters.0" : 1 ,
460+ "sentry.environment" : "production" ,
461+ "sentry.sdk.name" : "sentry.python" ,
462+ "sentry.sdk.version" : VERSION ,
463+ "sentry.severity_number" : 13 ,
464+ "sentry.severity_text" : "warn" ,
465+ }
466+
467+
396468def test_auto_flush_logs_after_100 (sentry_init , capture_envelopes ):
397469 """
398470 If you log >100 logs, it should automatically trigger a flush.
0 commit comments