Day084 django日志

mac2025-12-17  6

django日志

1、概述

​ django框架的日志通过python内置的logging模块实现的,日记可以记录自定义的一些信息描述,也可以记录系统运行中的一些对象数据,还可以记录包括堆栈跟踪、错误代码之类的详细信息

​ logging主要由4部分组成:Loggers、Handlers、Filters和Formatters

2、settings中完整的配置

LOGGING = { # 固定值 'version'1, # 格式器,详细见第6点 'formatters': {}, # 过滤器,详细见第5点 'filters'{}, # 处理器,详细见第4点 'handlers':{}, # 记录器,详细见第3点 'loggers':{}, # 根记录器,配置等同普通记录器,但是没有propagate配置项 'root':{}, # 默认为False。True:是将配置解释为现有配置的增量。False:配置会覆盖已有默认配置 'incremental':True, # 默认为True。禁用任何现有的非root记录器。如果设置了incremental=True,则此配置无效 'disable_existing_loggers': False }

3、Loggers

​ 这个类是logging系统的入口

​ python定义了日志的5个级别,分别对应python程序中日志信息的不同严重性(严重程度从上到下越来越严重,也就是级别越高):

DEBUG:用于调试的最低级的系统信息INFO:一般性的系统信息WARNING:一些警告性的信息,发生了一些小问题,这些问题不影响系统的正常运行,但是也不建议出现ERROR:系统出现错误了,该错误会影响系统的正常运行,记录错误相关的信息CRITICAL:非常严重的问题,譬如可能引起系统崩溃的问题等

​ 在使用logger记录日志时,每条日志消息也有日志级别,当logger记录该日志消息时,会将消息的级别和logger配置的日志级别进行比较,只有消息的级别达到或超过logger配置的日志级别,才会将该日志消息传递给handler进一步处理,否则该日志消息会被忽略

​ PS:一般开发环境时,会启用DEBUG级别,而在生产环境中,启用WARNING或ERROR级别

1.settings中配置

通过在settings中配置LOGGING配置项实现日志配置,共4个配置项(都是可选的,不过一般会指定handler):

level:指定记录日志的级别,没有配置则处理所有级别的日志propagate:设置该记录器的日志是否传播到父记录器,不设置则是Truefilters:指定过滤器列表handlers:指定处理器列表

示例如下:

LOGGING = { 'version': 1, # 固定值,现在只有这一个版本 'disable_existing_loggers': False, # 设置已存在的logger不失效 'loggers': { '': { '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'] } } }

说明:

配置了4个 logger, 分别对应2个不同的handler(console输出日志到控制台,mail_admins输出日志到邮件)

‘’:默认的记录器,不指定特定名称,那么就是使用这个记录器,没有配置level,那么就是处理所有级别的日志,传递所有级别的日志到console控制器django:传递所有级别的日志到console控制器django.request:django记录器的子记录器,处理ERROR级别及以上的日志,propagate设置为 False,表明不传播日志给 “django”,该logger传递日志到mail_admins控制器myproject.custom:处理INFO级别及以上的日志,应用了一个 special 的过滤器来过滤日志,传递日志到2个控制器([‘console’, ‘mail_admins’])处理

​ django框架有个默认的配置:DEFAULT_LOGGING,一旦配置了自己的LOGGING后,那么所有的默认的LOGGER全部都失效,失效不等于没有记录器了,而是说记录器不起作用了,即不会记录日志,也不会将日志传播给父记录器。因此你应该非常小心使用,因为你会感觉你丢了日志一样,可以手动设置同名的logger实现覆盖,如:

LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'file': { 'level': 'DEBUG', 'class': 'logging.FileHandler', 'filename': '/path/to/django/debug.log', }, }, 'loggers': { # 覆盖了 django 记录器,所有django的记录日志最后全部写入到文件中 'django': { 'handlers': ['file'], 'level': 'DEBUG', 'propagate': True, }, }, }

​ disable_existing_loggers默认是True,除非设置disable_existing_loggers为False,那么默认配置的记录器才会起作用

LOGGING = { 'disable_existing_loggers': False, }

​ 配置还可以使用系统变量,如下示例中读取 DJANGO_LOG_LEVEL 环境变量:

import os LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'class': 'logging.StreamHandler', }, }, 'loggers': { 'django': { 'handlers': ['console'], 'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'), }, }, }

2.logger的简单使用

在诸如views.py中:

import logging # 生成一个以当前文件名为名字的logger实例 logger = logging.getLogger(__name__) # __name__ 也可以换成在settings中配置的 logger 名称,生成指定的logger logger_custom = logging.getLogger('myproject.custom') def index(request): logger.debug("进入index视图函数") logger_custom.debug("进入index视图函数")

getLogger(_name_):记录器名使用模块名,这是基于每个模块过滤和处理日志记录调用,对应默认记录器,即名称为 ‘’ 的

