@@ -50,6 +50,13 @@ class LogLevel:
5050
5151class LogFormatter (logging .Formatter ):
5252 'Custom log formatter that formats log messages as JSON, aka "Structured Logging".'
53+ def __init__ (self , * args , defaults : dict = field (default_factory = dict ), ** kwargs ):
54+ '''
55+ Initializes the log formatter with optional default context.
56+ - `defaults` is a dictionary of default context values to include in every log message.
57+ '''
58+ self .defaults = defaults
59+ super ().__init__ (* args , ** kwargs )
5360
5461 def format (self , record ) -> str :
5562 'Formats the log message as JSON.'
@@ -67,15 +74,21 @@ def format(self, record) -> str:
6774 {
6875 'timestamp' : datetime .now ().isoformat (),
6976 'msg' : record .msg ,
70- 'data' : {'args' : args } if args else {} | kwargs or {}
77+ 'data' : {'args' : args } if args else {} | kwargs or {},
78+ 'context' : self .defaults or {},
7179 },
7280 default = _json_default ,
7381 )
7482 record .args = ()
7583 return super ().format (record )
7684
7785
78- def _getLogger (name : str , level : int = logging .CRITICAL , handlers : list [logging .Handler ] = []) -> logging .Logger :
86+ def _getLogger (
87+ name : str ,
88+ level : int = logging .CRITICAL ,
89+ handlers : list [logging .Handler ] = [],
90+ context : dict = field (default_factory = dict ),
91+ ) -> logging .Logger :
7992 '''
8093 Creates a logger with the given name, level, and handlers.
8194 - If no handlers are provided, the logger will not output any logs.
@@ -109,7 +122,7 @@ def _getLogger(name: str, level: int = logging.CRITICAL, handlers: list[logging.
109122
110123 if logger .handlers :
111124 # only set the first handler to use the custom formatter
112- logger .handlers [0 ].setFormatter (LogFormatter ())
125+ logger .handlers [0 ].setFormatter (LogFormatter (defaults = context ))
113126
114127 return logger
115128
@@ -119,6 +132,7 @@ def getLogger(
119132 level : int = logging .INFO ,
120133 stream : io .TextIOBase = sys .stderr ,
121134 files : dict [LogLevel , str ] = dict (),
135+ context : dict = field (default_factory = dict ),
122136) -> logging .Logger :
123137 '''
124138 Creates a logger with the given name, level, and handlers.
@@ -143,4 +157,4 @@ def getLogger(
143157 handler .setLevel (flevel )
144158 handlers .append (handler )
145159
146- return _getLogger (name , level , handlers )
160+ return _getLogger (name , level , handlers , context = context )
0 commit comments