107 lines
3.2 KiB
Python
Raw Normal View History

"""
logger decorator to enable logging of infos from django's HttpRequest object.
Usage:
Code:
@log.logger(__name__)
def home(request, logger=None):
logger.info('user performed some action')
Class based views work the same way, just decorate/modify the view's METHOD(s).
Logging formatter configuration:
'format': '[%(asctime)s] %(levelname)s %(message)s ' \
'[ip: %(request.META.REMOTE_ADDR)s, ua: "%(request.META.HTTP_USER_AGENT)s"]'
Based on code from (but heavily modified/refactored):
https://derrickpetzold.com/p/django-requst-logging-json/
which is (c) Derrick Petzold - with a Creative Commons BY-SA license.
"""
import logging
from django.http.request import HttpRequest
def _get_attrdict(obj, basename, excluded=None):
"""
get a dictionary of (basename-prefixed) attribute names/values,
excluding the excluded names, internal stuff and callables.
:param obj: the object to inspect
:param basename: the prefix for the names in the result dictionary
:param excluded: excluded attribute names, do not even touch [set or list]
:return: dict names: values
"""
if excluded is None:
excluded = set()
d = {}
names = set(dir(obj)) - set(excluded)
for name in names:
if not name.startswith('_'):
try:
attr = getattr(obj, name)
if not callable(attr):
d[basename + name] = attr
except AttributeError:
pass
return d
def _get_elementdict(dct, basename, excluded=None):
"""
get a dictionary of (basename-prefixed) dictionary elements,
excluding the excluded names.
:param dct: the dict to inspect
:param basename: the prefix for the names in the result dictionary
:param excluded: excluded dictionary keys [set or list]
:return: dict names: values
"""
if excluded is None:
excluded = set()
names = set(dct) - set(excluded)
return {basename + name: dct[name] for name in names}
def _build_request_info(request):
"""
build a dictionary with extra information extracted from request object
:param request: django HttpRequest object
:return: dict names: values
"""
d = _get_elementdict(request.META, "request.META.")
d.update(_get_attrdict(request, "request.", ['raw_post_data', ]))
d.update(_get_attrdict(request.session, "request.session."))
d.update(_get_attrdict(request.user, "request.user."))
return d
def logger(name):
"""
decorator to provide extra information from request to logging
:param name: name of the logger
:return: decorated function/method
"""
def wrap(func):
def caller(*args, **kwargs):
request = None
for arg in args:
if isinstance(arg, HttpRequest):
request = arg
break
if 'logger' not in kwargs:
l = logging.getLogger(name)
if request is None:
kwargs['logger'] = l
else:
kwargs['logger'] = logging.LoggerAdapter(l, _build_request_info(request))
return func(*args, **kwargs)
return caller
return wrap