getLogger(‘myproject.custom’):通过 “.” 符号分隔的方式,定义记录器名称的层次结构,‘myproject’ 是根记录器, ‘myproject.custom’是子记录器,甚至 ‘myproject.custom.child’ 是孙辈的记录器。使用层次结构的作用是因为子记录器是可以传播日志记录给父记录器的,最终传播到根记录器。默认就是传播的,如果不想传播,那么需要在logger的配置中使用’propagate’: False

3.常用方法

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),输出异常的堆栈信息

4.不常用方法

Logger.setLevel(lel):指定最低的日志级别,低于lel的级别将被忽略。debug是最低的内置级别,critical为最高

Logger.addFilter(filt)、Logger.removeFilter(filt):添加或删除指定的filter

Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增加或删除指定的handler

5.django内置logger

​ 内置的logger在django项目运行中会自动记录日志,与我们手动创建的logger的执行没有关系,除非我们也创建相同的logger

​ django框架调用的地方在:django.core.servers.basehttp中(如WSGIRequestHandler)

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:记录代码和数据库交互相关的消息,例如,请求执行的每个SQL语句都会记录为DEBUG级别的日志。这个记录器只有在settings.DEBUG设置为True时才启用,并且不记录事务管理(如:BEGIN, COMMIT, 和 ROLLBACK)

发送给此记录器的消息具有以下额外上下文:

duration:执行SQL语句所花费的时间。sql:已执行的SQL语句。params:SQL调用中使用的参数

django.security.*:记录任何SuspiciousOperation和其他安全相关错误(django.security.csrf )的消息,SuspiciousOperation子类型有:

DisallowedHost DisallowedModelAdminLookup DisallowedModelAdminToField DisallowedRedirect InvalidSessionKey RequestDataTooBig SuspiciousFileOperation SuspiciousMultipartForm SuspiciousSession TooManyFieldsSent

使用如:django.security.DisallowedHost

django.db.backends.schema:记录数据库迁移过程中的日志,但是不记录执行的查询SQL语句等,发送给此记录器的消息具有以下额外上下文:

sql:已执行的SQL语句。params:SQL调用中使用的参数

4、Handlers

​ 这个类是确定logger中消息发生的引擎程序,描述特定的日志记录行为,譬如控制台打印、写入日志文件、通过网络进行发送等

​ 与logger一样,handler也具有日志级别,如果日志记录的日志级别未达到或超过handler的级别,则handler将忽略该消息。

​ 一个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个handler,使用了2个filter:require_debug_true和special, 使用了1个formatter:simple

console:使用logging.StreamHandler,记录INFO级别及以上的日志到sys.stderr,使用simple格式化输出内容mail_admins:使用django.utils.log.AdminEmailHandler,将ERROR及以上的日志通过special过滤器过滤后,发送邮件到管理员邮箱(需要配置settings中的一些其他的信息,譬如ADMINS等)

2.不常用方法

Handler.setLevel(level):指定被处理的信息级别,低于level级别的信息将被忽略

Handler.setFormatter(fmt):给这个handler选择一个格式fmt

Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象

3.内置处理器

python3的logging中的handler:

StreamHandler:输出到stream,未指定则使用sys.stderr输出到控制台

FileHandler:继承自StreamHandler,输出到文件,默认情况下,文件无限增长

初始化参数:filename,mode =‘a’,encoding = None,delay = False

delay如果为True,那么会延迟到第一次调用emit写入数据时才打开文件

配置:

