
OpenTelemetry 的 LoggingInstrumentor 仅增强日志格式与上下文注入,不自动发送日志;需显式配置 LoggerProvider、OTLPLogExporter 和 LoggingHandler 才能将日志通过 OTLP 推送至 SigNoz。
opentelemetry 的 `logginginstrumentor` 仅增强日志格式与上下文注入,**不自动发送日志**;需显式配置 `loggerprovider`、`otlplogexporter` 和 `logginghandler` 才能将日志通过 otlp 推送至 signoz。
在 OpenTelemetry 生态中,LoggingInstrumentor().instrument() 的作用常被误解:它并非日志导出器,而是一个日志上下文注入工具——其核心功能是自动将当前 trace ID、span ID、service.name 等追踪上下文注入到 logging record 的 extra 字段中(例如 record.trace_id),从而实现日志与链路的关联。但它不会创建日志采集管道,也不会启动任何 exporter。这正是日志“看不见”的根本原因:日志仍由原生 logging 模块处理并输出到 console/file,从未进入 OpenTelemetry 的日志 SDK 流水线。
要真正将日志发送至 SigNoz,必须完整搭建 OpenTelemetry Logs SDK 的基础组件:
- ✅
LoggerProvider:日志 SDK 的根提供者,管理日志生命周期与资源; - ✅
OTLPLogExporter:将日志序列化为 OTLP 协议并通过 gRPC(或 HTTP)发送至 SigNoz(端口4317); - ✅
BatchLogRecordProcessor:异步批处理日志记录,提升性能与可靠性; - ✅
LoggingHandler:作为 logging 模块的桥接器,将logging.getLogger().info(...)调用转发至LoggerProvider。
以下是可直接运行的生产就绪配置示例(兼容 SigNoz v0.42+):
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
import logging
import json
import os
from opentelemetry import trace
from opentelemetry._logs import set_logger_provider
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import OTLPLogExporter
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.sdk.resources import Resource
# 1. 配置日志导出器(推荐从环境变量读取)
otlp_endpoint = os.getenv("OTLP_ENDPOINT", "http://localhost:4317")
insecure = json.loads(os.getenv("OTLP_INSECURE", "true").lower())
exporter = OTLPLogExporter(
endpoint=otlp_endpoint,
insecure=insecure,
# 可选:添加 headers(如 SigNoz API Token)
# headers={"signoz-api-token": "your-token-here"}
)
# 2. 创建日志提供者并绑定资源
logger_provider = LoggerProvider(
resource=Resource.create({
"service.name": os.getenv("SERVICE_NAME", "python-app"),
"telemetry.sdk.language": "python",
})
)
set_logger_provider(logger_provider)
# 3. 添加批处理处理器(关键!否则日志不会发出)
logger_provider.add_log_record_processor(BatchLogRecordProcessor(exporter))
# 4. 创建并注册 LoggingHandler(桥接标准 logging)
handler = LoggingHandler(level=logging.INFO, logger_provider=logger_provider)
logging.getLogger().addHandler(handler)
logging.getLogger().setLevel(logging.INFO)
# ✅ 此时日志将被采集、注入 trace 上下文,并发送至 SigNoz
logging.info("Application started")
logging.warning("This warning includes trace context if called within a span")
⚠️ 关键注意事项:
-
不要混用
LoggingInstrumentor.instrument()与上述手动配置:二者目标不同。若已启用LoggingInstrumentor,它会自动丰富日志字段(如trace_id),但仍需LoggingHandler将日志接入 SDK;单独使用LoggingInstrumentor而无 handler/exporter,日志永远只停留在 stdout。 -
端口与协议一致性:确保 SigNoz 的 OTLP receiver 启用了
logs类型(默认开启),且endpoint地址与 tracing 使用的4317端口一致(SigNoz 统一接收 traces/logs/metrics)。 -
环境变量优先:建议通过
OTLP_ENDPOINT和OTLP_INSECURE控制连接参数,便于容器/K8s 部署。 - 自动插桩替代方案:如追求极简,可直接使用 SigNoz 官方提供的 Python 自动插桩工具,它内部已封装完整的 trace + log SDK 初始化逻辑,一行命令即可启用全量可观测性。
完成配置后,重启应用,在 SigNoz UI 的 Logs → Explore 页面即可实时检索日志,并通过 trace_id 字段与对应链路双向跳转,真正实现 trace-log 一体化观测。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










