日志

BentoML 提供内置的日志系统,用于全面了解 BentoML 服务的运行情况。它实现了 OpenTelemetry 标准,以在整个 HTTP 调用栈中传播关键信息,用于详细的调试和分析。

本文档提供了在 BentoML 中配置日志的指南,包括管理服务器端日志以及将 BentoML 作为库使用时的自定义日志配置。

服务器日志

BentoML 默认启用服务器日志。服务启动后,发送到服务器的每个请求都会记录详细信息。BentoML 对日志进行结构化处理,以提供每个请求的清晰简洁概览,格式如下:

timestamp [LEVEL] [component] ClientIP:ClientPort (scheme,method,path,type,length) (status,type,length) Latency (trace,span,sampled,service.name)

由 BentoML 处理的请求的日志消息示例可能如下所示:

2024-04-13T02:03:49+0000 [INFO] [entry_service:Summarization:1] 44.xxx.xxx.104:7181 (scheme=http,method=GET,path=/docs.json,type=,length=) (status=200,type=application/json,length=5543) 1.972ms (trace=7589d361df3e8ad3f0a71acb44d150be,span=07ef3bc1685d067c,sampled=0,service.name=Summarization)

此日志条目提供了关于请求的详细信息,包括客户端 IP 和端口、请求方法、路径、负载类型和长度、响应状态、响应内容类型和长度、请求延迟以及 OpenTelemetry 标识符。

BentoML 的日志系统与 OpenTelemetry 标准完全兼容。服务器日志包含多个 OpenTelemetry 参数,这些参数有助于将日志关联回特定的请求或操作。

  • trace: 标识一个 trace,它由一个或多个 span 组成,代表流经多个服务的单个请求。详情请参阅 Traces

  • span: 标识 trace 中的单个 span。每个 span 代表 trace 中的一个特定操作或工作单元,例如单个 HTTP 请求。详情请参阅 Spaces

  • sampled: 指示 trace 是否正在被采样,即是否应该记录 trace 数据。如果启用采样(通常用 1 表示已采样,0 表示未采样),则只捕获 trace 的一个子集,这有助于管理数据量并减少性能开销。详情请参阅 Sampling

配置日志

您可以在服务定义中通过使用 logging 参数在 @bentoml.service 装饰器中配置服务器日志。

import bentoml

@bentoml.service(logging={
    "access": {
        "enabled": True,
        "request_content_length": True,
        "request_content_type": True,
        "response_content_length": True,
        "response_content_type": True,
        "skip_paths": ["/metrics", "/healthz", "/livez", "/readyz"],
        "format": {
            "trace_id": "032x",
            "span_id": "016x"
        }
    }
})
class MyService:
    # Service implementation

可用于控制记录哪些数据以及如何格式化的日志参数:

  • enabled: 启用或禁用日志记录。

  • request_content_length: 记录请求体的大小。

  • request_content_type: 记录请求的内容类型。

  • response_content_length: 记录响应体的大小。

  • response_content_type: 记录响应的内容类型。

  • skip_paths: 指定应从日志记录中排除的路由路径。

  • format: 自定义 OpenTelemetry trace 标识符的日志格式。

    • trace_id: 以指定格式记录 trace 标识符,例如 032x

    • span_id: 以指定格式记录 span 标识符,例如 016x

要配置其他日志,请使用默认的 Python 日志配置。所有 BentoML 日志都记录在 bentoml 命名空间下。

库日志

当您将 BentoML 作为库用于 Python 应用程序时,它不会配置任何日志,不包含任何特定的处理程序、格式化程序或过滤器。这意味着如果没有额外的配置,BentoML 的日志输出将遵循 Python 根日志记录器的设置,默认情况下,根日志记录器记录 WARNING 级别及更高级别的消息(包括 ERROR 和 CRITICAL)。

要捕获 BentoML 中更详细的日志,特别是在 DEBUGINFO 级别,您必须显式设置日志处理程序并将其注册到 bentoml 命名空间。以下是一个简单的示例说明如何实现这一点:

import logging

# Create a stream handler
ch = logging.StreamHandler()

# Set a format for the handler
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)

# Get the BentoML logger
bentoml_logger = logging.getLogger("bentoml")

# Add the handler to the BentoML logger
bentoml_logger.addHandler(ch)

# Set the desired logging level (e.g., DEBUG)
bentoml_logger.setLevel(logging.DEBUG)

注意

使用 bentoml serve 启动服务时,该命令会将 service.py fork 到一个子进程中。涉及文件操作的处理程序(例如日志轮换,RotatingFileHandlerTimedRotatingFileHandler)在服务定义中不受支持。更多信息请参阅Python 日志记录 Cookbook