'handlers': { 'file': { 'level': 'DEBUG', 'class': 'logging.FileHandler', 'filename': '/path/to/django/app.log', #参数配置在这里,多个参数按顺序继续配置即可, 如果要添加encoding,那么在下面添加 encoding: 'utf-8' 即可 }, }

NullHandler:没有任何输出,避免出现错误:No handlers could be found for logger XXX

WatchedFileHandler:自动重开log文件,配合别的会自动切分的log文件使用

RotatingFileHandler:自动按大小切分的log文件

初始化参数:filename,mode =‘a’,maxBytes = 0,backupCount = 0,encoding = None,delay = False

maxBytes:最大字节数,超过时创建新的日志文件,如果backupCount或maxBytes有一个为0,那么就一直使用一个文件

backupCount:最大文件个数,新文件的扩展名是指定的文件后加序号".1"等,譬如:backupCount=5,基础文件名为:app.log,那么达到指定maxBytes之后,会关闭文件app.log,将app.log重命名为app.log.1,如果app.log.1存在,那么就顺推,先将 app.log.1重命名为app.log.2,再将现在的app.log命名为app.log.1,最大创建到app.log.5(旧的app.log.5会被删除),然后重新创建app.log文件进行日志写入,也就是永远只会对app.log文件进行写入。

TimedRotatingFileHandler:按时间自动切分的log文件,文件后缀 %Y-%m-%d_%H-%M-%S

初始化参数:filename, when=‘h’, interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None

when:时间间隔类型,不区分大小写

'S':秒 'M':分钟 'H':小时 'D':天 'W0'-'W6':星期几(0 = 星期一) 'midnight':如果atTime未指定,则在 0点0分0秒 翻转,否则在atTime时间翻转

interval:间隔的数值

backupCount: 文件个数

encoding:编码

delay:True是写入文件时才打开文件,默认False,实例化时即打开文件

utc:False则使用当地时间,True则使用UTC时间

atTime:必须是datetime.time实例,指定文件第一次切分的时间,when设置为S,M,H,D时,该设置会被忽略

SocketHandler:通过TCP套接字发送日志记录消息

初始化参数:host, port

DatagramHandler:通过UDP套接字发送日志记录消息

SysLogHandler :发送记录消息到远程或本地Unix系统日志

NTEventLogHandler:发送日志消息到本地的Windows NT,Windows 2000或Windows XP事件日志

SMTPHandler:通过email发送日志记录消息

初始化参数:mailhost, fromaddr, toaddrs, subject, credentials=None, secure=None, timeout=5.0

mailhost:发件人邮箱服务器地址(默认25端口)或地址和指定端口的元组,如:(‘smtp.163.com’, 25)

fromaddr:发件人邮箱

toaddrs:收件人邮箱列表

subject:邮件标题

credentials:如果邮箱服务器需要登录,则传递(username, password)元组

secure:使用TLS加密协议

MemoryHandler :在内存中的日志记录缓冲,定期将其发送到目标处理程序,只要缓冲区已满,或者发生某个严重程度或更高的事件,就会发生发送

HTTPHandler:发送记录消息到Web服务器,使用GET或POST

QueueHandler:发送记录消息到队列中,适合多进程(multiprocessing)场景

QueueListener:从队列中接收消息,适合多进程(multiprocessing)场景,用于和QueueHandler搭配

django内置的handler:

AdminEmailHandler:会将收到的每一条日志消息发送一个邮件到ADMINS指定的邮箱地址

必须settings中设置 DEBUG=False 才起作用

示例配置:

DEBUG=False EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'smtp.qq.com' # smtp地址 EMAIL_PORT = 25 EMAIL_HOST_USER = 'xxxx@qq.com' # smtp 服务器的用户名 EMAIL_HOST_PASSWORD = 'xxxxxxxx' # smtp服务器的密码 SERVER_EMAIL = 'xxxx@qq.com' ADMINS = [('Terry', 'xxxx@qq.com')]

ADMINS默认是[],示例配置:[(‘John’, ‘john@example.com’), (‘Mary’, ‘mary@example.com’)]

如果日志记录包含request属性,则请求的完整详细信息将包含在电子邮件中。

如果客户端的IP地址在INTERNAL_IPS设置中,则电子邮件主题将包含短语“内部IP” ; 如果没有,它将包括“外部IP”。

如果日志记录包含堆栈跟踪信息,则该堆栈跟踪将包含在电子邮件中。

初始化参数:include_html=False, email_backend=None

include_html:该值设置为True,并且settings中设置DEBUG=True时,则会在邮件中包括含有调试网页的全部内容的HTML附件,该附件包含完整的回溯,包含堆栈每个级别的局部变量的名称和值,以及Django设置的值,会比较敏感,谨慎使用

email_backend:指定邮件后台,没设置使用django默认的

简单配置如下:

'handlers': { 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', } },

覆盖django默认的邮件后台,配置:

'handlers': { 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', 'email_backend': 'django.core.mail.backends.filebased.EmailBackend', 'include_html': True # 信息中包含html页面 } },

4.自定义处理器

​ 任意自定义的class,继承自logging.Handler,并且实现emit和flush方法(如下logging内置的StreamHandler类):

from logging import Handler class StreamHandler(Handler): terminator = '\n' def __init__(self, stream=None): Handler.__init__(self) if stream is None: stream = sys.stderr self.stream = stream def flush(self): self.acquire() try: if self.stream and hasattr(self.stream, "flush"): self.stream.flush() finally: self.release() def emit(self, record): try: msg = self.format(record) stream = self.stream stream.write(msg) stream.write(self.terminator) self.flush() except Exception: self.handleError(record)

5、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个过滤器

special:使用自定义的SpecialFilter类,传入初始化参数 foo=‘bar’

require_debug_true:使用类:RequireDebugTrue

2.内置过滤器

python内置的过滤器:

日志过滤器的父类:Filter,一般不直接使用

django内置的过滤器:

CallbackFilter:

初始化参数:callback

callback:为每个记录调用callback,如果callback返回True,则允许日志通过,如果callback返回False,则不允许该日志通过

示例:

# callback函数: def skip_unreadable_post(record): if record.exc_info: exc_type, exc_value = record.exc_info[:2] if isinstance(exc_value, UnreadablePostError): return False return True # filter配置: 'filters': { 'skip_unreadable_posts': { '()': 'django.utils.log.CallbackFilter', 'callback': skip_unreadable_post, } },

RequireDebugFalse:仅在settings.DEBUG为False时传递记录

'filters': { 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse', } }

RequireDebugTrue:仅在settings.DEBUG为True时传递记录

3.自定义过滤器

​ 任意自定义的class,继承自logging.Filter,并且实现filter方法(如下django内置的RequireDebugFalse类)

class RequireDebugFalse(logging.Filter): def filter(self, record): return not settings.DEBUG class TestFilter(logging.Filter): def __init__(self, name='', exist_word=None): super().__init__(name) self.exist_word = exist_word def filter(self, record): if not self.exist_word or self.exist_word in record.msg: return True else: return False

6、Formatters

​ 日志记录最终需要呈现为文本,formatter程序描述该文本的确切格式。formatter通常由包含LogRecord属性的Python格式化字符串组成 ; 但是,也可以编写自定义formatter来实现特定的格式化行为。

1.settings中配置:

3个参数(具体看后面的Formatter类):

():指定格式器的类,不指定的话,默认使用logging.Formatterformat:格式化字符串style:样式选择datefmt:日期格式化字符串,使用的是python中时间日期格式化符号 LOGGING = { 'formatters': { 'verbose': { '()': 'logging.Formatter', 'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}', 'style': '{', }, 'simple': { 'format': '{levelname} {message}', 'style': '{', }, } }

说明:

配置了2个格式器:

simple:只输出简单的:日志级别名称 日志消息verbose:输出:日志级别名称 生成日志消息的时间 模块 进程 线程 日志消息

2.内置格式器

python内置的格式器

Formatter:默认格式器

初始化参数:fmt=None, datefmt=None, style=’%’

fmt:格式化字符串,指定输出格式,如:’{levelname}{process:d}{message}’ %(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:日志消息

datefmt:日期格式化字符串,为None则使用ISO8601格式化,如:‘2010-01-01 08:03:26,870’

style:’%’,’{’ 或 ‘$’,3选一:

‘%’:默认是这个,使用python的 % 格式化 , 如: %(levelname)s‘{’:使用 str.format格式化(django框架使用这个), 如:{levelname}‘$’:使用类 string.Template 格式化,如:$levelname

BufferingFormatter:一种适于格式化批量记录的格式器,对每条记录都使用指定的格式器进行格式化

初始化参数:linefmt=None

linefmt:指定格式器,设置为None使用上述的默认Formatter

django内置的格式器

ServerFormatter:根据status_code不同,将日志消息格化式成不同的颜色的消息

7、logging.LogRecord对象

​ 每次logger记录日志时,都会自动创建该LogRecord实例

初始化参数:name,level,pathname,lineno,msg,args,exc_info,func = None,sinfo = None

说明:

name - 用于记录此LogRecord表示的事件的记录器的名称level - 日志记录事件的数字级别(DEBUG是10,INFO是20,以此类推),并将转换为LogRecord的两个属性: 对于数值levelno和对应的级别名称levelnamepathname - 进行日志记录调用的源文件的完整路径名lineno - 进行日志记录调用的源文件中的行号msg - 事件描述消息,可能是带有可变数据占位符的格式字符串args - 要合并到msg参数中以获取事件描述的可变数据exc_info - 包含当前异常信息的异常元组,或者None(没有可用的异常信息)func - 调用日志记录调用的函数或方法的名称sinfo - 表示当前线程中堆栈基础的堆栈信息的文本字符串,直到日志记录调用

方法

getMessage:返回用户提供的参数与消息合并后的消息

属性

首先是第6点Formatters中内置格式器Formatters类的 fmt 属性中,描述的类似:%(name)s 中的 name 就是 该对象的属性

其他属性如下:

args:元组或字典(只有一个参数是),用于合并日志消息exc_info:异常元组(类似:sys.exc_info),没有异常则是Nonemsg:日志记录调用中传递的格式字符串,可以合并args生成日志消息stack_info:在当前线程中从堆栈底部堆栈帧信息(如果有的话),直到并包括记录调用的堆栈帧

8、项目中应用日志

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及以上的日志 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', }, }, }

注意:RotatingFileHandler在生成新的文件时,会抛出 PermissionError 异常(其它分割文件的也同样会出现),是因为django自带的简易web服务器,启动时默认启动2个进程,以便于实现 reload 的功能,如果要避免此错误,那么必须修改manage.py的启动参数为:

​ runserver --noreload

但是增加了 --noreload 这个参数后,web服务器不会自动检测代码的修改和重启服务

视图函数中使用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 测试
最新回复(0)