Skip to content

dkzjq/opentelemetry-pycollector

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenTelemetry Python Collector Examples

一个全面的OpenTelemetry Python采集器示例项目,展示了如何在Python应用中使用OpenTelemetry进行分布式追踪和监控。

项目特色

  • 🚀 完整的OpenTelemetry集成:包含API、SDK和多种导出器
  • 📊 多种instrumentation示例:数据库、HTTP、Redis、日志等
  • 🔍 Jaeger集成:支持将追踪数据发送到Jaeger
  • 🛠️ 易于扩展:模块化设计,便于添加新的instrumentation
  • 📈 生产就绪:包含最佳实践和错误处理

快速开始

环境要求

  • Python 3.12+
  • Jaeger (推荐使用Docker运行)

安装

# 克隆项目
git clone <repository-url>
cd opentelemetry-pycollector

# 使用uv安装依赖
uv sync

# 或者使用pip
pip install -e .

运行Jaeger

# 使用Docker运行Jaeger (推荐)
docker run -d --name jaeger \
  -e COLLECTOR_OTLP_ENABLED=true \
  -p 16686:16686 \    # Jaeger UI
  -p 4317:4317 \      # OTLP gRPC (默认端口)
  -p 4318:4318 \      # OTLP HTTP
  jaegertracing/all-in-one:latest

重要提示

  • 本项目使用 OTLP gRPC 协议,默认端口为 4317
  • 确保 Jaeger 启用了 OTLP collector (COLLECTOR_OTLP_ENABLED=true)

运行示例

# 运行基本追踪示例
uv run python -m opentelemetry_pycollector.examples.basic_tracing

# 运行嵌套span示例
uv run python -m opentelemetry_pycollector.examples.nested_spans

# 运行instrumentation示例
uv run python -m opentelemetry_pycollector.examples.instrumentation_example

# 运行span attributes示例(示例四)
uv run python -m opentelemetry_pycollector.examples.span_attributes_example

# 运行嵌套span attributes示例(示例五)
uv run python -m opentelemetry_pycollector.examples.nested_span_attributes_example

项目结构

opentelemetry_pycollector/
├── src/opentelemetry_pycollector/
│   ├── config/              # 配置管理
│   ├── examples/            # 使用示例
│   │   ├── basic_tracing.py              # 示例一:基础追踪
│   │   ├── nested_spans.py              # 示例二:嵌套span
│   │   ├── instrumentation_example.py    # 示例三:装饰器模式
│   │   ├── span_attributes_example.py    # 示例四:设置span attribute
│   │   └── nested_span_attributes_example.py  # 示例五:子span attribute
│   ├── instrumentation/     # 各种instrumentation实现
│   └── __init__.py
├── tests/                   # 测试文件
├── pyproject.toml          # 项目配置
└── README.md               # 项目文档

示例说明

示例一:基础追踪 (basic_tracing.py)

演示如何使用 tracer.start_as_current_span() 进行基础的 span 采集。

服务名称: basic-tracing-demo
运行方式: uv run python -m opentelemetry_pycollector.examples.basic_tracing

特点:

  • 基础的 span 创建和使用
  • 错误处理和状态记录
  • 简单的函数追踪

示例二:嵌套span (nested_spans.py)

演示如何创建多层级的 span 结构,模拟复杂的电商业务流程。

服务名称: nested-spans-demo
运行方式: uv run python -m opentelemetry_pycollector.examples.nested_spans

追踪结构示例:

process-order (父 span)
├── validate-order (订单验证)
│   ├── check-inventory (库存检查)
│   └── validate-user (用户验证)
├── process-payment (支付处理)
│   └── payment-gateway-call (支付网关调用)
└── confirm-order (订单确认)

特点:

  • 多层级嵌套 span 结构
  • 模拟复杂业务流程
  • 展示父子 span 关系

示例三:装饰器模式 (instrumentation_example.py)

演示如何使用装饰器为函数自动添加 OpenTelemetry 追踪功能。

服务名称: instrumentation-example
运行方式: uv run python -m opentelemetry_pycollector.examples.instrumentation_example

核心装饰器: @instrument_function

from opentelemetry_pycollector.instrumentation import instrument_function

@instrument_function(
    span_name="my_operation",           # 自定义 span 名称
    tracer_name="custom-tracer",        # Tracer 名称
    trace_id="1234...",                 # 共享 trace_id
    record_exception=True,              # 记录异常
    add_attributes=True                 # 添加函数元数据
)
def my_function():
    pass

装饰器参数:

  • span_name: 自定义 span 名称(默认使用函数名)
  • tracer_name: Tracer 名称,用于区分不同模块或组件
  • trace_id: Trace ID(32字符16进制字符串),用于关联多个函数到同一 trace
  • record_exception: 是否记录异常(默认 True)
  • add_attributes: 是否添加函数元数据(默认 True)

使用场景:

  • 为现有函数快速添加追踪功能
  • API 端点追踪
  • 业务逻辑追踪
  • 性能分析和错误追踪

trace_id 使用示例:

SHARED_TRACE_ID = "1234567890abcdef1234567890abcdef"

@instrument_function(trace_id=SHARED_TRACE_ID, span_name="operation_a")
def operation_a():
    pass

@instrument_function(trace_id=SHARED_TRACE_ID, span_name="operation_b")
def operation_b():
    pass
# 这些函数会在同一个 trace 下

示例四:设置span attribute (span_attributes_example.py)

演示如何在函数中直接设置 span 的 attribute,记录执行状态和上下文信息。

服务名称: span-attributes-example
运行方式: uv run python -m opentelemetry_pycollector.examples.span_attributes_example

