前言
python有默認的日志配置,但是對於業務開發來說一般需要配置自己的日志輸出方式,同時各種框架也繼承了日志相關的內容。下面記錄一下celery和flask框架中自帶的logger使用方法。
flask使用logger
flask中的app對象自帶了logger方法,其本質上是在python內置的logging模塊上進行封裝使用,其調用的方式為:
from flask import current_app
current_app.logger.error('this is a error')
current_app.logger.info('this is a info')
current_app.logger.warning('this is a wraning')
current_app.logger.debug('this is a debug')
配置方法
日志的配置方法有多種,和python配置日志的方式是一樣的。
可參考:python日志配置logger
- 通過字典配置
#logging.py
logger_dict = {
'version': 1, # 該配置寫法固定
'formatters': { # 設置輸出格式
'default': {'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',}
},
# 設置處理器
'handlers': {
'wsgi': {
'class': 'logging.StreamHandler',
'stream': 'ext://sys.stdout',
'formatter': 'default',
'level': 'DEBUG'
}},
# 設置root日志對象配置
'root': {
'level': 'INFO',
'handlers': ['wsgi']
},
# 設置其他日志對象配置
'loggers': {
'test':
{'level': 'DEBUG',
'handlers':['wsgi'],
'propagate':0}
}
}
- 源碼分析
flask的logger其實也是通過python的logging模塊創建logger對象得到的,源碼為:
# logging.py
from logging import getLogger, getLoggerClass
def create_logger(app):
...
# 創建一個調試模式下的日志處理器,級別為debug
debug_handler = DebugHandler()
debug_handler.setLevel(DEBUG)
debug_handler.setFormatter(Formatter(DEBUG_LOG_FORMAT))
# 創建一個運行過程的日志處理器,級別為error
prod_handler = ProductionHandler(_proxy_stream)
prod_handler.setLevel(ERROR)
prod_handler.setFormatter(Formatter(PROD_LOG_FORMAT))
# 獲取應用的名字,即app = Flask(app.name)傳入的參數名,然后創建一個logger對象
logger = getLogger(app.logger_name)
# 先清空以前所有的處理器
del logger.handlers[:]
logger.__class__ = DebugLogger
# 加入新的處理器
logger.addHandler(debug_handler)
logger.addHandler(prod_handler)
# 默認情況下不繼承
logger.propagate = False
return logger
當程序調用current_app.logger時,會得到create_logger函數返回的logger對象,如果我們開啟的是調試模式,會使用debug_handler處理器;如果是非調試模式使用的是ProductionHandler處理器,日志的輸出格式為:
# 調試模式格式
DEBUG_LOG_FORMAT = (
'-' * 80 + '\n' +
'%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n' +
'%(message)s\n' +
'-' * 80
)
# 非調試模式格式
PROD_LOG_FORMAT = '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
此外我們開發程序時可以看到除了我們調用current_app.logger產生的日志信息外,還有flask默認的日志信息,這個默認的日志輸出我們是可以通過配置日志文件來修改的,但是current_app.logger產生的日志信息的格式是固定的,如果不滿足我們的要求的話就需要手動創建logger對象來使用。
細節
我們加載日志文件的時候應該盡可能的早,避免在調用過一次app.logger之后才加載日志配置,所以最好在app被創建之前就加載日志配置文件。
# app.py
logging.config.fileConfig(Config.FILEPATH)
app = Flask(__name__)
在celery中使用logger
celery也封裝了logger使用方法:
from celery.utils.log import get_task_logger
# 創建一個logger對象
logger = get_task_logger('name')
celery的logger調用的仍然是logging模塊的logger.
# get_task_logger函數調用了get_logger函數
# 傳入一個字符串獲取一個logger對象
def get_logger(logger):
"""Get logger by name."""
# 判斷該參數是不是字符串,是就獲取一個logger對象
if isinstance(logger, string_t):
logger = logging.getLogger(logger)
# 沒有處理器就添加NullHandler處理器
if not logger.handlers:
logger.addHandler(logging.NullHandler())
return logger
- 其相關的配置可以在celery的配置文件中設置;
# 在4.0版本后改成了小寫,但是原來的還沒有棄用
CELERYD_HIJACK_ROOT_LOGGER :默認true,先前所有的logger的配置都會失效,可以通過設置false禁用定制自己的日志處理程序;
CELERYD_LOG_COLOR :是否開啟不同級別的顏色標記,默認開啟;
CELERYD_LOG_FORMAT :設置celery全局的日志格式;默認格式:"[%(asctime)s: %(levelname)s/%(processName)s] %(message)s"
CELERYD_TASK_LOG_FORMAT:設置任務日志格式,默認:"[%(asctime)s: %(levelname)s/%(processName)s [%(task_name)s(%(task_id)s)] %(message)s"
CELERY_REDIRECT_STDOUTS:設置標准輸入輸出重定向到當前的處理器,默認為 true
CELERY_REDIRECT_STDOUTS_LEVEL:設定標准輸入輸出重定向到當前的處理器日志的輸出級別;即指定使用print()輸出的是什么級別的日志記錄;默認wraning;
注意:
-
由於celery的運行是獨立的,在flask中定義的logger對象的配置在celery的程序中是失效的,必須使用get_task_logger創建logger;
-
指定celery日志的輸出等級,通過啟動時用--loglevel參數來指定;