Django provides a working default logging configuration that is readily extended.
要从代码中发送日志消息,你需要在代码中添加日志调用。
Don't be tempted to use logging calls in settings.py
.
The way that Django logging is configured as part of the setup()
function means that logging calls placed in settings.py
may not work as
expected, because logging will not be set up at that point. To explore
logging, use a view function as suggested in the example below.
First, import the Python logging library, and then obtain a logger instance
with logging.getLogger()
. Provide the getLogger()
method with a
name to identify it and the records it emits. A good option is to use
__name__
(see 使用命名空间日志记录器 below for more on this) which will
provide the name of the current Python module as a dotted path:
import logging
logger = logging.getLogger(__name__)
在模块级别执行此声明是一个好的约定。
然后在函数中,例如在视图中,向日志记录器发送一条记录:
def some_view(request):
...
if some_risky_state:
logger.warning("Platform is running at risk")
When this code is executed, a LogRecord
containing that
message will be sent to the logger. If you're using Django's default logging
configuration, the message will appear in the console.
The WARNING
level used in the example above is one of several
logging severity levels: DEBUG
,
INFO
, WARNING
, ERROR
, CRITICAL
. So, another example might be:
logger.critical("Payment system is not responding")
重要
Records with a level lower than WARNING
will not appear in the console
by default. Changing this behavior requires additional configuration.
虽然 Django 的日志配置可以直接使用,但您可以通过一些额外的配置来精确控制日志发送到各种目标的方式,如日志文件、外部服务、电子邮件等。
你可以配置:
LogRecord
objects to a string or
other form for consumption by human beings or another systemThere are various ways of configuring logging. In Django, the
LOGGING
setting is most commonly used. The setting uses the
dictConfig format, and extends the
default logging configuration.
See 日志模块的配置 for an explanation of how your custom settings are merged with Django's defaults.
See the Python logging documentation
for
details of other ways of configuring logging. For the sake of simplicity, this
documentation will only consider configuration via the LOGGING
setting.
在配置日志时,以下操作是有意义的
LOGGING
目录¶在你的 settings.py
:: 中
LOGGING = {
"version": 1, # the dictConfig format version
"disable_existing_loggers": False, # retain the default loggers
}
It nearly always makes sense to retain and extend the default logging
configuration by setting disable_existing_loggers
to False
.
This example configures a single handler named file
, that uses Python's
FileHandler
to save logs of level DEBUG
and higher to the
file general.log
(at the project root):
LOGGING = {
# ...
"handlers": {
"file": {
"class": "logging.FileHandler",
"filename": "general.log",
},
},
}
Different handler classes take different configuration options. For more
information on available handler classes, see the
AdminEmailHandler
provided by Django and the various
handler classes
provided by Python.
日志级别也可以在处理程序上进行设置(默认情况下,它们接受所有级别的日志消息)。使用上面的示例,添加以下内容:
{
"class": "logging.FileHandler",
"filename": "general.log",
"level": "DEBUG",
}
would define a handler configuration that only accepts records of level
DEBUG
and higher.
要将记录发送到该处理程序,请配置一个日志记录器映射,例如:
LOGGING = {
# ...
"loggers": {
"": {
"level": "DEBUG",
"handlers": ["file"],
},
},
}
The mapping's name determines which log records it will process. This
configuration (''
) is unnamed. That means that it will process records
from all loggers (see 使用命名空间日志记录器 below on how to use the mapping
name to determine the loggers for which it will process records).
It will forward messages of levels DEBUG
and higher to the handler named
file
.
请注意,一个日志记录器可以将消息转发给多个处理程序,因此日志记录器和处理程序之间的关系是多对多的。
如果您执行以下操作:
logger.debug("Attempting to connect to API")
in your code, you will find that message in the file general.log
in the
root of the project.
By default, the final log output contains the message part of each log
record
. Use a formatter if you want to include additional
data. First name and define your formatters - this example defines
formatters named verbose
and simple
:
LOGGING = {
# ...
"formatters": {
"verbose": {
"format": "{name} {levelname} {asctime} {module} {process:d} {thread:d} {message}",
"style": "{",
},
"simple": {
"format": "{levelname} {message}",
"style": "{",
},
},
}
The style
keyword allows you to specify {
for str.format()
or
$
for string.Template
formatting; the default is $
.
See LogRecord attributes for the LogRecord
attributes
you can include.
To apply a formatter to a handler, add a formatter
entry to the handler's
dictionary referring to the formatter by name, for example:
"handlers": {
"file": {
"class": "logging.FileHandler",
"filename": "general.log",
"formatter": "verbose",
},
}
The unnamed logging configuration ''
captures logs from any Python
application. A named logging configuration will capture logs only from loggers
with matching names.
The namespace of a logger instance is defined using
getLogger()
. For example in views.py
of my_app
:
logger = logging.getLogger(__name__)
will create a logger in the my_app.views
namespace. __name__
allows you
to organize log messages according to their provenance within your project's
applications automatically. It also ensures that you will not experience name
collisions.
A logger mapping named my_app.views
will capture records from this logger:
LOGGING = {
# ...
"loggers": {
"my_app.views": {...},
},
}
A logger mapping named my_app
will be more permissive, capturing records
from loggers anywhere within the my_app
namespace (including
my_app.views
, my_app.utils
, and so on):
LOGGING = {
# ...
"loggers": {
"my_app": {...},
},
}
您还可以明确定义日志记录器的命名空间:
logger = logging.getLogger("project.payment")
并相应地设置日志记录器映射。
Logger naming is hierarchical. my_app
is the parent of my_app.views
,
which is the parent of my_app.views.private
. Unless specified otherwise,
logger mappings will propagate the records they process to their parents - a
record from a logger in the my_app.views.private
namespace will be handled
by a mapping for both my_app
and my_app.views
.
为了管理这种行为,请在您定义的映射中设置传播键:
LOGGING = {
# ...
"loggers": {
"my_app": {
# ...
},
"my_app.views": {
# ...
},
"my_app.views.private": {
# ...
"propagate": False,
},
},
}
propagate
defaults to True
. In this example, the logs from
my_app.views.private
will not be handled by the parent, but logs from
my_app.views
will.
当日志包含尽可能多的信息,而不是您不需要的信息时,日志是最有用的——需要多少取决于您正在做的事情。在调试时,您需要一定程度的信息,如果您不得不在生产环境中处理这些信息,那么这些信息将是多余的,而且毫无用处。
您可以配置日志记录,以在需要时为您提供所需的详细程度。与手动更改配置以实现此目的不同,更好的方式是根据环境自动应用配置。
For example, you could set an environment variable DJANGO_LOG_LEVEL
appropriately in your development and staging environments, and make use of it
in a logger mapping thus:
"level": os.getenv("DJANGO_LOG_LEVEL", "WARNING")
- so that unless the environment specifies a lower log level, this
configuration will only forward records of severity WARNING
and above to
its handler.
Other options in the configuration (such as the level
or formatter
option of handlers) can be similarly managed.
9月 22, 2023