使用示例:

with tracer.start_as_current_span("process-order") as span:
    span.set_attribute("order.id", order_id)
    span.set_attribute("user.id", user_id)
    span.set_attribute("order.total_amount", total_amount)
    span.set_attribute("payment.method", "credit_card")
    span.set_attribute("order.status", "confirmed")

特点:

  • 在函数执行过程中动态设置 attribute
  • 支持字符串、数字、布尔值、时间戳等多种类型
  • 使用点号分隔的层次结构命名(如 order.id, payment.status

适用场景:

  • 单一操作追踪
  • 状态记录和参数追踪
  • 简单场景,操作步骤较少

示例五:子span attribute (nested_span_attributes_example.py)

演示如何在函数中创建子 span,并在每个子 span 中独立设置 attribute。

服务名称: nested-span-attributes-example
运行方式: uv run python -m opentelemetry_pycollector.examples.nested_span_attributes_example

使用示例:

with tracer.start_as_current_span("process-payment") as parent_span:
    parent_span.set_attribute("order.id", order_id)
    
    with tracer.start_as_current_span("validate-payment") as validate_span:
        validate_span.set_attribute("validation.is_valid", True)
    
    with tracer.start_as_current_span("call-gateway") as gateway_span:
        gateway_span.set_attribute("gateway.name", "stripe")

特点:

  • 清晰的层级结构展示操作关系
  • 每个 span 有独立的 attribute
  • 支持多层嵌套

适用场景:

  • 复杂操作追踪,包含多个独立步骤
  • 性能分析,需要分析每个步骤的耗时
  • 错误定位,需要精确定位问题步骤

最佳实践

Attribute 命名规范

  • 使用点号分隔的层次结构:order.id, payment.status
  • 保持命名风格一致
  • 使用有意义的名称,便于理解

Span 设计原则

  • 合理粒度: span 的粒度要适中,不要太细也不要太粗
  • 职责单一: 每个 span 应该代表一个明确的操作
  • 层级清晰: 保持清晰的父子关系,避免过深的嵌套

性能考虑

  • 不要设置过多的 attribute,影响性能
  • 避免设置过大的值(如大字符串、大数组)
  • 在高频操作中考虑使用采样策略
  • 装饰器会带来少量性能开销,在高频函数上要谨慎使用

使用建议

  • 合理命名 span,使用有意义的名称
  • 控制追踪范围,只追踪关键路径
  • 在函数内部添加自定义属性,提供更多上下文
  • 确保异常被正确记录和传播
  • 使用 tracer_name 区分不同模块或组件
  • 使用 trace_id 关联相关的操作到同一 trace

环境变量

变量名 默认值 描述
OTEL_EXPORTER_OTLP_ENDPOINT http://localhost:4317 OTLP exporter endpoint (完整 URL)
JAEGER_URL localhost Jaeger collector 地址(如果未设置 OTEL_EXPORTER_OTLP_ENDPOINT)
OTEL_EXPORTER_OTLP_TRACES_PORTJAEGER_PORT 4317 Jaeger collector 端口 (OTLP gRPC)
OTEL_SERVICE_NAME opentelemetry-pycollector 服务名称
OTEL_CONSOLE_EXPORT false 是否启用控制台导出(用于调试)

Jaeger 故障排查

在 Jaeger UI 中找不到服务数据

如果执行代码后在 Jaeger UI (http://localhost:16686) 中找不到对应的服务日志,请检查以下几点:

  1. 检查 Jaeger 是否运行

    docker ps | grep jaeger
    #
    curl http://localhost:16686/api/services
  2. 检查端口配置

    • 确保 Jaeger collector 监听在 4317 端口(OTLP gRPC)
    • 检查防火墙是否允许 TCP 连接
    # 检查端口是否开放
    netstat -an | grep 4317
    #
    lsof -i :4317
  3. 使用测试脚本验证连接

    # 使用测试脚本发送测试数据
    uv run python test_jaeger_connection.py <your-service-name>
    
    # 例如:
    uv run python test_jaeger_connection.py spirits-agentchat
  4. 启用控制台导出进行调试

    from opentelemetry_pycollector.config.telemetry import setup_telemetry
    
    # 启用控制台导出,查看 spans 是否被正确创建
    tracer = setup_telemetry("your-service-name", enable_console_export=True)
  5. 检查服务名称匹配

    • 确保代码中使用的服务名称与 Jaeger UI 中搜索的名称完全一致
    • 服务名称区分大小写
  6. 确保 spans 被刷新

    • 程序结束前会自动调用 shutdown_telemetry() 刷新所有 spans
    • 如果程序异常退出,spans 可能未被导出
  7. 检查时间范围

    • 在 Jaeger UI 中确保选择了正确的时间范围
    • 数据可能有几秒钟的延迟才会显示

常见问题

Q: 为什么使用端口 4317?

  • 本项目使用 OTLP gRPC 协议,默认端口为 4317
  • 这是 OpenTelemetry 的标准协议,更现代且功能更强大
  • 端口 6831 是 Jaeger Thrift UDP 协议使用的端口(已弃用)

Q: 如何确认数据是否发送到 Jaeger?

  • 启用控制台导出:setup_telemetry(..., enable_console_export=True)
  • 查看 Jaeger agent 日志:docker logs jaeger
  • 使用测试脚本:python test_jaeger_connection.py <service-name>

开发

运行测试

uv run pytest

代码格式化

uv run black src/
uv run isort src/

类型检查

uv run mypy src/

贡献

欢迎提交Issue和Pull Request!

许可证

MIT License - 详见 LICENSE 文件

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages