## 8.1 Using LoggerAdapters to impart contextual information 

An easy way in which you can pass contextual information to be output along with logging event information is to use the$_{LoggerAdapter}$ class. This class is designed to look like a$_{Logger}$ , so that you can call$_{debug()}$ , info() ,$_{warning()}$ ,$_{error()}$ ,$_{exception()}$ ,$_{critical()}$ and$_{log()}$ . These methods have the same signatures as their counterparts in Logger , so you can use the two types of instances interchangeably. 

When you create an instance of LoggerAdapter , you pass it a Logger instance and a dict-like object which con- tains your contextual information. When you call one of the logging methods on an instance of LoggerAdapter , it delegates the call to the underlying instance of Logger passed to its constructor, and arranges to pass the contextual information in the delegated call. Here’s a snippet from the code of$_{LoggerAdapter}$: 

def debug(self, msg,/,*args,**kwargs): """ Delegate a debug call to the underlying logger, after adding contextual information from this adapter instance. """ msg, kwargs=self.process(msg, kwargs) self.logger.debug(msg, *args,**kwargs) 

The process() method of LoggerAdapter is where the contextual information is added to the logging output. It’s passed the message and keyword arguments of the logging call, and it passes back (potentially) modified versions of these to use in the call to the underlying logger. The default implementation of this method leaves the message alone, but inserts an ‘extra’ key in the keyword argument whose value is the dict-like object passed to the constructor. Of course, if you had passed an ‘extra’ keyword argument in the call to the adapter, it will be silently overwritten. 

The advantage of using ‘extra’ is that the values in the dict-like object are merged into the$_{LogRecord}$ instance’s __dict__, allowing you to use customized strings with your$_{Formatter}$ instances which know about the keys of the dict-like object. If you need a different method, e.g. if you want to prepend or append the contextual information to the message string, you just need to subclass$_{LoggerAdapter}$ and override$_{process()}$ to do what you need. Here is a simple example: 

classCustomAdapter (logging .LoggerAdapter): """ This example adapter expects the passed in dict-like object to have a 'connid' key, whose value in brackets is prepended to the log message. """ def process(self, msg, kwargs): return '[ %s ] %s '%(self.extra['connid'], msg), kwargs 

which you can use like this: 

logger=logging.getLogger(__name__ ) adapter =CustomAdapter(logger, { 'connid': some_conn_id}) 

Then any events that you log to the adapter will have the value of$_{some_conn_id}$ prepended to the log messages. 

## Using objects other than dicts to pass contextual information 

You don’t need to pass an actual dict to a$_{LoggerAdapter}$ - you could pass an instance of a class which implements __getitem__ and$_{__iter__}$ so that it looks like a dict to logging. This would be useful if you want to generate values dynamically (whereas the values in a dict would be constant). 

