[英]Structured Logging for a project
我在我的python項目上使用Logging。 我的問題是關於在我的項目中構建日志記錄的正確和優雅的方法,因為我將首先描述我正在使用的結構。
我有3個主要的.py腳本,所以在啟動時稱為服務的acquisition.py,actus.py和management.py。 上面的3個腳本導入network.py和devices.py。
我想組織與3個主要腳本相關的每個文件的日志記錄,所以我想擁有:acquisition.log,actuation.log和management.log。 在這個日志里面我希望從對network.py的調用中得到相應的日志一個device.py(使用名稱空間%(name) )
INFO acquisition.thread 2016-03-17 12:26:02,069 in Thread 70de3b66-e14b-11e5-8953-80fa5b0ae007
DEBUG acquisition 2016-03-17 12:26:02,070 Thread launched 70de3b66-e14b-11e5-8953-80fa5b0ae007
INFO acquisition.devices 2016-03-17 12:26:03,072 Variable_R read: 0013a20040c1bb0b temperature1
ERROR acquisition.devices 2016-03-17 12:26:19,076 variable.read.DeviceConfigurationError: 0013a20040c1bb0b
INFO acquisition.thread 2016-03-17 12:26:19,077 exit Thread 70ddfa20-e14b-11e5-8953-80fa5b0ae007
ERROR acquisition.devices 2016-03-17 12:26:25,085 variable.read.DeviceConfigurationError: 0013a20040c1bb0b
INFO acquisition.thread 2016-03-17 12:26:25,086 exit Thread 70de3b66-e14b-11e5-8953-80fa5b0ae007
在這種情況下,您可以看到,對於相同的日志文件,我可以從不同的文件進行日志記錄,可以在日志命名空間acquisition.thread和acquisition.devices中看到。
我實現這一點的方法是使用記錄器功能,我用它在每個文件中創建一個回退記錄器,我正在記錄。 並且,稍后如果我想記錄該文件中的信息,我將在主腳本文件中更改導入文件中創建的記錄器。
代碼示例解釋了上述內容:
imports...
import logger_sys
import logging
import xnetwork
import xdevices
# Log configuration
log_name = os.path.basename(__file__).strip(".py")
logit = logger_sys.setup_logger(log_name, log_name) #internal logger for main file
logger_thread = logging.getLogger(log_name + '.thread')
#Log configuration of external files
xnetwork.logger = logging.getLogger(log_name + '.network')
xdevices.logger = logging.getLogger(log_name + '.devices')
logit.info("START acquisition_service")
# REST OF THE CODE...
import logger_sys
# Fallback logger in case the calling script doesnt modify logger
log_name = __name__.strip(".py") + '_fallback'
logger = logger_sys.setup_logger(log_name, log_name, stream_hdlr=False)
# REST OF THE CODE...
import logger_sys
# Fallback logger in case the calling script doesnt modify logger
log_name = __name__.strip(".py") + '_fallback'
logger = logger_sys.setup_logger(log_name, log_name, stream_hdlr=False)
# REST OF THE CODE...
import logging, sys, os
from global_settings import RUNNING_MODE, DEBUG, STAGING, PRODUCTION
def setup_logger(namespace, filename, stream_hdlr=True):
logger = logging.getLogger(namespace)
handler_format = logging.Formatter("%(levelname)s %(name)s %(asctime)s %(message)s")
log_handler = logging.FileHandler(filename + ".log")
logger.addHandler(log_handler)
log_handler.setFormatter(handler_format)
if RUNNING_MODE == DEBUG:
if stream_hdlr:
log_handler = logging.StreamHandler(sys.stdout)
logger.addHandler(log_handler)
log_handler.setFormatter(handler_format)
logger.setLevel(logging.DEBUG)
elif RUNNING_MODE == STAGING or RUNNING_MODE == PRODUCTION:
logger.setLevel(logging.INFO)
return logger
我想知道是否有更優雅的解決方案,不使用將logger作為參數傳遞給被調用方法的邏輯。
我想了解在更復雜的情況下通常如何構建日志記錄,例如在使用外部模塊時。
而且,我想閱讀關於這種采伐策略的批評者。
先感謝您
您應該學習正式的日志記錄和一些正確記錄的復雜項目。 我建議閱讀請求源代碼 ,看看一個相當復雜的項目如何進行日志記錄。
對您的案例來說,食譜的關鍵點可能是:
對logging.getLogger('someLogger')的多次調用返回對同一記錄器對象的引用。 這不僅在同一模塊中,而且在模塊之間也是如此,只要它在同一個Python解釋器過程中。
一種典型的方法是在文件的頂部有類似下面的內容:
import logging
log = logging.getLogger(__name__)
這使log
成為全局,因此可以在函數中使用它而不將log
作為參數傳遞:
def add(x, y):
log.debug('Adding {} and {}'.format(x, y))
return x + y
如果您正在創建一些長時間運行的服務並打算記錄所有/大多數/多個函數調用,請考慮使用裝飾器。 我建議來自Fresh Books Dev Blog的這篇文章作為使用裝飾器進行日志記錄的介紹。 聽起來您的程序可能會受益於裝飾器方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.