Python logging handler概述
Python logging 模塊提供了一套靈活的日志記錄系統,允許開發者在應用程序中記錄不同級別的消息,如調試信息、警告、錯誤等。使用Python SDK提供的logging Handler可以使Python程序在日志在不落盤的情況下自動上傳到日志服務上,這種上傳方式具有實時性、異步性、吞吐量大、配置簡單等特點。使用這部分功能,只需要配置handler目錄下的logging.ini 內的幾個關鍵配置即可直接使用。
使用步驟
1、安裝ctyun-lts-python-sdk:1.6.0,目錄中包含ctyun-lts-python-sdk-1.6.0.tar.gz。
pip install ctyun-lts-python-sdk-1.6.0.tar.gz
如果安裝失敗,可單獨安裝requirements_py3.txt,詳情可參考python SDK 概述-2.2下載和安裝。
pip install -r requirements_py3.txt
2、修改handler 中的 logging.ini 中的自定義配置,里面包含了與日志上傳服務相關的5個參數,這和使用SDK上傳日志類似。
;替換下面5個參數
args=('your endpoint','your access_key','your secret_key', 'log_project', 'log_unit',)
3、執行example/sample_logging_handler.py 示例即可。
logging.ini 配置
在用例中自定義配置了三種handler :consoleHandler、asyncHandler、syncHandler。
1、consoleHandler的配置中class=StreamHandler,這代表會將logger 日志輸出到控制臺。
2、syncHandler 配置中的 class=handler.AsyncHandler,這代表handler 將會去使用SyncHandler 類的配置進行日志上傳,這個類使用的是同步單線程將logger 的日志上傳到云日志服務中。
3、asyncHandler配置中的 class=handler.AsyncHandler,這代表handler 將會去使用AsyncHandler 類的配置進行日志上傳,這個類使用的是異步批量多線程方式將logger 的日志上傳到云日志服務中。
用戶使用這個功能的時候,需要修改handler 中的args 配置。里面包含了與日志上傳服務相關的5個參數,這和使用SDK上傳日志類似。
;替換下面5個參數
args=('your endpoint','your access_key','your secret_key', 'log_project', 'log_unit',)
;使用環境變量
;args=(os.environ.get('LTS_ENDPOINT', '',),os.environ.get('LTS_ACCESSKEY', ''),
? os.environ.get('LTS_SECRETKEY', ''),os.environ.get('LTS_LOGPROJECT', ''),
? os.environ.get('LTS_LOGUNIT', ''))
當然如果對安全性要求較高,強烈建議不要將明文access_key 和 secret_key 寫在logging.ini配置中,代替使用系統變量存放。可使用args=(os.environ.get('LTS_ENDPOINT', '',)獲取系統變量。
[loggers]
keys=root,sync_logging,async_logging
[handlers]
keys=consoleHandler, asyncHandler,syncHandler
[formatters]
keys=consoleFormatter,ltsFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_async_logging]
level=INFO
handlers=consoleHandler,asyncHandler
qualname=async_logging
propagate=0
[logger_sync_logging]
level=INFO
handlers=consoleHandler,syncHandler
qualname=sync_logging
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=consoleFormatter
args=(sys.stdout,)
[handler_asyncHandler]
class=handler.AsyncHandler
formatter=ltsFormatter
;替換下面5個參數
args=('your endpoint','your access_key','your secret_key', 'log_project', 'log_unit',)
[handler_syncHandler]
class=handler.SyncHandler
formatter=ltsFormatter
;替換下面5個參數
args=('your endpoint','your access_key','your secret_key', 'log_project', 'log_unit',)
[formatter_consoleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
[formatter_ltsFormatter]
format=%(asctime)s - %(levelname)s - %(threadName)s - %(filename)s[line:%(lineno)d] - %(message)s
log handler 的使用示例
在完成前面logging.ini 的配置之后,就可以直接使用本服務將logger 日志直接上傳到云日志服務中去。由于定義的三個handler功能各不同,使用時也有細微差異。
示例代碼:log handler 使用(example 目錄下的 sample_logging_handler.py)
import logging.config
import time
# 加載logging.ini配置文件
logging.config.fileConfig("../handler/logging.ini")
# 獲取logger實例,異步發送logger日志
logger = logging.getLogger('async_logging')
# 獲取logger實例,同步發送logger日志
logger2 = logging.getLogger('sync_logging')
# 獲取logger實例,將日志輸出到日志控制臺
logger3 = logging.getLogger()
logger.info("log message,level:info")
logger.warning("log message,level:warning")
logger.error("log message,level:error")
try:
? result = 10 / 0 ? ? # 可能引發異常的代碼
except Exception as e:
? # 或者
logger.error("An error occurred: ", exc_info=True) # 采集異常信息
logger2.info("log2 message,level:info")
logger2.error("log2 message,level:error")
logger3.debug("log2 message,level:debug")
logger3.info("log2 message,level:info")
logger3.error("log2 message,level:error")
time.sleep(5)
logging.shutdown()
日志格式如下所示:其中__ user_agent 、__ ts 、__ message__ 是云日志服務的固定字段,其余字段是將message進行分詞處理后的字段。
__user_agent__ : lts-python-logging-handler/1.5.1
exception : {錯誤信息,此處省略} ZeroDivisionError: division by zero
file_name : sample_logging_handler.py
level : ERROR
message : An error occurred:
thread : MainThread
time : 2024-06-21,17:52:48
__ts__ : 2024-06-21 17:52:48.920
__message__ : 2024-06-21 17:52:48,920 - ERROR - MainThread - sample_logging_handler.py[line:26] - An error occurred: {錯誤信息,此處省略}
加載logging.ini配置
此操作是用于加載logging.ini 配置文件,文件處于handler 目錄下。加載這份配置才能夠使用后續功能。
logging.config.fileConfig("../handler/logging.ini")
獲取logger 實例:root
此操作是用于使用原生的logger 功能,即不將logger日志上傳到云日志服務。其中root參數可以省略。
logger = logging.getLogger()
# 下面這個格式也生效
logger = logging.getLogger('root')
# logger 使用
logger.info("log message,level:info")
獲取logger 實例:sync_logging
此操作是使用同步單線程的形式將logger日志上傳到云日志服務(同時也會輸出到控制臺),這種方式調用logger生成一條日志,就會發送一次http請求將日志上傳。這種方式簡單,但當調用頻率很高時,會出現阻塞情況,發送效率不高。
logger = logging.getLogger('sync_logging')
logger.info("sync log message 1,level:info")
logger.info("sync log message 2,level:info")
logger.info("sync log message 3,level:info")
獲取logger 實例:async_logging
此操作是使用異步批量多線程的形式將logger日志上傳到云日志服務(同時也會輸出到控制臺),這種方式調用logger生成一條日志后,會發送到一個日志累加器內,當日志累加器的日志量超過預設的大小或條數,或者等待指定時間后,日志累加器的日志會被打包成一個任務,然后開啟一個線程將這些日志一次批量發送到云日志服務。這種方式效率高,異步非阻塞,非常適合需要頻繁上傳日志的場景。
logger = logging.getLogger('async_logging')
logger.info("async log message 1,level:info")
logger.info("async log message 2,level:info")
logger.info("async log message 3,level:info")
捕獲異常信息Exception
此操作是當發送異常時,可以使用logger.error()將異常信息也進行上傳。這種方式可以有效記錄異常發生時的情況。其中需要配置exc_info=True這個參數。
try:
? result = 10 / 0
except Exception as e:
logger.error("An error occurred:" exc_info=True)
修改日志上傳的level級別
修改logging.ini 配置中對應的level為WARN 則只上傳WARN及以上級別日志
[logger_async_logging]
level=WARN
handlers=consoleHandler,asyncHandler
qualname=async_logging
propagate=0
Logging.shutdown()
此操作是關閉所有的logger,使用這個方法會關閉所有日志,除了原生的logger.getLogger()。如果使用了async_logging 這個異步上傳的handler,請在不需要使用的時候調用logging.shutdown()方法進行關閉,這樣可以有效減少資源消耗。
logging.shutdown()