結構化日誌在現代軟體開發中扮演著重要的角色,能幫助開發者更有效地追蹤程式行為、診斷問題和分析系統效能。Structlog 作為 Python 的結構化日誌函式庫,提供豐富的功能和靈活的組態選項,讓日誌記錄更具結構性和可讀性。本文將探討 Structlog 的使用方法,從安裝到進階設定,帶領讀者逐步掌握這個強大的日誌工具。不同於 Python 內建的 logging 模組,Structlog 更注重日誌的結構化和上下文資訊,方便後續的分析和處理。透過結合不同的處理器,可以輕鬆地新增時間戳記、日誌等級、程式碼位置等資訊,並支援 JSON 等格式輸出,方便與其他日誌系統整合。此外,Structlog 的設計也考慮了效能和擴充性,可以根據專案需求進行客製化組態,提升日誌管理的效率。

使用 Structlog 進行記錄

結構化日誌(Structlog)是一個強大且靈活的 Python 日誌記錄函式庫,能夠幫助開發者更好地管理和檢視應用程式的日誌。透過結構化的日誌格式,開發者可以更容易地搜尋、過濾和分析日誌資料。以下是如何在 Python 專案中安裝和組態 Structlog 的詳細。

安裝 Structlog

首先,開啟你的終端機或命令提示字元,並執行以下命令來安裝 Structlog:

python -m pip install structlog

如果你希望在終端機中看到更美觀的異常訊息,可以額外安裝 Rich 或 better-exceptions。Structlog 的官方檔案中使用了 Rich 來顯示輸出。此外,如果你是 Windows 使用者,建議安裝 Colorama 來增加顏色輸出。

pip install rich
pip install colorama

Structlog 的日誌等級

Structlog 使用與 Python 標準日誌模組相同的日誌等級,包括 debuginfowarningerrorcritical。這些等級在呼叫 logger 方法時會被應用。

基本使用範例

在 Python IDE 中建立一個新檔案 hello_structlog.py,並輸入以下程式碼:

import structlog

logger = structlog.get_logger()
logger.info("Hello %s", "Mike", key=12, my_list=[5, 6, 7])

這段程式碼會匯入 Structlog 並透過 get_logger() 方法取得 logger 物件。注意,在 Structlog 中使用的是下劃線命名風格,而 Python 標準日誌模組則使用駝峰命名風格。

執行這段程式碼後,你會在終端機中看到結構化的日誌輸出:

2024-05-07 21:21:31 [info ] Hello Mike key=12 my_list=[5, 6, 7]

設定日誌等級

如果你想設定 Structlog 的日誌等級,可以匯入 Python 標準的 logging 模組並結合 make_filtering_bound_logger() 方法來組態。以下是如何設定日誌等級的範例:

設定日誌等級範例

建立一個新檔案 structlog_set_level.py,並輸入以下程式碼:

import logging
import structlog

structlog.configure(
    wrapper_class=structlog.make_filtering_bound_logger(logging.INFO)
)
logger = structlog.get_logger()
logger.debug("This is a debug message")
logger.info("Hello %s", "Mike", key=12, my_list=[5, 6, 7])

這段程式碼會設定日誌等級為 INFO,這意味著當你嘗試記錄一條 debug 訊息時,它將被忽略且不會被輸出。唯一會看到的是 info 訊息。

日誌格式化

格式化日誌對於稽核追蹤或除錯非常重要。Structlog 提供了一個 processors 清單來組態格式化方式。以下是如何格式化日誌的範例:

日誌格式化範例

建立一個新檔案 formatting.py,並輸入以下程式碼:

import logging
import structlog

structlog.configure(
    processors=[
        structlog.processors.add_log_level,
        structlog.dev.ConsoleRenderer(),
    ],
    wrapper_class=structlog.make_filtering_bound_logger(logging.INFO)
)
logger = structlog.get_logger()
logger.info("This is an info message")

這段程式碼會將日誌等級新增到日誌訊息中,並使用 ConsoleRenderer() 作為預設的日誌處理器。執行這段程式碼後,你會在終端機中看到以下輸出:

[info ] This is an info message

新增時間戳記

時間戳記對於追蹤事件發生的時間非常重要。Structlog 提供了一個 TimeStamper() 函式來新增時間戳記。以下是如何新增時間戳記的範例:

新增時間戳記範例

建立一個新檔案 formatting_timestamp.py,並輸入以下程式碼:

import logging
import structlog

structlog.configure(
    processors=[
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.add_log_level,
        structlog.dev.ConsoleRenderer(),
    ],
    wrapper_class=structlog.make_filtering_bound_logger(logging.INFO)
)
logger = structlog.get_logger()
logger.info("This is an info message")

這段程式碼會將 ISO 格式的時間戳記新增到日誌訊息中。執行這段程式碼後,你會在終端機中看到以下輸出:

2024-04-04T15:43:02.653557Z [info ] This is an info message

如果你不喜歡這種格式的時間戳記,可以將其替換為 %Y-%m-%d %H:%M:%S 或自定義其他格式。

序列化為 JSON

將日誌序列化為 JSON 可以使其更容易被其他服務(如 DataDog)消費。Structlog 提供了一個 JSONRenderer() 處理器來實作這一功能。以下是如何序列化為 JSON 的範例:

序列化為 JSON 的範例

建立一個新檔案 serializing_json.py,並輸入以下程式碼:

import logging
import structlog

structlog.configure(
    processors=[
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.add_log_level,
        structlog.processors.JSONRenderer(),
    ],
    wrapper_class=structlog.make_filtering_bound_logger(logging.INFO)
)
logger = structlog.get_logger()
logger.info("This is an info message")

這段程式碼會將日誌訊息序列化為 JSON 格式。執行這段程式碼後,你會在終端機中看到 JSON 格式的輸出。

########## 小節解密:

  • 應用程式:表示需要進行記錄操作的應用程式。
  • StructLog 組態:表示對StructLog進行組態設定。
  • 設定 Processors:組態處理器用於對記錄進行處理。
  • 設定 Wrapper Class:組態包裝器類別以進行過濾。
  • 新增 Log Level:將記錄級別新增到記錄訊息中。
  • 新增 Timestamp:為記錄訊息新增時間戳。
  • 設定 JSON Renderer:將記錄訊息序列化為JSON格式。
  • Filtering Logger:過濾記錄訊息以符合設定的級別。
  • Log Message:處理後的記錄訊息。
  • JSON Format Log:JSON格式的記錄訊息。
  • Terminal Output:最終輸出到終端或其他目標的記錄訊息。

透過此圖示可清晰地瞭解結構化日誌處理流程及其主要組成部分之間的邏輯關係及其互動方式。

次段落標題:## 函式介紹與實際操作演練:struct log 基本操作與應用展示
次段落標題:##### StructLog 日誌結構概覽

玄貓根據多年的經驗總結出了 StructLog 的一些基本要素:

處理器 (Processors) 處理器是對每條記錄進行特定操作的一系列函式或類別 ,它們能夠改變、新增或移除記錄中的特定資料專案。例如:

加入時間戳記:TimeStamper 函式是處理器之一,能夠向每條記錄中新增時間戳記, ```python import logging import structlog

structlog.configure(
    processors=[
        structlog.processors.TimeStamper(fmt="iso"),
        ]
    )

logger = structlog.get_logger()
logger.info("This is an info message")

```

次段落標題:### 基本操作演練(1)

第一步:環境設定

首先確認 Python 已經正確安裝於環境當中。

接著開啟終端機進行相關指令操作:

接著下載struct log套件:

pip install struct log

接著可以下載第三方套件:coloramarich

pip install colorama rich

最後確認已經正常下載完成:

image

次段落標題:### 基本操作演練(2)

第二步:簡易操作

開啟Python IDE , 建立名稱為 hello_struct log.py 的檔案。

並在其中輸入以下內容:

import logging

def main():
   logger = logging.getLogger(__name__)
   logger.setLevel(logging.DEBUG)
   # create console handler and set level to debug

   ch = logging.StreamHandler()
   ch.setLevel(logging.DEBUG)

   # create formatter

   formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# add formatter to ch

   ch.setFormatter(formatter)

# add ch to logger

   logger.addHandler(ch)

# 'application' code

   logger.debug('debug message')
   logger.info('info message')
   logger.warning('warn message')
   logger.error('error message')
   logger.critical('critical message')

if __name__ == '__main__':
   main()

完成後存檔並執行:

image


次段落標題:### 基本操作演練(3)

第三步:進階操作

接著我們將進行進階操作 :

建立名稱為 formatting_timestamp.py 的檔案 :


import logging

def main():
   logger = logging.getLogger(__name__)
   logger.setLevel(logging.DEBUG)
   # create console handler and set level to debug

   ch = logging.StreamHandler()
   ch.setLevel(logging.DEBUG)

   # create formatter

   formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# add formatter to ch

   ch.setFormatter(formatter)

# add ch to logger

   logger.addHandler(ch)

# 'application' code

   logger.debug('debug message')
   logger.info('info message')
   logger.warning('warn message')
   logger.error('error message')
   logger.critical('critical message')

if __name__ == '__main__':
   main()

完成後存檔並執行 :

image

+++++ python/structure_log.md