Python – logging Logger & Handler Filter

Loading

測試環境為 CentOS 8 x86_64 (虛擬機)

參考文章 – https://docs.python.org/3/library/logging.html#filter-objects

使用 logging 類別,有以下 6 個物件.

Logger <- Handler <- Formatter
   |        |
   <<<<<<<<<<<<<< Filter 
  1. Logger (紀錄器) – 用來執行日誌紀錄,透過 logging.getLogger(name=None) 來生成 .
  2. Handler (處理器) – 選擇日誌的輸出地方,常用的 Handler ,生成後透過 logger.addHandler(hdlr) 把 Handler 加到 Logger .
    • StreamHandler – 透過 logging.StreamHandler(stream=None) 來生成, 將資料輸出到標準輸出 sys.stdout, sys.stderr 或是 file-like object .
    • FileHandler – 透過 logging.FileHandler(filename, mode=’a’, encoding=None, delay=False, errors=None) 來生成 ,將資料儲存成檔案.
  3. Formatter (格式器) – 顯示訊息的格式, 透過 logging.Formatter(fmt=None, datefmt=None, style=’%’, validate=True, *, defaults=None)來生成, 生成後透過 Handler.setFormatter(fmt) 把 Formatter 加到 Handler .
  4. Filter (過濾器) – 用來控制訊息的輸出內容,看是要加到 logger 或是 Handler ,當你要所有的 Handler 都使用相同的 Filter 時就在 logger 物件透過 logger.addFilter(filter) 來生成 ,想要在個別 Handler 使用時就在 Handler 物件透過 handler.addFilter(filter) 來生成 .
  5. LogRecord – 產生 Logger 時自動生成.
  6. LoggerAdapter – 沒使用過.

在官方網站說明 Filter 可以使用在 Handler 或是 Logger ,觀念應該跟 setLevel – https://benjr.tw/104370 一樣,我們可以依據使用情況設定 Filter ,當你要所有的 Handler 都使用相同的 Filter 時就在 Logger 物件設定 ,想要在個別 Handler 使用時就在 Handler 物件使用.

  1. 範例 :
    資料同時輸出到文字命令列與檔案,並使用相同的 Filter .

    [root@localhost ~]# vi logger_filter.py 
    import logging
    
    class stringFilter(logging.Filter):
        def filter(self, record):
            if record.msg.find('abc') == -1:
                return True
            return False
    
    dev_logger = logging.getLogger(__name__)
    dev_logger.setLevel(logging.DEBUG)
    
    handler1 = logging.FileHandler('test.log')
    handler2 = logging.StreamHandler()
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
    handler1.setFormatter(formatter)
    handler2.setFormatter(formatter)
    dev_logger.addHandler(handler1)
    dev_logger.addHandler(handler2)
    
    dev_logger.addFilter(stringFilter())
    
    dev_logger.debug('debug message')
    dev_logger.info('info message')
    dev_logger.warning('warning message')
    dev_logger.error('error message')
    dev_logger.critical('abc-critical message')
    

    執行結果

    [root@localhost ~]# python3 logger_filter.py 
    2022-05-31 11:07:36,767 - __main__ - DEBUG - debug message
    2022-05-31 11:07:36,767 - __main__ - INFO - info message
    2022-05-31 11:07:36,767 - __main__ - WARNING - warning message
    2022-05-31 11:07:36,767 - __main__ - ERROR - error message
    
    [root@localhost ~]# cat test.log 
    2022-05-31 11:07:36,767 - __main__ - DEBUG - debug message
    2022-05-31 11:07:36,767 - __main__ - INFO - info message
    2022-05-31 11:07:36,767 - __main__ - WARNING - warning message
    2022-05-31 11:07:36,767 - __main__ - ERROR - error message
    

    說明:
    自行定義 stringFilter 類別,主要內容是會檢查訊息是否包含 abc 字串,無才會顯示.

    class stringFilter(logging.Filter):
        def filter(self, record):
            if record.msg.find('abc') == -1:
                return True
            return False
    

    Filter 是設在 Logger 物件上,所有的 Handler 使用相同的 Filter.

    dev_logger.addFilter(stringFilter())
    
    
  2. 範例 :
    資料同時輸出到文字命令列與檔案,並使用不同的 Filter.

    [root@localhost ~]# vi lhandler_filter.py
    import logging
    
    class stringFilter1(logging.Filter):
        def filter(self, record):
            if record.msg.find('abc') == -1:
                return True
            return False
    
    class stringFilter2(logging.Filter):
        def filter(self, record):
            if record.msg.find('123') != -1:
                return True
            return False
    
    dev_logger = logging.getLogger(__name__)
    dev_logger.setLevel(logging.DEBUG)
    
    handler1 = logging.FileHandler('test.log')
    handler2 = logging.StreamHandler()
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
    handler1.setFormatter(formatter)
    handler2.setFormatter(formatter)
    dev_logger.addHandler(handler1)
    dev_logger.addHandler(handler2)
    
    handler1.addFilter(stringFilter1())
    handler2.addFilter(stringFilter2())
    
    dev_logger.debug('debug message')
    dev_logger.info('info message')
    dev_logger.warning('warning message')
    dev_logger.error('error message-123')
    dev_logger.critical('abc-critical message')
    

    執行結果

    [root@localhost ~]# python3 lhandler_filter.py 
    2022-05-31 11:14:20,779 - __main__ - ERROR - error message-123
    
    [root@localhost ~]# cat test.log
    2022-05-31 11:14:20,778 - __main__ - DEBUG - debug message
    2022-05-31 11:14:20,778 - __main__ - INFO - info message
    2022-05-31 11:14:20,779 - __main__ - WARNING - warning message
    2022-05-31 11:14:20,779 - __main__ - ERROR - error message-123
    

    說明:
    這一次自行定義了 2 個 Filter.

    stringFilter1 類別,主要內容是會檢查訊息是否包含 abc 字串,無才會顯示.

    class stringFilter1(logging.Filter):
        def filter(self, record):
            if record.msg.find('abc') == -1:
                return True
            return False
    

    stringFilter2 類別,主要內容是會檢查訊息是否包含 123 字串,有才會顯示.

    class stringFilter2(logging.Filter):
        def filter(self, record):
            if record.msg.find('123') != -1:
                return True
            return False
    

    透過個別 Handler 來設定不同 filter.

    handler1.addFilter(stringFilter1())
    handler2.addFilter(stringFilter2())
    
沒有解決問題,試試搜尋本站其他內容

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料