国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當前位置: 首頁 > news >正文

網(wǎng)站后端技術(shù)有哪些運營商大數(shù)據(jù)精準營銷獲客

網(wǎng)站后端技術(shù)有哪些,運營商大數(shù)據(jù)精準營銷獲客,國外成人做視頻網(wǎng)站有哪些,太倉建設(shè)工程網(wǎng)站Python 日志記錄:6大日志記錄庫的比較 文章目錄 Python 日志記錄:6大日志記錄庫的比較前言一些日志框架建議1. logging - 內(nèi)置的標準日志模塊默認日志記錄器自定義日志記錄器生成結(jié)構(gòu)化日志 2. Loguru - 最流行的Python第三方日志框架默認日志記錄器自定…

Python 日志記錄:6大日志記錄庫的比較

文章目錄

  • Python 日志記錄:6大日志記錄庫的比較
    • 前言
    • 一些日志框架建議
    • 1. logging - 內(nèi)置的標準日志模塊
      • 默認日志記錄器
      • 自定義日志記錄器
      • 生成結(jié)構(gòu)化日志
    • 2. Loguru - 最流行的Python第三方日志框架
      • 默認日志記錄器
      • 自定義日志記錄器
    • 3. Structlog
    • 4. Eliot
    • 5. Logbook
    • 6. Picologging
    • 最后的想法

前言

日志記錄框架是一種工具,可幫助您標準化應(yīng)用程序中的日志記錄過程。雖然某些編程語言提供內(nèi)置日志記錄模塊作為其標準庫的一部分,但大多數(shù)日志記錄框架都是第三方庫,例如logging (Python)、Log4j (Java)、 Zerolog (Go) 或 Winston (Node.js)。有時,組織會選擇開發(fā)自定義日志記錄解決方案,但這通常僅限于具有高度專業(yè)化需求的大型公司。

雖然 Python 在其標準庫中提供了強大且功能豐富的日志記錄解決方案,但第三方日志記錄生態(tài)系統(tǒng)也提供了一系列引人注目的替代方案。根據(jù)您的需求,這些外部庫可能更適合您的日志記錄需求。

因此,本文將介紹 Python 用于跟蹤應(yīng)用程序和庫行為的六大日志解決方案。我們將首先討論標準logging模塊,然后研究 Python 社區(qū)創(chuàng)建的其他五個logging frameworks。

一些日志框架建議

  • Pino (Node.js)

  • Zerolog, Zap, or Slog (Go)

  • Monolog (PHP)

  • SLF4J with Log4J2 or Logback (Java)

  • Loguru (Python)

  • Semantic Logger (Ruby)

1. logging - 內(nèi)置的標準日志模塊

默認日志記錄器

與大多數(shù)編程語言不同,Python 在其標準庫中包含了一個功能齊全的日志框架。該日志記錄解決方案有效地滿足了庫和應(yīng)用程序開發(fā)人員的需求,并包含了以下嚴重性級別:DEBUG、INFO、WARNING、ERRORCRITICAL。有了默認日志記錄器,無需任何前期設(shè)置,您就可以立即開始記錄日志。

import logginglogging.debug("A debug message")
logging.info("An info message")
logging.warning("A warning message")
logging.error("An error message")
logging.critical("A critical message")

此default(或root)記錄器在該WARNING級別運行,這意味著只有嚴重性等于或超過的記錄調(diào)用WARNING才會產(chǎn)生輸出:

WARNING:root:A warning message
ERROR:root:An error message
CRITICAL:root:A critical message

自定義日志記錄器

這種配置可確保只顯示潛在的重要信息,減少日志輸出中的噪音。不過,您也可以根據(jù)需要自定義日志級別并微調(diào)日志記錄行為。使用logging模塊的推薦方法是通過 getLogger()方法創(chuàng)建自定義日志記錄器:

import logginglogger = logging.getLogger(__name__)

一旦有了自定義記錄器,您就可以通過 logging模塊 提供的Handler(處理程序)、 Formatter(格式化器)和Filter(過濾器) 類來自定義其輸出。

  • Handlers決定輸出目的地,并可根據(jù)日志級別進行定制。一個日志記錄器還可添加多個Handlers,以便同時向不同目的地發(fā)送日志信息。

  • Formatters決定了日志記錄器產(chǎn)生的記錄的格式。然而,目前還沒有JSON、Logfmt等預(yù)定義格式。您必須結(jié)合可用的日志記錄屬性來構(gòu)建自己的格式。
    root日志記錄器的默認格式為%(levelname)s:%(name)s:%(message)s
    然而,自定義日志記錄器默認為只有%(message)s。

  • Filtershandlerlogger objects使用,用于過濾日志記錄。與日志級別相比,Filters能更好地控制哪些日志記錄應(yīng)被處理或忽略。在日志被發(fā)送到最終目的地之前,它們還能以某種方式增強或修改記錄。例如,您可以創(chuàng)建一個自定義過濾器,以刪除日志中的敏感數(shù)據(jù)。

下面是一個使用自定義日志記錄器將日志記錄到控制臺和文件的示例:

import sys
import logginglogger = logging.getLogger("example")
logger.setLevel(logging.DEBUG)# Create handlers for logging to the standard output and a file
stdoutHandler = logging.StreamHandler(stream=sys.stdout)
errHandler = logging.FileHandler("error.log")# Set the log levels on the handlers
stdoutHandler.setLevel(logging.DEBUG)
errHandler.setLevel(logging.ERROR)# Create a log format using Log Record attributes
fmt = logging.Formatter("%(name)s: %(asctime)s | %(levelname)s | %(filename)s:%(lineno)s | %(process)d >>> %(message)s"
)# Set the log format on each handler
stdoutHandler.setFormatter(fmt)
errHandler.setFormatter(fmt)# Add each handler to the Logger object
logger.addHandler(stdoutHandler)
logger.addHandler(errHandler)logger.info("Server started listening on port 8080")
logger.warning("Disk space on drive '/var/log' is running low. Consider freeing up space"
)try:raise Exception("Failed to connect to database: 'my_db'")
except Exception as e:# exc_info=True ensures that a Traceback is includedlogger.error(e, exc_info=True)

執(zhí)行上述程序時,控制臺會如期打印出以下日志信息:

example: 2023-07-23 14:42:18,599 | INFO | main.py:30 | 187901 >>> Server started listening on port 8080example: 2023-07-23 14:14:47,578 | WARNING | main.py:28 | 143936 >>> Disk space on drive '/var/log' is running low. Consider freeing up spaceexample: 2023-07-23 14:14:47,578 | ERROR | main.py:34 | 143936 >>> Failed to connect to database: 'my_db'Traceback (most recent call last):File "/home/ayo/dev/betterstack/demo/python-logging/main.py", line 32, in <module>raise Exception("Failed to connect to database: 'my_db'")
Exception: Failed to connect to database: 'my_db'

同時還創(chuàng)建了 error.log 文件,該文件應(yīng)僅包含 ERROR 日志,因為 errHandler 的最小級別已設(shè)置為 ERROR:

example: 2023-07-23 14:14:47,578 | ERROR | main.py:34 | 143936 >>> Failed to connect to database: 'my_db'
Traceback (most recent call last):File "/home/ayo/dev/betterstack/demo/python-logging/main.py", line 32, in <module>raise Exception("Failed to connect to database: 'my_db'")
Exception: Failed to connect to database: 'my_db'

生成結(jié)構(gòu)化日志

在撰寫本文時,除非執(zhí)行一些附加代碼,否則logging模塊無法生成結(jié)構(gòu)化日志。值得慶幸的是,有一種更簡單、更好的方法可以獲得結(jié)構(gòu)化輸出:python-json-logger 庫。

$ pip install python-json-logger

安裝后,您可以按以下方式使用它:

import sys
import logging
from pythonjsonlogger import jsonlogger. . .# The desired Log Record attributes must be included here, and they can be
# renamed if necessary
fmt = jsonlogger.JsonFormatter("%(name)s %(asctime)s %(levelname)s %(filename)s %(lineno)s %(process)d %(message)s",rename_fields={"levelname": "severity", "asctime": "timestamp"},
)# Set the log format on each handler
stdoutHandler.setFormatter(fmt)
errHandler.setFormatter(fmt). . .

如果用上面突出顯示的幾行修改前面的示例,執(zhí)行時將觀察到以下輸出:

{"name": "example", "filename": "main.py", "lineno": 31, "process": 179775, "message": "Server started listening on port 8080", "severity": "INFO", "timestamp": "2023-07-23 14:39:03,265"}
{"name": "example", "filename": "main.py", "lineno": 32, "process": 179775, "message": "Disk space on drive '/var/log' is running low. Consider freeing up space", "severity": "WARNING", "timestamp": "2023-07-23 14:39:03,265"}
{"name": "example", "filename": "main.py", "lineno": 38, "process": 179775, "message": "Failed to connect to database: 'my_db'", "exc_info": "Traceback (most recent call last):\n  File \"/home/ayo/dev/betterstack/demo/python-logging/main.py\", line 36, in <module>\n    raise Exception(\"Failed to connect to database: 'my_db'\")\nException: Failed to connect to database: 'my_db'", "severity": "ERROR", "timestamp": "2023-07-23 14:39:03,265"}

還可以通過 level 方法上的extra屬性在log point添加上下文數(shù)據(jù),如下所示:

logger.info("Server started listening on port 8080",extra={"python_version": 3.10, "os": "linux", "host": "fedora 38"},
)
{"name": "example", "filename": "main.py", "lineno": 31, "process": 195301, "message": "Server started listening on port 8080", "python_version": 3.1, "os": "linux", "host": "fedora 38", "severity": "INFO", "timestamp": "2023-07-23 14:45:42,472"}

正如您所看到的,built-in的 logging module 能夠滿足各種日志記錄需求,并且具有可擴展性。不過,它的初始配置和自定義可能比較麻煩,因為在開始有效記錄之前,你必須創(chuàng)建和配置loggers、handlersformatters。

請參閱我們的 Python 日志指南和官方文檔,進一步了解日志模塊的功能和最佳實踐。

2. Loguru - 最流行的Python第三方日志框架

Loguru 是最流行的 Python 第三方日志框架,在撰寫本文時已在 GitHub 上獲得超過 15k顆星。它旨在通過預(yù)配置日志記錄器來簡化日志記錄過程,并通過其 add() 方法使自定義日志記錄器變得非常容易。

默認日志記錄器

使用 Loguru 啟動日志記錄非常簡單,只需安裝軟件包并導(dǎo)入,然后調(diào)用其級別方法即可,如下所示:

$ pip install loguru
from loguru import loggerlogger.trace("Executing program")
logger.debug("Processing data...")
logger.info("Server started successfully.")
logger.success("Data processing completed successfully.")
logger.warning("Invalid configuration detected.")
logger.error("Failed to connect to the database.")
logger.critical("Unexpected system error occurred. Shutting down.")

默認配置將半結(jié)構(gòu)化和彩色化的輸出記錄到標準錯誤。它還默認將 DEBUG 作為最低級別,這也解釋了為什么 TRACE 輸出不會被記錄。

在這里插入圖片描述

自定義日志記錄器

通過 add() 函數(shù),可以輕松定制 Loguru 的內(nèi)部工作機制,該函數(shù)可處理從日志格式化到日志目的地設(shè)置等一切操作。例如,您可以將日志記錄到標準輸出,將默認級別更改為 INFO,并使用下面的配置將日志格式化為 JSON:

from loguru import logger
import syslogger.remove(0) # remove the default handler configuration
logger.add(sys.stdout, level="INFO", serialize=True). . .
{"text": "2023-07-17 15:26:21.597 | INFO     | __main__:<module>:9 - Server started successfully.\n", "record": {"elapsed": {"repr": "0:00:00.006401", "seconds": 0.006401}, "exception": null, "extra": {}, "file": {"name": "main.py", "path": "/home/ayo/dev/betterstack/demo/python-logging/main.py"}, "function": "<module>", "level": {"icon": "??", "name": "INFO", "no": 20}, "line": 9, "message": "Server started successfully.", "module": "main", "name": "__main__", "process": {"id": 3852028, "name": "MainProcess"}, "thread": {"id": 140653618894656, "name": "MainThread"}, "time": {"repr": "2023-07-17 15:26:21.597156+02:00", "timestamp": 1689600381.597156}}}

Loguru 生成的默認 JSON 輸出可能相當冗長,但使用類似這樣的自定義函數(shù)可以輕松地將日志信息序列化:

from loguru import logger
import sys
import jsondef serialize(record):subset = {"timestamp": record["time"].timestamp(),"message": record["message"],"level": record["level"].name,"file": record["file"].name,"context": record["extra"],}return json.dumps(subset)def patching(record):record["extra"]["serialized"] = serialize(record)logger.remove(0)logger = logger.patch(patching)
logger.add(sys.stderr, format="{extra[serialized]}")logger.bind(user_id="USR-1243", doc_id="DOC-2348").debug("Processing document")
{"timestamp": 1689601339.628792, "message": "Processing document", "level": "DEBUG", "file": "main.py", "context": {"user_id": "USR-1243", "doc_id": "DOC-2348"}}

Loguru 也完全支持上下文日志記錄。您已經(jīng)看到上面的 bind() 方法,它允許在 log point 添加上下文數(shù)據(jù)。

您還可以使用 bind() 方法來創(chuàng)建子記錄器來記錄共享相同上下文的記錄:

child = logger.bind(user_id="USR-1243", doc_id="DOC-2348")
child.debug("Processing document")
child.warning("Invalid configuration detected. Falling back to defaults")
child.success("Document processed successfully")

請注意,user_id 和 doc_id 字段出現(xiàn)在所有三條記錄中:

{"timestamp": 1689601518.884659, "message": "Processing document", "level": "DEBUG", "file": "main.py", "context": {"user_id": "USR-1243", "doc_id": "DOC-2348"}}{"timestamp": 1689601518.884706, "message": "Invalid configuration detected. Falling back to defaults", "level": "WARNING", "file": "main.py", "context": {"user_id": "USR-1243", "doc_id": "DOC-2348"}}{"timestamp": 1689601518.884729, "message": "Document processed successfully", "level": "SUCCESS", "file": "main.py", "context": {"user_id": "USR-1243", "doc_id": "DOC-2348"}}

另一方面,它的 contextualize() 方法可以輕松地為特定范圍或上下文中的所有日志記錄添加上下文字段。例如,下面的代碼段演示了將唯一的請求 ID 屬性添加到因該請求而創(chuàng)建的所有日志中:

from loguru import logger
import uuiddef logging_middleware(get_response):def middleware(request):request_id = str(uuid.uuid4())with logger.contextualize(request_id=request_id):response = get_response(request)response["X-Request-ID"] = request_idreturn responsereturn middleware

Loguru 還支持優(yōu)秀日志框架所應(yīng)具備的所有功能,如通過自動旋轉(zhuǎn)和壓縮將日志記錄到文件、自定義日志級別、異常處理、同時記錄到多個目的地等。它還為來自標準logging模塊的用戶提供了遷移指南。

請參閱Loguru 官方文檔和我們專用 Loguru 指南,了解有關(guān)使用 Loguru 為 Python 應(yīng)用程序創(chuàng)建production-ready日志設(shè)置的更多信息。

3. Structlog

Structlog 是一個日志庫,專門用于生成 JSON 或 Logfmt 格式的結(jié)構(gòu)化輸出。它支持為開發(fā)環(huán)境提供彩色、美觀的控制臺輸出,也允許完全自定義日志格式,以滿足不同需求。你可以使用下面的命令安裝 Structlog 軟件包:

$ pip install structlog

Structlog 最簡單的用法是調(diào)用 get_logger()方法,然后在生成的logger上使用任何level方法:

import structloglogger = structlog.get_logger()logger.debug("Database query executed in 0.025 seconds")
logger.info("Processing file 'data.csv' completed. 1000 records were imported",file="data.csv",elapsed_ms=300,num_records=1000,
)
logger.warning("Unable to load configuration file 'config.ini'. Using default settings instead",file="config.ini",
)try:1 / 0
except ZeroDivisionError as e:logger.exception("Division by zero error occurred during calculation. Check the input values",exc_info=e,)
logger.critical("Application crashed due to an unhandled exception")

在這里插入圖片描述

Structlog 日志記錄器的默認配置對開發(fā)環(huán)境非常友好。輸出是彩色的,任何包含的上下文數(shù)據(jù)都以 key=value 對的形式出現(xiàn)。此外,tracebacks的格式和organized都很整齊,因此更容易發(fā)現(xiàn)問題的原因。

Structlog 的獨特之處在于,它不會按levels去過濾記錄。這就是為什么上面所有的levels都被寫入控制臺的原因。不過,通過 configure() 方法配置默認級別也很簡單,如下所示:

import structlog
import loggingstructlog.configure(wrapper_class=structlog.make_filtering_bound_logger(logging.INFO))

Structlog 與標準logging模塊中的日志級別兼容,因此可以使用上述 logging.INFO 常量。你也可以直接使用與級別相關(guān)的數(shù)字:

structlog.configure(wrapper_class=structlog.make_filtering_bound_logger(20))

get_logger()函數(shù)返回的日志記錄器稱為綁定日志記錄器,因為您可以將上下文值與之綁定。一旦綁定了key/value pairs,它們將包含在日志記錄器生成的每個后續(xù)日志條目中。

import structlog
import platformlogger = structlog.get_logger()logger = logger.bind(python_version=platform.python_version(), os="linux"). . .
2023-07-23 17:20:10 [debug] Database query executed in 0.025 seconds os=linux python_version=3.11.42023-07-23 17:20:10 [info] Processing file 'data.csv' completed. 1000 records were imported elapsed_ms=300 file=data.csv num_records=1000 os=linux python_version=3.11.4

綁定日志記錄器還包括一系列處理器函數(shù),可在日志記錄通過日志記錄管道時對日志記錄進行轉(zhuǎn)換和豐富。例如,您可以使用以下配置以 JSON 格式記錄日志:

import structlog
import platformstructlog.configure(processors=[structlog.processors.TimeStamper(fmt="iso"),structlog.processors.add_log_level,structlog.processors.JSONRenderer(),]
). . .

每個處理器都按照聲明順序執(zhí)行,因此首先調(diào)用 TimeStamper() 為每個條目添加 ISO-8601 格式的時間戳,然后通過 add_log_level 添加嚴重級別,最后調(diào)用 JSONRenderer() 將整個記錄序列化為 JSON 格式。對程序進行高亮顯示的修改后,您將看到以下輸出:

{"python_version": "3.11.4", "os": "linux", "event": "Database query executed in 0.025 seconds", "timestamp": "2023-07-23T15:32:21.590688Z", "level": "debug"}{"python_version": "3.11.4", "os": "linux", "file": "data.csv", "elapsed_ms": 300, "num_records": 1000, "event": "Processing file 'data.csv' completed. 1000 records were imported", "timestamp": "2023-07-23T15:32:21.590720Z", "level": "info"}

Structlog 能做的另一件很酷的事情是自動格式化tracebacks,使其也以 JSON 格式序列化。你只需要像這樣使用 dict_tracebacks 處理器:

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

每當記錄異常情況時,你會發(fā)現(xiàn)記錄中的異常情況信息格式非常豐富,便于在日志管理服務(wù)中進行分析。

{"python_version": "3.11.4", "os": "linux", "event": "Division by zero error occurred during calculation. Check the input values", "timestamp": "2023-07-23T16:07:50.127241Z", "level": "error", "exception": [{"exc_type": "ZeroDivisionError", "exc_value": "division by zero", "syntax_error": null, "is_cause": false, "frames": [{"filename": "/home/ayo/dev/betterstack/demo/python-logging/main.py", "lineno": 32, "name": "<module>", "line": "", "locals": {"__name__": "__main__", "__doc__": "None", "__package__": "None", "__loader__": "<_frozen_importlib_external.SourceFileLoader object at 0x7fdb22df2ed0>", "__spec__": "None", "__annotations__": "{}", "__builtins__": "<module 'builtins' (built-in)>", "__file__": "/home/ayo/dev/betterstack/demo/python-logging/main.py", "__cached__": "None", "structlog": "\"<module 'structlog' from '/home/ayo/.local/lib/python3.11/site-packages/structlo\"+15", "platform": "<module 'platform' from '/usr/lib64/python3.11/platform.py'>", "logging": "<module 'logging' from '/usr/lib64/python3.11/logging/__init__.py'>", "logger": "\"<BoundLoggerFilteringAtDebug(context={'python_version': '3.11.4', 'os': 'linux'}\"+249", "e": "ZeroDivisionError('division by zero')"}}]}]}

這里只介紹了 Structlog 所提供的常用功能,因此請務(wù)必查看其文檔以了解更多信息。

4. Eliot

Eliot 是一種獨特的 Python 日志解決方案,它不僅能記錄程序中發(fā)生的事件,還能輸出導(dǎo)致事件發(fā)生的行為因果鏈。使用 pip 安裝 Eliot 的方法如下:

$ pip install eliot

Eliot 的一個關(guān)鍵概念是 “動作”(action),它代表任何可以開始并成功完成或因異常而失敗的任務(wù)。當你啟動一個動作時,會產(chǎn)生兩條日志記錄:一條用來表示action的開始,另一條用來表示action的成功或失敗。演示此模型的最佳方式是舉例說明:

import sys
from eliot import start_action, to_fileto_file(sys.stdout)def calculate(x, y):with start_action(action_type="multiply"):return x * ycalculate(10, 5)

這里使用start_action函數(shù)來表示一個新action的開始。一旦執(zhí)行calculate()函數(shù),兩個日志就會被發(fā)送到to_file()配置的目的地:

{"action_status": "started", "timestamp": 1690213156.7701144, "task_uuid": "a9a47808-15a9-439b-8335-b88d50013f75", "action_type": "multiply", "task_level": [1]}{"action_status": "succeeded", "timestamp": 1690213156.7701554, "task_uuid": "a9a47808-15a9-439b-8335-b88d50013f75", "action_type": "multiply", "task_level": [2]}

Eliot 默認生成結(jié)構(gòu)化的 JSON 輸出,其中包括以下記錄:

  • task_uuid: 生成消息的唯一任務(wù)標識符。
  • action_status: 表示action的狀態(tài)。
  • timestamp: 信息的 UNIX 時間戳。
  • task_level: 信息在actions樹中的位置。
  • action_type: 提供的 action_type 參數(shù)。

您可以向action的開始消息和成功消息添加其他字段,如下所示:

def calculate(x, y):# additional fields here are added to the start message of the action alonewith start_action(action_type="multiply", x=x, y=y) as action:result = x * y# fields added here show up only in the success message of the actionaction.add_success_fields(result=result)return result
{"x": 10, "y": 5, "action_status": "started", "timestamp": 1690213820.4083755, "task_uuid": "09df3632-96d2-4dd8-b782-1926cd87ccc9", "action_type": "multiply", "task_level": [1]}{"result": 50, "action_status": "succeeded", "timestamp": 1690213820.4084144, "task_uuid": "09df3632-96d2-4dd8-b782-1926cd87ccc9", "action_type": "multiply", "task_level": [2]}

另一種記錄函數(shù)的輸入和結(jié)果的方法是通過log_call裝飾器:

from eliot import log_call, to_fileto_file(sys.stdout)@log_call
def calculate(x, y):return x * ycalculate(10, 5)

在這種情況下,action_type 將是模塊和函數(shù)名稱的連接,但其余字段將與之前相同:

{"x": 10, "y": 5, "action_status": "started", "timestamp": 1690214038.799868, "task_uuid": "2c78b304-12a1-474a-8b95-e80deadb8dde", "action_type": "__main__.calculate", "task_level": [1]}{"result": 50, "action_status": "succeeded", "timestamp": 1690214038.7999015, "task_uuid": "2c78b304-12a1-474a-8b95-e80deadb8dde", "action_type": "__main__.calculate", "task_level": [2]}

您可以通過更改 action_type 字段并排除某些參數(shù)或結(jié)果來自定義 log_call 裝飾器的行為:

@log_call(action_type="CALC", include_args=["x"], include_result=False)

如果在某個action的上下文中檢測到uncaught exception,該操作將被標記為失敗,并將記錄一條異常消息,而不是成功消息:

import sys
from eliot import log_call, to_fileto_file(sys.stdout)@log_call
def calculate(x, y):return x / ytry:calculate(1, 0)
except ZeroDivisionError as e:print("division by zero detected")

您現(xiàn)在看到的不是成功信息,而是一條exception信息,并附有reason

{"x": 1, "y": 0, "action_status": "started", "timestamp": 1690215830.1103916, "task_uuid": "f267b0f5-8c07-4828-a973-0a8a273f272d", "action_type": "__main__.calculate", "task_level": [1]}{"exception": "builtins.ZeroDivisionError", "reason": "division by zero", "action_status": "failed", "timestamp": 1690215830.1104264, "task_uuid": "f267b0f5-8c07-4828-a973-0a8a273f272d", "action_type": "__main__.calculate", "task_level": [2]}

當您需要在action的上下文中記錄獨立的消息時,可以使用log方法,如下所示:

def calculate(x, y):with start_action(action_type="multiply") as ctx:ctx.log(message_type="mymsg", msg="a standalone message")return x * y
{"msg": "a standalone message", "timestamp": 1690217318.2063951, "task_uuid": "500b06e6-c0ba-42b4-9d6c-466ea3f1634d", "task_level": [2], "message_type": "mymsg"}

Eliot沒有 log levels 的概念,因此只能在需要時手動添加level字段:

def calculate(x, y):with start_action(action_type="multiply", level="INFO") as ctx:ctx.log(message_type="mymsg", msg="a standalone message", level="INFO")return x * y

Eliot 的另一項出色功能是通過 eliot-tree 命令行工具實現(xiàn)日志可視化。

$ pip install eliot-tree

安裝 eliot -tree 后,您可以將 Eliot 生成的 JSON 日志通過管道傳輸?shù)矫?#xff0c;如下所示:

$ python main.py | eliot-tree

在這里插入圖片描述

如果你將日志記錄到文件,可以將這個文件作為參數(shù)傳遞給工具:

$ eliot-tree <file>

在這里插入圖片描述

Eliot的內(nèi)容遠不止于此,因此請務(wù)必查看其文檔以了解更多信息。

5. Logbook

Logbook 自稱是 Python 標準庫logging模塊的酷炫替代品,其目的是讓日志記錄變得有趣。你可以使用以下命令將其安裝到你的項目中:

$ pip install logbook

開始使用 Logbook 也非常簡單:

import sys
import logbooklogger = logbook.Logger(__name__)handler = logbook.StreamHandler(sys.stdout, level="INFO")
handler.push_application()logger.info("Successfully connected to the database 'my_db' on host 'ubuntu'")logger.warning("Detected suspicious activity from IP address: 111.222.333.444")
[2023-07-24 21:41:50.932575] INFO: __main__: Successfully connected to the database 'my_db' on host 'ubuntu'[2023-07-24 21:41:50.932623] WARNING: __main__: Detected suspicious activity from IP address: 111.222.333.444

如上圖所示,logbook.Logger 方法用于創(chuàng)建一個新的 logger channel。該 logger provides 提供了對 info()warning() 等級別方法的訪問,用于寫入日志信息。支持logging模塊中的所有日志levels,并增加了介于 INFOWARNING 之間的 NOTICE 級別。

Logbook 還使用Handler概念來確定日志的目的地和格式。StreamHandler 類可將日志發(fā)送到任何輸出流(本例中為標準output),其他處理程序可將日志發(fā)送到文件、Syslog、Redis、Slack 等。

不過,與標準logging模塊不同的是,我們不鼓勵你直接在日志記錄器上注冊handlers。相反,你應(yīng)該分別通過 push_application()、push_thread()push_greenlet() 方法將處理程序綁定到process、thread或 greenlet stack中。相應(yīng)的 pop_application()、pop_thread()pop_greenlet() 方法用于取消處理程序的注冊:

handler = MyHandler()
handler.push_application()
# everything logged here here goes to that handler
handler.pop_application()

您還可以在 with-block 的持續(xù)時間內(nèi)綁定一個handler。這樣可以確保在塊內(nèi)創(chuàng)建的日志只發(fā)送給指定的handler:

with handler.applicationbound():logger.info(...)with handler.threadbound():logger.info(...)with handler.greenletbound():logger.info(...)

日志格式化也是通過handlers完成的。為此,每個處理程序都有一個 format_string 屬性,它接受 LogRecord 類的屬性:

import sys
import logbooklogger = logbook.Logger(__name__)handler = logbook.StreamHandler(sys.stdout, level="INFO")
handler.format_string = "{record.channel} | {record.level_name} | {record.message}"
handler.push_application()logger.info("Successfully connected to the database 'my_db' on host 'ubuntu'")logger.warning("Detected suspicious activity from IP address: 111.222.333.444")
__main__ | INFO | Successfully connected to the database 'my_db' on host 'ubuntu'
__main__ | WARNING | Detected suspicious activity from IP address: 111.222.333.444

遺憾的是,Logbook 的任何內(nèi)置處理程序都不支持結(jié)構(gòu)化日志記錄。您必須通過自定義處理程序自行實現(xiàn)。有關(guān)詳細信息,請參閱 Logbook 文檔。

6. Picologging

Mirosoft 的 Picologging 庫是 Python 日志生態(tài)系統(tǒng)的一個相對較新的補充。如其 GitHub Readme 所述,它被定位為標準日志模塊的高性能直接替代品,速度可顯著提高 4-10 倍。要將其集成到你的項目中,你可以用以下命令安裝它:

$ pip install picologging

Picologging 與 Python 中的logging模塊共享相同的熟悉的 API,并且使用相同的日志記錄屬性進行格式化:

import sys
import picologging as logginglogger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)stdout_handler = logging.StreamHandler(sys.stdout)
fmt = logging.Formatter("%(name)s: %(asctime)s | %(levelname)s | %(process)d >>> %(message)s"
)stdout_handler.setFormatter(fmt)
logger.addHandler(stdout_handler)logger.info("Successfully connected to the database '%s' on host '%s'", "my_db", "ubuntu20.04"
)logger.warning("Detected suspicious activity from IP address: %s", "111.222.333.444")
__main__: 2023-07-24 05:46:38,-2046715687 | INFO | 795975 >>> Successfully connected to the database 'my_db' on host 'ubuntu20.04'
__main__: 2023-07-24 05:46:38,-2046715687 | WARNING | 795975 >>> Detected suspicious activity from IP address: 111.222.333.444

Picologging 的文檔強調(diào),它目前還處于早期開發(fā)階段,因此應(yīng)暫緩在生產(chǎn)中使用。不過,根據(jù)這些benchmarks,Picologging 在提高標準日志模塊的性能方面已經(jīng)顯示出了一定的前景。有關(guān)其功能和限制的更多信息,請參閱文檔。

最后的想法

在 Python 中使用日志記錄時,我們的主要推薦是使用 Loguru,因為它具有令人印象深刻的功能和用戶友好的 API。不過,熟悉built-in logging 模塊也很重要,因為它仍然是一個功能強大、使用廣泛的解決方案。

Structlog 是另一個值得考慮的強大選項,Eliot 也可能是一個不錯的選擇,只要它缺乏日志級別并不是您的用例的主要問題。另一方面,Picologging 目前還處于早期開發(fā)階段,而 Logbook 缺乏對結(jié)構(gòu)化日志記錄的原生支持,因此不太適合在生產(chǎn)環(huán)境中進行日志記錄。

http://m.aloenet.com.cn/news/39597.html

相關(guān)文章:

  • 做網(wǎng)站找誰百度服務(wù)中心投訴
  • 網(wǎng)站的思維導(dǎo)圖怎么做線上怎么做推廣和宣傳
  • 做app推廣上哪些網(wǎng)站嗎2022年今天新聞聯(lián)播
  • 服務(wù)周到的做網(wǎng)站自媒體軟文發(fā)布平臺
  • 織夢手機網(wǎng)站怎么安裝教程視頻在線網(wǎng)絡(luò)培訓(xùn)平臺
  • 河北網(wǎng)站制作網(wǎng)絡(luò)營銷與管理
  • 怎么做網(wǎng)站免費常用的網(wǎng)絡(luò)營銷方法有哪些
  • 誰知道蘇州溪城水處理網(wǎng)站誰做的今日短新聞20條
  • 020網(wǎng)站建設(shè)專業(yè)網(wǎng)站建設(shè)公司
  • 重慶網(wǎng)站建設(shè)排名武漢seo首頁
  • 網(wǎng)站負責人辦理幕布或站點拍照重要新聞今天8條新聞
  • 用html制作網(wǎng)站代碼百家號關(guān)鍵詞排名優(yōu)化
  • android安裝教程seo診斷書
  • 499全包網(wǎng)站建設(shè)東莞做網(wǎng)頁建站公司
  • 企業(yè)免費網(wǎng)站優(yōu)化方案百度瀏覽器手機版
  • 做倫理電影網(wǎng)站百度推廣關(guān)鍵詞質(zhì)量度
  • 杭州網(wǎng)站建設(shè)哪家好seo深圳培訓(xùn)班
  • 北京道路建設(shè)在什么網(wǎng)站查詢網(wǎng)站推廣的軟件
  • 機械網(wǎng)站建設(shè)哪家好怎么樣在百度上推廣自己的產(chǎn)品
  • 做網(wǎng)站怎么收集資料太原免費網(wǎng)站建站模板
  • 網(wǎng)站正常打開速度慢semi
  • 單頁網(wǎng)站對攻擊的好處如何做好互聯(lián)網(wǎng)營銷
  • 警惕成人網(wǎng)站免費看手機引流推廣接單
  • 做網(wǎng)站所用的技術(shù)推廣普通話的宣傳語
  • 國內(nèi)網(wǎng)站開發(fā)短視頻精準獲客系統(tǒng)
  • 品牌專業(yè)建設(shè)網(wǎng)站常見的搜索引擎
  • 在哪能學(xué)到網(wǎng)站建設(shè)專業(yè)seo推廣是做什么
  • 做植物提取物好的推廣網(wǎng)站seo自動優(yōu)化軟件下載
  • 校園網(wǎng)站規(guī)劃與建設(shè)工具大全
  • 網(wǎng)站建設(shè)app開發(fā)合同范本百度普通下載