前言
Django對於日志輸出的信息是很完善的,request的信息,setting配置,trackback的信息,一應俱全,足夠我們調試了。但是在線上環境,如果讓用戶看到這些信息,是很不安全的(暴露代碼)。所以在線上我們要關閉Debug,但是又不能扔掉這些調試信息,這就要用到logging模塊。
logging模塊其實是Python的模塊,在Django中有很多本地化的支持。
Python日志記錄配置由四部分組成:
-
Logger(記錄儀)
- Handler處理程序
- Filters過濾器
- Formaters格式化程序
Logger
記錄器是記錄系統的入口點。每個記錄器都是一個命名存儲桶,可以將消息寫入進行處理。
記錄器配置為具有日志級別。此日志級別描述了記錄器將處理的消息的嚴重性。Python定義了以下日志級別:
DEBUG
:用於調試目的的低級系統信息INFO
:一般系統信息WARNING
:描述已發生的小問題的信息。ERROR
:描述已發生的主要問題的信息。CRITICAL
:描述已發生的嚴重問題的信息。
一旦記錄器確定需要處理消息,它就會傳遞給處理程序。
處理程序
處理程序是確定記錄器中每條消息發生情況的引擎。它描述了特定的日志記錄行為,例如將消息寫入屏幕,文件或網絡套接字。
與記錄器一樣,處理程序也具有日志級別。如果日志記錄的日志級別未達到或超過處理程序的級別,則處理程序將忽略該消息。
記錄器可以有多個處理程序,每個處理程序可以具有不同的日志級別。以這種方式,可以根據消息的重要性提供不同形式的通知。
過濾器
- 過濾器用於提供對從記錄器到處理程序的日志記錄傳遞的額外控制。
- 默認情況下,將處理滿足日志級別要求的任何日志消息。但是,通過安裝篩選器,您可以在日志記錄過程中添加其他條件
- 例如,您可以安裝僅允許
ERROR
發出來自特定源的消息的過濾器。
- 例如,您可以安裝僅允許
- 過濾器還可用於在發出之前修改日志記錄。
- 例如,如果滿足一組特定條件,您可以編寫一個過濾器,將
ERROR
日志記錄降級 為WARNING
記錄。
- 例如,如果滿足一組特定條件,您可以編寫一個過濾器,將
- 過濾器可以安裝在記錄器或處理器上; 可以在鏈中使用多個過濾器來執行多個過濾操作。
格式化程序
最終,日志記錄需要呈現為文本。格式化程序描述該文本的確切格式。格式化程序通常由包含LogRecord屬性的Python格式化字符串組成 ; 但是,您也可以編寫自定義格式化程序來實現特定的格式化行為。
使用日志記錄
配置記錄器,處理程序,過濾器和格式化程序后,需要將日志記錄調用放入代碼中。使用日志框架非常簡單。這是一個例子:
# import the logging library import logging # Get an instance of a logger logger = logging.getLogger(__name__) def my_view(request, arg1, arg): ... if bad_mojo: # Log an error message logger.error('Something went wrong!')
配置日志記錄
常用配置
BASE_LOG_DIR = os.path.join(BASE_DIR, "log") LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' '[%(levelname)s][%(message)s]' }, 'simple': { 'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' }, 'collect': { 'format': '%(message)s' } }, 'filters': { 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, }, 'handlers': { 'console': { 'level': 'DEBUG', 'filters': ['require_debug_true'], # 只有在Django debug為True時才在屏幕打印日志 'class': 'logging.StreamHandler', 'formatter': 'simple' }, 'SF': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,根據文件大小自動切 'filename': os.path.join(BASE_LOG_DIR, "xxx_info.log"), # 日志文件 'maxBytes': 1024 * 1024 * 50, # 日志大小 50M 'backupCount': 3, # 備份數為3 xx.log --> xx.log.1 --> xx.log.2 --> xx.log.3 'formatter': 'standard', 'encoding': 'utf-8', }, 'TF': { 'level': 'INFO', 'class': 'logging.handlers.TimedRotatingFileHandler', # 保存到文件,根據時間自動切 'filename': os.path.join(BASE_LOG_DIR, "xxx_info.log"), # 日志文件 'backupCount': 3, # 備份數為3 xx.log --> xx.log.2018-08-23_00-00-00 --> xx.log.2018-08-24_00-00-00 --> ... 'when': 'D', # 每天一切, 可選值有S/秒 M/分 H/小時 D/天 W0-W6/周(0=周一) midnight/如果沒指定時間就默認在午夜 'formatter': 'standard', 'encoding': 'utf-8', }, 'error': { 'level': 'ERROR', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自動切 'filename': os.path.join(BASE_LOG_DIR, "xxx_err.log"), # 日志文件 'maxBytes': 1024 * 1024 * 5, # 日志大小 50M 'backupCount': 5, 'formatter': 'standard', 'encoding': 'utf-8', }, 'collect': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自動切 'filename': os.path.join(BASE_LOG_DIR, "xxx_collect.log"), 'maxBytes': 1024 * 1024 * 50, # 日志大小 50M 'backupCount': 5, 'formatter': 'collect', 'encoding': "utf-8" } }, 'loggers': { '': { # 默認的logger應用如下配置 'handlers': ['SF', 'console', 'error'], # 上線之后可以把'console'移除 'level': 'DEBUG', 'propagate': True, }, 'collect': { # 名為 'collect'的logger還單獨處理 'handlers': ['console', 'collect'], 'level': 'INFO', } }, }
可以添加發送郵件
#管理員郵箱 ADMINS = ( ('laixintao','*******@163.com'), ) #非空鏈接,卻發生404錯誤,發送通知MANAGERS SEND_BROKEN_LINK_EMAILS = True MANAGERS = ADMINS #Email設置 EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST= 'smtp.163.com'#QQ郵箱SMTP服務器(郵箱需要開通SMTP服務) EMAIL_PORT= 25 #QQ郵箱SMTP服務端口 EMAIL_HOST_USER = '**********@163.com' #我的郵箱帳號 EMAIL_HOST_PASSWORD = '**************' #授權碼 EMAIL_SUBJECT_PREFIX = 'website' #為郵件標題的前綴,默認是'[django]' EMAIL_USE_TLS = True #開啟安全鏈接 DEFAULT_FROM_EMAIL = SERVER_EMAIL = EMAIL_HOST_USER #設置發件人 #logging日志配置 LOGGING = { 'version': 1, 'disable_existing_loggers': True, 'formatters': {#日志格式 'standard': { 'format': '%(asctime)s [%(threadName)s:%(thread)d] [%(name)s:%(lineno)d] [%(module)s:%(funcName)s] [%(levelname)s]- %(message)s'} }, 'filters': {#過濾器 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse', } }, 'handlers': {#處理器 'null': { 'level': 'DEBUG', 'class': 'logging.NullHandler', }, 'mail_admins': {#發送郵件通知管理員 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', 'filters': ['require_debug_false'],# 僅當 DEBUG = False 時才發送郵件 'include_html': True, }, 'debug': {#記錄到日志文件(需要創建對應的目錄,否則會出錯) 'level':'DEBUG', 'class':'logging.handlers.RotatingFileHandler', 'filename': os.path.join(BASE_DIR, "log",'debug.log'),#日志輸出文件 'maxBytes':1024*1024*5,#文件大小 'backupCount': 5,#備份份數 'formatter':'standard',#使用哪種formatters日志格式 }, 'console':{#輸出到控制台 'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'standard', }, }, 'loggers': {#logging管理器 'django': { 'handlers': ['console'], 'level': 'DEBUG', 'propagate': False }, 'django.request': { 'handlers': ['debug','mail_admins'], 'level': 'ERROR', 'propagate': True, }, # 對於不在 ALLOWED_HOSTS 中的請求不發送報錯郵件 'django.security.DisallowedHost': { 'handlers': ['null'], 'propagate': False, }, } }
以上的配置文件中,有三個日志處理器。分別是:
- ‘django.request':django的request發生error會自動記錄,然后使用debug將信息記錄到文件,還有mail_admins將信息通過郵件發送給管理員。這里郵件的功能非常棒!並不是一個純文本信息,而是一個html文件,和我們在瀏覽器看到的錯誤頁面一模一樣!要正常使用郵件功能需要像我一樣配置一下上面的郵件發件人信息。我是直接去網易申請了一個郵箱。要格外注意三點:
- 一定要去郵件服務商開啟SMTP服務;
- 不同的郵件服務商可能有一些特殊的設置,比如網易,會給你一個客戶端授權碼,這個才是密碼,而不是網頁的登錄密碼。
- 注意服務商有沒有對發信頻率的限制。
- ‘django':使用console處理器,將信息輸出。在開發的時候就可以使用這個處理器(什么?print? 太low了!)
- 最后一個處理器見注釋
日志模塊流程圖
參考https://www.cnblogs.com/liwenzhou/p/8763264.html
https://www.jb51.net/article/105563.htm