You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python日志格式化器中设置名称含点的变量?

Python Logging注入Datadog带点格式自定义元数据的解决方案

我在尝试实现Datadog日志注入时,遇到自定义dd.service、dd.env、dd.version字段输出为空的问题。原代码通过ContextFilter给日志record绑定了一个dd对象,但Python Logging没法正确解析格式字符串里带点的%(dd.service)s语法,而且Datadog的logging补丁对这类字段有特殊处理逻辑。

推荐方案:全局配置自动注入

Datadog的ddtrace库支持通过全局配置直接设置服务元数据,开启logging补丁后会自动把这些值注入到日志的对应字段里,不用自己写过滤器:

import logging
from ddtrace import tracer, config
from ddtrace import patch

# 全局设置Datadog元数据
config.service = "bi_app_log_service"
config.env = "DEV"
config.version = "20220624"

# 打补丁开启日志注入功能
patch(logging=True)

FORMAT = ('%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] '
          '[dd.service=%(dd.service)s dd.env=%(dd.env)s '
          'dd.version=%(dd.version)s '
          'dd.trace_id=%(dd.trace_id)s dd.span_id=%(dd.span_id)s]'
          '- %(message)s')

@tracer.wrap()
def hello():
    logging.basicConfig(format=FORMAT)
    logger = logging.getLogger(__name__)
    logger.level = logging.DEBUG
    logger.info('Hello, World!')

if __name__ == '__main__':
    hello()

备选方案:自定义过滤器设置单个属性

如果需要动态注入元数据,要注意Datadog的logging补丁会把dd.service这类带点字段映射成record.dd_service形式的单个属性(不是嵌套对象),所以直接给record设置对应属性就行:

import logging
from ddtrace import tracer
from ddtrace import patch

patch(logging=True)

class ContextFilter(logging.Filter):
    def filter(self, record):
        # 给record设置单个属性,对应格式字符串里的dd.*字段
        record.dd_service = "bi_app_log_service"
        record.dd_env = "DEV"
        record.dd_version = "20220624"
        return True

FORMAT = ('%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] '
          '[dd.service=%(dd.service)s dd.env=%(dd.env)s '
          'dd.version=%(dd.version)s '
          'dd.trace_id=%(dd.trace_id)s dd.span_id=%(dd.span_id)s]'
          '- %(message)s')

@tracer.wrap()
def hello():
    logging.basicConfig(format=FORMAT)
    logger = logging.getLogger(__name__)
    logger.addFilter(ContextFilter())
    logger.level = logging.DEBUG
    logger.info('Hello, World!')

if __name__ == '__main__':
    hello()

为什么原代码无效?

Datadog的patch(logging=True)会给Python Logging添加自定义格式化逻辑:它会解析格式字符串中的dd.*字段,自动转换成对record.dd_*属性的访问(比如dd.service对应record.dd_service)。原代码里给record绑定dd嵌套对象的方式,不符合这个解析逻辑,所以没法被正确识别。

内容的提问来源于stack exchange,提问作者Bogdan Lashkov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 19:39:17