Django的log,主要是复用Python标准库中的logging模块,在settings.py
中进行配置
源代码
1、__init__.py包含以下类:
StreamHandler
Formatter
%(name)s Name of the logger (logging channel) %(levelno)s Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL) %(levelname)s Text logging level for the message ("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL") %(pathname)s Full pathname of the source file where the logging call was issued (if available) %(filename)s Filename portion of pathname %(module)s Module (name portion of filename) %(lineno)d Source line number where the logging call was issued (if available) %(funcName)s Function name %(created)f Time when the LogRecord was created (time.time() return value) %(asctime)s Textual time when the LogRecord was created %(msecs)d Millisecond portion of the creation time %(relativeCreated)d Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded (typically at application startup time) %(thread)d Thread ID (if available) %(threadName)s Thread name (if available) %(process)d Process ID (if available) %(message)s The result of record.getMessage(), computed just as the record is emitted
FileHandler
日志级别:
CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
2、config.py
3、handlers.py包含以下class
TimedRotatingFileHandler:可以根据时间自动生成新的日志文件
HTTPHandler:
RotatingFileHandler:可以根据日志大小自动生成新的日志文件
日志处理类:
class 功能 StreamHandler 输出到Stream。通常用来打印到标准输出。 FileHandler 打印到文件。 NullHandler 不格式化也不打印。主要是为了避免No handlers could be found for logger XXX的设计。 WatchedFileHandler 自动重开log文件,配合别的会自动切分的log文件使用。 RotatingFileHandler 自动按大小切分的log文件。 TimedRotatingFileHandler 按时间自动切分的log文件。 SocketHandler 向Socket打log,基于TCP协议。 DatagramHandler 向Socket打log,基于UDP协议。 SysLogHandler 在Unix-like系统打印到remote或local的Unix syslog。 NTEventLogHandler 在Windows系统打印到微软的event log。 SMTPHandler 通过email发送log。 MemoryHandler 打印到内存buffer。 HTTPHandler 通过HTTP协议向服务器发送log。 QueueHandler 打log到Queue中,适合多进程(multiprocessing)场景。
分层传递日志
a.b.c.d会把日志传到a.b.c;a.b.c会把日志传到a.b;a.b会把日志传到a
写到相应层级日志的方法是,在需要记录日志的文件地方,使用如下函数,里面根据需要填写相应的层级:logger = logging.getLogger('a.b.c')
Django日志示例:
配置:
# https://docs.djangoproject.com/zh-hans/2.1/topics/logging/LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { # 后缀d表示数据格式是整数,s表示数据格式是字符串 'format': '[%(levelname)s] [%(asctime)s] [%(module)s] %(filename)s:%(lineno)d %(funcName)s ' '%(processName)s:[%(process)d] %(threadName)s:[%(thread)d] %(message)s' # 'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}', # 'style': '{', }, 'simple': { 'format': '[%(levelname)s] [%(asctime)s] %(message)s', # 'format': '[%(asctime)s] %(message)s', # 后缀d表示数据格式是整数,s表示数据格式是字符串 # 'format': '[%(levelname)s] [%(asctime)s] [%(module)s] %(filename)s:%(lineno)d %(funcName)s ' # '%(processName)s:[%(process)d] %(threadName)s:[%(thread)d] %(message)s', # 'style': '{', }, 'standard': { # 'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s', 'format': '{asctime} [{levelname:6}] {name:30}: {message}', # 设置上面格式样式;{lineno:3}是行号,至少显示3个字符,少则补空格 # 这里style选择{,是指{asctime}这种形式。 # 如果选择%,则是%(asctime)s这种形式。 # 还有一种选择,是$,是$asctime或${asctime}这种形式。 'style': '{', # 设置时间格式 'datefmt': '%Y-%m-%d %H:%M:%S', }, 'operation': { 'format': '%(message)s' } }, # 'filters': { # # 'special': { # # '()': 'erebus.logging.SpecialFilter', # # 'foo': 'bar', # # }, # 'require_debug_true': { # '()': 'django.utils.log.RequireDebugTrue', # }, # }, # Handler是决定如何处理logger中每一条消息的引擎。它描述特定的日志行为,比如把消息输出到屏幕、文件或网络socket。 # 和 logger 一样,handler 也有日志级别的概念。如果一条日志记录的级别不匹配或者低于 handler 的日志级别, # 对应的消息会被 handler 忽略。 'handlers': { 'default': { 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', 'filename': 'logs/default.log', # 'maxBytes': 1024*1024*5, # 5 MB 'maxBytes': 1024*5, # 5 KB 'backupCount': 5, 'formatter': 'standard', }, 'output_to_file': { 'level': 'INFO', # 忽略debug信息 'class': 'logging.FileHandler', 'filename': '{}/{}.log'.format(BASE_LOG_DIR, conf.get('log', 'name')), 'formatter': 'simple' if DEBUG else 'verbose', 'encoding': 'utf8', }, 'console_log': { 'level': 'DEBUG', # 所有的日志都会被输出到console # 'filters': ['require_debug_true'], 'class': 'logging.StreamHandler', 'formatter': 'simple' }, 'operation': { 'level': 'INFO', 'class': 'logging.FileHandler', 'filename': '{}/{}.log'.format(BASE_LOG_DIR, 'operation'), 'formatter': 'operation', 'encoding': 'utf8' } # 'mail_admins': { # 'level': 'ERROR', # 'class': 'django.utils.log.AdminEmailHandler', # # 'filters': ['special'] # } }, 'loggers': { # 可以通过使用空字符串:''来设置'catch all' logger # 在以下设置中,将所有日志事件保存到logs/default.log,但配置为'propagate': False日志事件除外, # 这些日志事件将保存到相应的日志文件中,比如本文的logs/erebus.log。 '': { 'handlers': ['default'], 'level': 'DEBUG', 'propagate': True }, # 名字随意起,用时,使用logger = logging.getLogger(conf.get('log', 'name'))获取,传到相应的loggers里就可以 conf.get('log', 'name'): { 'handlers': ['output_to_file', 'console_log'], # 当 logger 处理一条消息时,会将自己的日志级别和这条消息的日志级别做对比。 # 如果消息的日志级别匹配或者高于 logger 的日志级别,它就会被进一步处理。 # 否则这条消息就会被忽略掉。当 logger 确定了一条消息需要处理之后,会把它传给 Handler。 # 'level': 'INFO', # debug日志会被忽略 'level': 'DEBUG', # 所有的日志都会被处理 'propagate': False, # 值为False,表示日志不会传到上个层级,自然也不会传到default.log里 }, # 使用logger = logging.getLogger('django.request'), logger.info('info'), # 可以把日志输出到'handlers': ['output_to_file', 'console_log'], # 这里的名字不能随便取,命名为django、django.request才会捕获django的日志 conf.get('log', 'name')+'.request': { 'handlers': ['output_to_file', 'console_log'], 'level': 'DEBUG', # 会把日志向django.request的上层django传播 'propagate': True, }, # 'erebus.custom': { # 'handlers': ['console', 'mail_admins'], # 'level': 'INFO', # # 'filters': ['special'] # }, 'operation': { 'handlers': ['operation'], 'level': 'INFO', # 'propagate': True, } }}
使用日志
logger = logging.getLogger('django')
def hello(request): content = {'hello': 'hello world'} # return HttpResponse("hello world") logger.error('test') logger.error('访问hello界面:error') logger.debug('访问hello界面:debug') logger.info('访问hello界面:info') logger.warning('访问hello界面:warning') logger.critical('访问hello界面:critical') logger.log(40, '测试') logger.exception('ceshi') return render(request, 'hello.html', content)
时间格式:
Directive Meaning Notes %a Locale’s abbreviated weekday name. %A Locale’s full weekday name. %b Locale’s abbreviated month name. %B Locale’s full month name. %c Locale’s appropriate date and time representation. %d Day of the month as a decimal number [01,31]. %H Hour (24-hour clock) as a decimal number [00,23]. %I Hour (12-hour clock) as a decimal number [01,12]. %j Day of the year as a decimal number [001,366]. %m Month as a decimal number [01,12]. %M Minute as a decimal number [00,59]. %p Locale’s equivalent of either AM or PM. (1) %S Second as a decimal number [00,61]. (2) %U Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0. (3) %w Weekday as a decimal number [0(Sunday),6]. %W Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0. (3) %x Locale’s appropriate date representation. %X Locale’s appropriate time representation. %y Year without century as a decimal number [00,99]. %Y Year with century as a decimal number. %z Time zone offset indicating a positive or negative time difference from UTC/GMT of the form +HHMM or -HHMM, where H represents decimal hour digits and M represents decimal minute digits [-23:59, +23:59]. %Z Time zone name (no characters if no time zone exists). %% A literal '%' character.
Django内置的loggers:
Django provides several built-in loggers.
django
、django.request、django.server
、django.template
、django.db.backends、
django.security.*
、django.security.csrf、django.db.backends.schema
日志输出时区问题
当设置日志时区为utc时,中国时区的日志输出会相差8个小时
# 使用utc时间,前端根据时区自动显示当地时间 USE_TZ = True TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True
这是需要修改日志模块,在settings配置里添加:
def beijing(sec, what): beijing_time = datetime.datetime.now() + datetime.timedelta(hours=8) return beijing_time.timetuple() logging.Formatter.converter = beijing
参考:
1、https://codeday.me/bug/20170630/32009.html
2、http://note.qidong.name/2018/11/django-logging/
3、https://docs.djangoproject.com/zh-hans/2.1/topics/logging/#django-request
4、https://blog.csdn.net/u010099080/article/details/85944741
来源:https://www.cnblogs.com/shengulong/p/10294017.html