概述
-
django
框架的日志通过python
内置的logging
模块实现的,日记可以记录自定义的一些信息描述,也可以记录系统运行中的一些对象数据,还可以记录包括堆栈跟踪、错误代码之类的详细信息 -
logging
主要由4部分组成:Loggers
、Handlers
、Filters
和Formatters
settings中完整的配置
LOGGING = {
# 固定值
'version':1,
# 格式器
'formatters': {},
# 过滤器
'filters':{},
# 处理器
'handlers':{},
# 记录器
'loggers':{},
# 根记录器,配置等同普通记录器,但是没有propagate配置项
'root':{},
# 默认为False。True:是将配置解释为现有配置的增量。False:配置会覆盖已有默认配置
'incremental':True,
# 默认为True。禁用任何现有的非root记录器。如果设置了incremental=True,则此配置无效
'disable_existing_loggers': False
}
Loggers
这个类是logging
系统的入口
python
定义了日志的5个级别,分别对应python程序中日志信息的不同严重性:
DEBUG
:用于调试的最低级的系统信息INFO
:一般性的系统信息WARNING
:一些警告性的信息,发生了一些小问题,这些问题不影响系统的正常运行,但是也不建议出现ERROR
:系统出现错误了,该错误会影响系统的正常运行,记录错误相关的信息CRITICAL
:非常严重的问题,譬如可能引起系统崩溃的问题等
当logger
记录的日志消息与logger配置的日志级别比较,达到或超过级别,才会将日志消息传递给handler
进一步处理,否则消息会被忽略。
一般开发环境时,会启用DEBUG
级别,而在生产环境中,启用WARNING
或ERROR
级别
1.settings中配置
通过在settings
中配置LOGGING
配置项实现日志配置,共4个配置项(都是可选的,不过一般会指定handler
):
level
:指定记录日志的级别,没有配置则处理所有级别的日志propagate
:设置该记录器的日志是否传播到父记录器,不设置则是True
filters
:指定过滤器列表handlers
:指定处理器列表
LOGGING = {
# 固定值,现在只有这一个版本
'version': 1,
# 设置已存在的logger不失效
'disable_existing_loggers': False,
'loggers': {
# '':默认的记录器
'': {
# console输出日志到控制台
# mail_admins输出日志到邮件
'handlers': ['console'],
},
'django': {
'handlers': ['console'],
'propagate': True,
},
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
'myproject.custom': {
'handlers': ['console', 'mail_admins'],
'level': 'INFO',
'filters': ['special']
}
}
}
2.常用方法
-
Logger.debug(msg)、Logger.info(msg)、Logger.warning(msg)、Logger.error(msg)、Logger.critical(msg)
,分别对应5个不同的日志级别 -
Logger.log(level, msg)
记录日志,手动指定level
,level
的选择是CRITICAL = 50,ERROR = 40,WARNING = 30,INFO = 20,DEBUG = 10
,需要填写数字,譬如50
或logging.DEBUG
-
Logger.exception()
:等同于Logger.error(msg, exc_info=True)
,输出异常的堆栈信息
3.django内置logger
-
django
:django
框架中所有消息的记录器,一般使用它的子记录器,而不是它发布消息,因为默认情况下子记录器的日志会传播到根记录器django
,除非设置'propagate': False
-
django.request
:记录与请求处理相关的消息。5XX
响应作为ERROR
消息;4XX
响应作为WARNING
消息引发。记录到django.security
记录器的请求不会记录到django.request
中发送给此记录器的消息具有以下额外上下文:
status_code
:与请求关联的HTTP
响应代码
request
:生成日志消息的请求对象。 -
django.server
:记录与runserver
命令调用的服务器接收的请求的处理相关的消息。5XX
响应记录为ERROR
消息,4XX
响应记录为WARNING
消息,其他所有响应记录为INFO
。发送给此记录器的消息具有以下额外上下文:
status_code
:与请求关联的HTTP
响应代码。
request
:生成日志消息的请求对象。 -
django.template
:记录与模板呈现相关的消息 -
django.db.backends
:记录代码和数据库交互相关的消息 -
django.security.*
:记录任何SuspiciousOperation
和其他安全相关错误(django.security.csrf
)的消息 -
django.db.backends.schema
:记录数据库迁移过程中的日志,但是不记录执行的查询SQL语句等
Handlers
-
这个类是确定
logger
中消息发生的引擎程序,描述特定的日志记录行为,譬如控制台打印、写入日志文件、通过网络进行发送等 -
一个
logger
可以有多个handler
,每个handler
可以有不同的日志级别和记录方法
1.settings中配置
4个参数,加上对应class
类的初始化参数
class
(必需):处理程序类的名称level
(可选的):处理程序的级别formatter
(可选的):处理程序的格式化程序filters
(可选的):处理程序的过滤器的列表
LOGGING = {
'handlers': {
'console': {
'level': 'INFO',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
'formatter': 'simple',
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
'filters': ['special']
}
},
}
2.内置处理器
(1)python3的logging中的handler:
-
StreamHandler
:输出到stream
,未指定则使用sys.stderr
输出到控制台 -
FileHandler
:继承自StreamHandler
,输出到文件,默认情况下,文件无限增长 -
RotatingFileHandler
:自动按大小切分的log
文件 -
TimedRotatingFileHandler
:按时间自动切分的log
文件,文件后缀%Y-%m-%d_%H-%M-%S
-
SMTPHandler
:通过email
发送日志记录消息
(2)django内置的handler:
AdminEmailHandler
:会将收到的每一条日志消息发送一个邮件到ADMINS指定的邮箱地址
Filters
-
过滤器
filter
用于提供对日志记录从logger
传递到handler
的附加控制 -
默认情况下,
logger
和handler
将处理满足日志级别要求的任何日志消息,但是,通过安装filter
,可以在日志记录过程中添加其他条件。例如,可以安装仅允许ERROR
级别 来自特定源的消息的filter
。 -
filter
还可用于在发出之前修改日志记录。例如,如果满足一组特定条件,可以编写一个过滤器,将ERROR
日志记录降级为WARNING
记录。 -
filter
可以安装在logger
或handler
上; 可以在链中使用多个filter
来执行多个过滤操作。
1.settings中配置
LOGGING = {
'filters': {
'special': {
'()': 'project.logging.SpecialFilter',
'foo': 'bar',
},
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
}
2.内置过滤器
(1). python内置的过滤器:
- 日志过滤器的父类:
Filter
,一般不直接使用
(2). django内置的过滤器:
-
CallbackFilter
:为每个记录调用callback
,如果callback
返回True
,则允许日志通过,如果callback
返回False
,则不允许该日志通过 -
RequireDebugFalse
:仅在settings.DEBUG
为False
时传递记录 -
RequireDebugTrue
:仅在settings
.DEBUG
为True
时传递记录
Formatters
- 日志记录最终需要呈现为文本,
formatter
程序描述该文本的确切格式。 formatter
通常由包含LogRecord
属性的Python
格式化字符串组成- 但是,也可以编写自定义
formatter
来实现特定的格式化行为。
1.settings中配置:
()
:指定格式器的类,不指定的话,默认使用logging.Formatter
format
:格式化字符串style
:样式选择datefmt
:日期格式化字符串,使用的是python
中时间日期格式化符号
LOGGING = {
'formatters': {
'verbose': {
'()': 'logging.Formatter',
'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
'style': '{',
},
'simple': {
'format': '{levelname} {message}',
'style': '{',
},
}
}
2.内置格式器
(1) python内置的格式器
Formatter
:默认格式器
初始化参数:fmt=None, datefmt=None, style='%'
fmt
:格式化字符串,指定输出格式,如:'{levelname}{process:d}{message}'
datefmt
:日期格式化字符串,为None
则使用ISO8601
格式化,如:'2010-01-01 01:01:01,890'
style
:’%’,’{’ 或 ‘$’
%(name)s:记录器logger的名称
%(levelno)s:日志级别对应的数字
%(levelname)s:日志级别名称
%(pathname)s:日志记录调用的源文件的完整路径
%(filename)s:日志记录调用的源文件名
%(module)s:模块名
%(lineno)d:日志调用的行数
%(funcName)s:函数名
%(created)f:日志创建时间,time.time()
%(asctime)s:日志创建时间,文本类型
%(msecs)d:日志创建时间的毫秒部分
%(relativeCreated)d:日志创建时间 - 加载日志模块的时间 的 毫秒数
%(thread)d:线程ID
%(threadName)s:线程名
%(process)d:进程ID
%(processName)s:进程名
%(message)s:日志消息
BufferingFormatter
:一种适于格式化批量记录的格式器,对每条记录都使用指定的格式器进行格式化
(2). django内置的格式器
ServerFormatter
:根据status_code
不同,将日志消息格化式成不同的颜色的消息
logging.LogRecord对象
- 每次
logger
记录日志时,都会自动创建该LogRecord
实例
-
初始化参数
:- name - 用于记录此LogRecord表示的事件的记录器的名称
- level - 日志记录事件的数字级别(DEBUG是10,INFO是20,以此类推),并将转换为LogRecord的两个属性: 对于数值levelno和对应的级别名称levelname
- pathname - 进行日志记录调用的源文件的完整路径名
- lineno - 进行日志记录调用的源文件中的行号
- msg - 事件描述消息,可能是带有可变数据占位符的格式字符串
- args - 要合并到msg参数中以获取事件描述的可变数据
- exc_info - 包含当前异常信息的异常元组,或者None(没有可用的异常信息)
- func - 调用日志记录调用的函数或方法的名称
- sinfo - 表示当前线程中堆栈基础的堆栈信息的文本字符串,直到日志记录调用
-
方法
- getMessage:返回用户提供的参数与消息合并后的消息
项目中应用日志
1、默认配置
- 不进行额外的配置,直接在项目中使用
logger
,则会使用django.utils.log
的默认配置DEFAULT_LOGGING
DEFAULT_LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse',
},
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'formatters': {
'django.server': {
'()': 'django.utils.log.ServerFormatter',
'format': '[{server_time}] {message}',
'style': '{',
}
},
'handlers': {
'console': {
'level': 'INFO',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
},
'django.server': {
'level': 'INFO',
'class': 'logging.StreamHandler',
'formatter': 'django.server',
},
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
}
},
'loggers': {
'django': {
'handlers': ['console', 'mail_admins'],
'level': 'INFO',
},
'django.server': {
'handlers': ['django.server'],
'level': 'INFO',
'propagate': False,
},
}
}
-
如果设置
DEBUG=True
,那么会将除django.server
以外的INFO
及以上的日志输出到控制台 -
如果设置
DEBUG=False
,那么会将除django.server
以外的ERROR
和CRITICAL
级别的日志传递到AdminEmailHandler
-
与
DEBUG
设置无关,所有的django.server
记录器的日志,INFO
及以上级别的都会输出到控制台 -
django.server
记录器外其他内置记录器都会传播消息到根记录器django
,而根记录器django
使用了console
和mail_admins
处理器。
views
模块测试:
import logging
# 这个 logger 只会在控制台输出 warning及以上的日志
# __name__ 模块logger,对应settings中的 名称为:'' 的 logger
logger = logging.getLogger(__name__)
# 这个logger 会输出 info及以上的日志
logger_server = logging.getLogger('django.server')
def index(request):
logger.debug('debug 测试')
logger.info('info 测试-------------------')
logger.warning('warning 测试')
logger.error('error 测试')
logger_server.debug('debug 测试')
logger_server.info('info 测试-------------------')
logger_server.warning('warning 测试')
logger_server.error('error 测试')
2、一般应用
-
在根目录下建立 log 目录
-
在settings中配置:
BASE_LOG_DIR = os.path.join(BASE_DIR, "log") LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d:%(funcName)s] %(message)s' }, 'simple':{ 'format':'[%(levelname)s][%(asctime)s] %(message)s' } }, 'filters': { 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, }, 'handlers': { 'console': { 'level': 'DEBUG', 'filters': ['require_debug_true'], 'class': 'logging.StreamHandler', 'formatter': 'simple' }, 'file': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', 'filename': os.path.join(BASE_LOG_DIR, "log_study.log"), 'maxBytes': 1024 * 1024 * 50, # 日志大小 50M 'backupCount': 3, 'formatter': 'standard', 'encoding': 'utf-8', }, }, 'loggers': { '': { # 部署到生产环境之后可以把'console'移除 'handlers': ['console', 'file'], 'level': 'DEBUG', }, }, }
-
视图函数中使用
logger
:import logging # __name__ 模块logger,对应settings中的 名称为:'' 的 logger logger = logging.getLogger(__name__) def index(request): logger.debug('debug 测试') logger.info('info 测试') logger.warning('warning 测试') logger.error('error 测试')
-
结果:
console
控制台输出:
[INFO][2019-08-06 13:08:25,121] info 测试
[WARNING][2019-08-06 13:08:25,122] warning 测试
[ERROR][2019-08-06 13:08:25,122] error 测试
- log目录生成 log_study.log、log_study.log.1、log_study.log.2和log_study.log.3文件,内容为:
[INFO][2019-08-06 13:08:25,121][views.py:16:index] info 测试
[WARNING][2019-08-06 13:08:25,122][views.py:17:index] warning 测试
[ERROR][2019-08-06 13:08:25,122][views.py:18:index] error 测试