Skip to content

Instantly share code, notes, and snippets.

@j-griffith
Created January 2, 2015 23:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save j-griffith/2885dfae87b0040de8d6 to your computer and use it in GitHub Desktop.
Save j-griffith/2885dfae87b0040de8d6 to your computer and use it in GitHub Desktop.
class KeywordArgumentAdapter(BaseLoggerAdapter):
"""Logger adapter to add keyword arguments to log record's extra data
"""
def process(self, msg, kwargs):
# Make a new extra dictionary combining the values we were
# given when we were constructed and anything from kwargs.
extra = {}
extra.update(self.extra)
if 'extra' in kwargs:
extra.update(kwargs.pop('extra'))
# Move any unknown keyword arguments into the extra
# dictionary.
for name in list(kwargs.keys()):
if name == 'exc_info':
continue
extra[name] = kwargs.pop(name)
# NOTE(dhellmann): The gap between when the adapter is called
# and when the formatter needs to know what the extra values
# are is large enough that we can't get back to the original
# extra dictionary easily. We leave a hint to ourselves here
# in the form of a list of keys, which will eventually be
# attributes of the LogRecord processed by the formatter. That
# allows the formatter to know which values were original and
# which were extra, so it can treat them differently (see
# JSONFormatter for an example of this). We sort the keys so
# it is possible to write sane unit tests.
extra['extra_keys'] = list(sorted(extra.keys()))
# Place the updated extra values back into the keyword
# arguments.
kwargs['extra'] = extra
# NOTE(jdg): We would like an easy way to add resource info
# to logging, for example a header like 'volume-<uuid>'
# Turns out Nova implemented this but it's Nova specific with
# instance. Also there's resource_uuid that's been added to
# context, but again that only works for Instances, and it
# only works for contexts that have the resource id set.
resource = kwargs.pop('resource', None)
if resource:
# Many OpenStack resources have a name entry in their db ref
# of the form <resource_type>-<uuid>, let's just use that if
# it's passed in
if not resource.get('name', None):
# For resources that don't have the name of the format we wish
# to use (or places where the LOG call may not have the full
# object ref, allow them to pass in a dict:
# resource={resource_type: volume, resource_id: uuid}
resource_type = resource.get('type', None)
resource_id = resource.get('id', None)
if resource_type and resource_id:
extra.setdefault('resource', ('[' + resource_type + '-' + resource_id + '] '))
else:
# FIXME(jdg): Since the name format can be specified via conf
# entry, we may want to consider allowing this to be configured
# here as well
extra.setdefault('resource', ('[' + resource.get('name', '') + '] '))
return msg, kwargs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment