格式为Django的日志记录错误:KeyError:“类名”

时间:2020-02-28 09:18:05

标签: python django python-3.x logging django-rest-framework

无法使用settings.py中定义的给定日志格式设置额外的上下文,并且如果我们从格式中删除%(classname)s()] %(token)s %(router_macid)s %(user_email)s %(device_macid)s,那么我正在使用API​​进行响应,甚至在日志文件中生成日志,也可以正常工作没有错误,我正在使用django == 2.1,djangorestframework == 3.10.3

错误

--- Logging error ---
Traceback (most recent call last):
  File "/usr/lib/python3.6/logging/__init__.py", line 994, in emit
    msg = self.format(record)
  File "/usr/lib/python3.6/logging/__init__.py", line 840, in format
    return fmt.format(record)
  File "/usr/lib/python3.6/logging/__init__.py", line 580, in format
    s = self.formatMessage(record)
  File "/usr/lib/python3.6/logging/__init__.py", line 549, in formatMessage
    return self._style.format(record)
  File "/usr/lib/python3.6/logging/__init__.py", line 391, in format
    return self._fmt % record.__dict__
KeyError: 'classname'
Call stack:
  File "/usr/lib/python3.6/threading.py", line 884, in _bootstrap
    self._bootstrap_inner()
  File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python3.6/socketserver.py", line 654, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python3.6/socketserver.py", line 364, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python3.6/socketserver.py", line 724, in __init__
    self.handle()
  File "/usr/lib/python3.6/site-packages/django/core/servers/basehttp.py", line 154, in handle
    handler.run(self.server.get_app())
  File "/usr/lib/python3.6/wsgiref/handlers.py", line 138, in run
    self.finish_response()
  File "/usr/lib/python3.6/wsgiref/handlers.py", line 183, in finish_response
    self.close()
  File "/usr/lib/python3.6/wsgiref/simple_server.py", line 35, in close
    self.status.split(' ',1)[0], self.bytes_sent
  File "/usr/lib/python3.6/http/server.py", line 536, in log_request
    self.requestline, str(code), str(size))
  File "/usr/lib/python3.6/site-packages/django/core/servers/basehttp.py", line 124, in log_message
    level(format, *args, extra=extra)
Message: '"%s" %s %s'

settings.py

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'formatter': {
            'format' : '[%(asctime)s] %(levelname)s [%(pathname)s:%(lineno)s:%(classname)s()] %(token)s %(router_macid)s  %(user_email)s  %(device_macid)s %(message)s',
            'datefmt' : "%d/%b/%Y %H:%M:%S"
        },
        'simple': {
            'format': '%(levelname)s %(message)s'

        },
    },
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': 'my_django.log',
            'formatter': 'formatter'
        },
    },
    'loggers': {
        'django': {
            'handlers':['file'],
            'propagate': True,
            'level':'DEBUG',
        },
        'backend': {
            'handlers': ['file'],
            'level': 'DEBUG',
            'propagate': True,
        },
    }
}

views.py

import logging
from rest_framework import views
from rest_framework.response import Response


logging.basicConfig(level=logging.INFO)
log = logging.getLogger('backend')

log_dict = {
    'classname': 'NA', 
    'router_macid':'NA',
    'token':'NA',
    'device_macid':'NA',
    'user_email':'NA'
}

class MyView(views.APIView):
    def post(self, request):
        extra_dict =  log_dict.copy()
        extra_dict['classname'] = self.__class__.__name__

        response=codes['200'].copy()
        response['message']= “Success”        
        log.info(" ".join(["Request received with =",str(request.data),"response=",str(response)]), extra= extra_dict)
        return Response(response)

1 个答案:

答案 0 :(得分:2)

您当前的日志记录配置将覆盖其他库的日志记录配置。因此,出现错误的原因(请参阅错误回溯)。

我建议仅对django项目覆盖日志记录配置。

创建一个单独的格式化程序条目,并保留默认状态下的“格式化程序”条目。您还可以重命名“格式化程序”条目以使其特定于您的项目

'formatters': {
    'backend': {
        'format' : '[%(asctime)s] %(levelname)s [%(pathname)s:%(lineno)s:%(classname)s()] %(token)s %(router_macid)s  %(user_email)s  %(device_macid)s %(message)s',
        'datefmt' : "%d/%b/%Y %H:%M:%S"
    },
},

然后输入一个条目,以仅为使用上述已配置格式器的项目配置处理程序。不要覆盖Django的记录器。外部库应配置自己的日志记录。

'handlers': {
    'backend': {
        'level': 'DEBUG',
        'class': 'logging.FileHandler',
        'filename': 'my_django.log',
        'formatter': 'backend'
    },
},

最后为使用处理程序的项目配置记录器。

'loggers': {
    'backend': {
        'handlers': ['backend'],
        'level': 'DEBUG',
        'propagate': False,
    },
}

请记住将propagate设置为False,以防止事件传递给祖先记录器。

获取已配置的记录器,并像以前一样在项目中使用它。

 log = logging.getLogger('backend')