我可以在控制台错误中访问请求对象吗?



我对Django不是很熟悉,但必须对它如何记录项目进行一些更改。我想从请求对象中添加信息到日志。

import logging
MODULE_LOGGER = logging.getLogger(__name__)
class IndexPage():
def get(self, request, *args, **kwargs):

MODULE_LOGGER.warning("log me!")
# code...
return self.render_to_response(context)

这个会被这个类注销:

import json
from fluent import handler
class JsonFormatter(handler.FluentRecordFormatter):
def format(self, record):
data = super(JsonFormatter, self).format(record)
return json.dumps(data)

我们有以下记录器设置(我真的不明白)

LOGGING = {
"version": 1,
"disable_existing_loggers": True,
"root": {"level": "WARNING", "handlers": ["sentry", "json_console"]},
"formatters": {
"console": {"datefmt": syslog_date_fmt, "format": syslog_msg_format},
"json_fmt": {
"()": "out_project.logs.JsonFormatter",
"format": {
"level": "%(levelname)s",
"hostname": "%(hostname)s",
"name": "%(name)s",
"where": "%(module)s.%(funcName)s",
"stack_trace": "%(exc_text)s",
},
},
},
"filters": {
"require_debug_false": {"()": "django.utils.log.RequireDebugFalse"},
"file_logging": {"": ""},
},
"handlers": {
"null": {
"level": "DEBUG",
"class": "logging.NullHandler",
},
"console": {
"level": "DEBUG",
"class": "logging.StreamHandler",
"formatter": "console",
},
"sentry": {
"level": "WARNING",
"class": "raven.contrib.django.raven_compat.handlers.SentryHandler",
},
"json_console": {
"level": "INFO",
"class": "logging.StreamHandler",
"formatter": "json_fmt",
},
},
"loggers": {
"raven": {
"level": "INFO",
"handlers": ["json_console"],
"propagate": False,
},
"sentry.errors": {
"level": "INFO",
"handlers": ["json_console"],
"propagate": False,
},
"out_project": {
"level": "INFO",
"propagate": True,
},
},
}

Django文档讨论了django.request记录器,然而这似乎是在请求有问题的时候(比如4XX, 5XX错误)。我已经尝试添加这个记录器与它的处理程序是json_console处理程序,但是request对象没有出现在record对象上。

理想情况下,我希望将数据从请求对象添加到记录中,或者将其自动放在那里。我假设一旦它在那里,我就可以通过更新json_fmt.format属性来改变日志的外观。

据我所知,我可以向各个日志添加额外的信息,但是我想要从请求中获得的数据需要添加到通过logging.getLogger(__name__)的日志记录器完成的每个日志中。

我对Django中的日志工作方式非常陌生,所以如果我解释或理解错误的话,我很抱歉。

我最终使用了pip包django-middleware-global-request。我可以在任何地方导入它,并使用请求对象的方法get_request

from django_middleware_global_request.middleware import get_request

class JsonFormatter(handler.FluentRecordFormatter):
def format(self, record):
def add_request_data(data):
request = get_request()
if request:
# do stuff with request and data
return data

如果您想使用breakpoint()调试错误,这样您将获得一个交互式控制台,您可以在其中键入变量并查看其值。

如果您想记录请求对象,请像这样修改您的JsonFormatter

class JsonFormatter(handler.FluentRecordFormatter):
def format(self, record):
if type(record) in [str]:
data = super(JsonFormatter, self).format(record)
else:
# request object | manually serialize it
request_data = f"{request.status} | {request.user.username} | {request.data} | ... other request data"
data = super(JsonFormatter, self).format(request_data)
return json.dumps(data)

现在在您的views.py forIndexPage:

class IndexPage():
def get(self, request, *args, **kwargs):

MODULE_LOGGER.warning(request)
# code...
return self.render_to_response(context)

如果你想了解更多关于logger的信息,你需要查看Python文档,它与Django无关。Django使用JSON来配置Python日志记录器。见https://docs.python.org/3/howto/logging.html

要在每个日志中都有请求,您可以采用显式的方式,即替换所有

MODULE_LOGGER.warning("log me!")

MODULE_LOGGER.warning("log me!", extra={"request": request})

然后在你的格式化器中你会有请求对象

class JsonFormatter(handler.FluentRecordFormatter):
def format(self, record):
print(record.request) # Probably you want to do something more useful here.
data = super(JsonFormatter, self).format(record)
return json.dumps(data)

如果这不适合你,你想自动地隐式地将请求传递给日志记录器,然后需要做一些更复杂的事情,比如中间件。大多数情况下,Django是使用基于线程/进程的服务器部署的,所以当前线程每次处理一个请求。因此,我们可以将当前请求对象存储在线程本地存储器中(使用中间件),并在我们的记录器中提取它。

在文件"my_pretty_middleware.py"中添加这个

import threading
_local = threading.local()
_local.current_request = None

class StoreRequestMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
try:
_local.current_request = request
return self.get_response(request)
finally:
_local.current_request = None

def get_current_request():
return _local.current_request

然后将此中间件添加到中间件的顶部。像

MIDDLEWARE = [
"my_pretty_middleware.StoreRequestMiddleware"
"django.middleware.security.SecurityMiddleware",
"django.middleware.common.CommonMiddleware",
...
]

然后在你的格式化器(或代码的任何部分)中,你可以获得请求对象。

from my_pretty_middleware import get_current_request

class JsonFormatter(handler.FluentRecordFormatter):
def format(self, record):
request = get_current_request()
if request:  # Beware it can be None in case you're logging outside of request cycle.
print(request)  # Probably you'd like to do something else
data = super(JsonFormatter, self).format(record)
return json.dumps(data)

检查并安装requestLogging.

它帮助你用请求对象修改和格式化日志。

最新更新