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
