- LLMOps
- 可观测性
【免费下载链接】openllmetry
Open-source observability for your GenAI or LLM application, based on OpenTelemetry
导读
traceloop-sdk是 openllmetry 仓库中面向 Python 的 LLM 可观测性 SDK,它以 OpenTelemetry 为底座,以非侵入式的方式自动埋点 LLM 应用:一行Traceloop.init()即可自动插桩 OpenAI、Anthropic、LangChain、LlamaIndex 等主流框架,并配合@workflow、@task等装饰器刻画业务实体与调用链。读完本文,你将掌握 SDK 的初始化参数、自动插桩选择机制、装饰器体系、关联属性(association properties)以及自定义导出/处理器等完整接入方案。
一、SDK 定位:非侵入式 LLM 可观测性
根据 packages/traceloop-sdk/README.md 的说明,该 SDK 的核心主张是:
- 非侵入式:无需修改 LLM 调用代码,通过 OpenTelemetry 插桩机制自动捕获调用;
- 基于 OpenTelemetry:trace 数据完全符合 OTel 语义约定(SDK 直接依赖
opentelemetry-api、opentelemetry-sdk,并配套使用本仓库的 opentelemetry-semantic-conventions-ai 包定义 GenAI 语义属性); - 导出灵活:既可以把 trace 导出到 Traceloop 云端平台,也可以接入你现有的任何 OpenTelemetry Collector / 可观测性后端。
从 pyproject.toml 可以看到,SDK 还内置了日志(
opentelemetry-instrumentation-logging)、HTTP 客户端(requests/urllib3)、数据库(sqlalchemy、redis)等通用插桩依赖,以及 40+ 个 GenAI 专项插桩包,构成完整的可观测性覆盖。
二、快速开始:最小可用示例
README 给出了最精简的接入形态——只需两步:调用Traceloop.init()初始化,然后用@workflow装饰业务函数:
Traceloop.init(app_name="joke_generation_service") @workflow(name="joke_creation") def create_joke(): completion = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": "Tell me a joke about opentelemetry"}], ) return completion.choices[0].message.content这段代码揭示了两层机制:
Traceloop.init()是总开关,负责创建 TracerProvider、注册 span processor、自动初始化各框架插桩(详见下文第三、四节);@workflow装饰器把create_joke标记为一个"工作流"实体,它内部对 OpenAI 的调用会自动产生 LLM span,并成为工作流 span 的子 span,从而在 trace 中还原完整的业务调用链(装饰器实现位于 decorators/base.py)。
更完整的可运行示例可参考仓库中的 packages/sample-app/sample_app/anthropic_joke_example.py,其中演示了带api_key/api_endpoint参数的Traceloop.init()调用。
三、Traceloop.init() 初始化参数详解
Traceloop.init()是 SDK 的入口,定义于 traceloop/sdk/init.py。关键参数如下:
| 参数 | 默认值 | 作用说明 |
|---|---|---|
app_name | sys.argv[0] | 应用名,会作为 OTel 资源的service.name写入所有 trace/指标 |
api_endpoint | https://api.traceloop.com | OTLP 导出端点;可被环境变量TRACELOOP_BASE_URL覆盖 |
api_key | None | Traceloop 平台 API Key;可被TRACELOOP_API_KEY覆盖 |
enabled | True | 总开关,为False时完全禁用插桩(输出黄色提示并直接返回) |
headers | {} | 自定义导出请求头;可被TRACELOOP_HEADERS覆盖(支持Key1: Value1,Key2: Value2格式字符串) |
disable_batch | False | 为True时使用SimpleSpanProcessor(同步导出),否则使用BatchSpanProcessor |
telemetry_enabled | True | SDK 自身遥测开关 |
exporter | None | 自定义SpanExporter,替换默认 OTLP exporter |
metrics_exporter | None | 自定义指标MetricExporter |
logging_exporter | None | 自定义日志LogExporter |
processor | None | 自定义SpanProcessor或处理器列表,可覆盖默认导出流程 |
propagator | None | 自定义TextMapPropagator,会通过set_global_textmap全局生效 |
sampler | None | 自定义Sampler,用于 trace 采样 |
traceloop_sync_enabled | False | 为True时启用 Traceloop 平台配置/提示词同步(Fetcher) |
should_enrich_metrics | True | 是否让各 LLM 插桩上报 token 用量等增强指标 |
resource_attributes | {} | 附加 OTel 资源属性,service.name会自动并入 |
instruments | 全部 | 显式指定启用的插桩集合(见第四节) |
block_instruments | None | 显式禁用的插桩集合 |
span_postprocess_callback | None | span 结束前回调,可用于脱敏/修改属性 |
use_attributes | True | True时 prompt/completion 以 span 属性(gen_ai.input.messages/gen_ai.output.messages)上报;False时改为 OTel log events |
trace_content | None | 控制是否捕获 prompt/completion 内容,等价于设置环境变量TRACELOOP_TRACE_CONTENT |
3.1 初始化流程中的关键校验逻辑
从init.py 的实现可以看到几条重要行为:
use_attributes与use_legacy_attributes不能同时传入,后者已标记为 Deprecated(未来版本移除),建议统一使用use_attributes;- 若既未传
exporter也未传processor,且api_endpoint仍是默认的https://api.traceloop.com而缺少api_key,SDK 会报错并提示去平台创建 API Key; - 同时传
exporter和processor时,exporter会被忽略并给出告警——自定义processor应当自行包裹 exporter,例如SimpleSpanProcessor(my_exporter); trace_content=False只是进程级关闭内容捕获,而每个关联属性(association properties)的允许列表(content allow list)仍可针对特定 span 重新开启内容追踪。
3.2 自定义导出端点
SDK 的init_spans_exporter(位于 tracing/tracing.py)会根据api_endpoint的 URL scheme 自动选择导出协议:
| scheme | 导出器 | 说明 |
|---|---|---|
http:///https:// | OTLP HTTP exporter | 自动补全/v1/traces路径 |
grpc:// | OTLP gRPC exporter(insecure) | 使用netloc作为端点 |
grpcs:// | OTLP gRPC exporter(TLS) | 安全模式 |
| 无 scheme | gRPC(insecure) | 为向后兼容保留的默认行为 |
因此接入本地 OpenTelemetry Collector 或任何兼容 OTLP 的后端,只需:
Traceloop.init( app_name="my_llm_app", api_endpoint="http://localhost:4318", # 标准 OTLP/HTTP 端口 )四、自动插桩:Instruments 与插桩选择
SDK 的"非侵入式"核心在于自动加载各框架的插桩器。Instruments枚举定义于 instruments.py,覆盖了当前主流 GenAI 生态:
- LLM 厂商:OPENAI、ANTHROPIC、COHERE、MISTRAL、OLLAMA、GROQ、TOGETHER、BEDROCK、SAGEMAKER、GOOGLE_GENERATIVEAI、VERTEXAI、WATSONX、WRITER、REPLICATE、ALEPHALPHA、VOYAGEAI、AGNO、OPENAI_AGENTS;
- 框架/编排:LANGCHAIN、LLAMA_INDEX、LITELLM、HAYSTACK、CREWAI、MCP、TRANSFORMERS;
- 向量数据库:CHROMA、PINECONE、QDRANT、MILVUS、WEAVIATE、LANCEDB、MARQO;
- 基础设施:REQUESTS、URLLIB3、REDIS、PYMYSQL。
默认情况下init()会尝试初始化所有已安装库对应的插桩器;也可以精细控制:
from traceloop.sdk.instruments import Instruments # 只启用 OpenAI 插桩 Traceloop.init( app_name="chat_service", instruments={Instruments.OPENAI}, ) # 启用全部,但排除 Anthropic Traceloop.init( app_name="chat_service", block_instruments={Instruments.ANTHROPIC}, )从 tracing/tracing.py 的init_instrumentations实现可见其选择逻辑:instruments集合先减去block_instruments,再逐个检查对应三方库是否已安装(is_package_installed),已安装才真正执行instrumentor.instrument();若最终没有任何插桩成功,会输出"No valid instruments set"的红色告警。这套逻辑在测试中有对应验证,见 tests/conftest.py 的exporter_with_custom_instrumentationsfixture。
注意:
Instruments中CREW = "crewai"是已弃用的别名(源码注释标明会在未来大版本移除),请使用CREWAI。
五、装饰器体系:workflow / task / agent / tool / conversation
除自动插桩外,SDK 提供一套语义化装饰器,用于把函数标注为业务实体并自动生成 span。全部装饰器定义于 decorators/init.py,包括同步与异步版本:
| 装饰器 | span 类型(traceloop.span.kind) | 适用场景 |
|---|---|---|
@workflow(name=...) | workflow | 端到端业务工作流(README 示例即用它) |
@task(name=...) | task | 工作流中的子任务 |
@agent(name=...) | agent | Agent 实体,遵循 OTel GenAI 的gen_ai.agent.name语义 |
@tool(name=...) | tool | 工具调用,同时写入gen_ai.tool.name属性 |
@conversation(conversation_id=...) | — | 为上下文中的所有 span 设置会话 ID(gen_ai.conversation.id) |
5.1 span 命名与属性
以@workflow(name="joke_creation")为例,生成的 span 名称为joke_creation.workflow(f"{entity_name}.{tlp_span_kind.value}",见 decorators/base.py),并写入:
traceloop.span.kind:实体类型;traceloop.entity.name:实体名称;traceloop.entity.version(若传入version参数);traceloop.entity.input/traceloop.entity.output:函数入参与返回值的 JSON 序列化(受内容追踪开关控制)。
实体名缺省时取函数的__qualname__。异步函数、生成器函数同样被支持:entity_method内部通过inspect.iscoroutinefunction/isasyncgenfunction自动分流(decorators/base.py)。
5.2 错误处理
装饰器对异常有完整的语义化处理:函数抛异常时,span 会被置为StatusCode.ERROR,状态描述携带异常消息并调用record_exception记录异常事件,随后异常原样向上抛出。这一点在 tests/test_tasks.py 中有直接的测试验证(同步与异步任务各一例)。
5.3 实体路径与上下文
装饰器在 span 建立时会通过 context 机制把workflow_name、agent_name、entity_path附加到当前上下文,后续创建的 LLM span 会自动继承(default_span_processor_on_start,见 tracing/tracing.py)。entity_path支持链式拼接:task 的路径会带上其父实体,例如workflow_name.task_name(get_chained_entity_path)。源码中的注释特别强调:这些 context token 必须在装饰函数结束时按 LIFO 顺序 detach,否则实体名会泄漏到同 trace 中后续创建的 span 上——这也是实现细节中对并发/异步场景的显式处理。
5.4 会话关联
@conversation(conversation_id="conv-123")可将同一会话中的所有 span 关联起来,支持与@workflow叠加使用(装饰器 docstring 给出了两个示例)。它内部调用set_conversation_id(tracing/tracing.py),写入符合 OTel GenAI 语义约定的gen_ai.conversation.id属性。
六、关联属性与内容追踪控制
6.1 Association Properties
关联属性用于把业务维度(客户、用户、会话)绑定到 trace 上,便于按业务口径检索。两种设置方式等价:
from traceloop.sdk import Traceloop # 方式一:直接传 dict Traceloop.set_association_properties({ "customer_id": "cust-123", "user_id": "user-456", }) # 方式二:使用标准枚举(定义见 associations/associations.py) from traceloop.sdk.associations import AssociationProperty from traceloop.sdk.associations import Associations Associations.set([ (AssociationProperty.CUSTOMER_ID, "cust-123"), (AssociationProperty.SESSION_ID, "session-789"), ])标准枚举包括customer_id、user_id、session_id三个预定义键(associations/associations.py),也支持任意自定义键。关联属性会被写入每个 span 的traceloop.association.properties.<key>属性(tracing/tracing.py),并同样作用于指标的公共标签(metrics_common_attributes)。
6.2 内容追踪与允许列表
是否捕获 prompt/completion 等敏感内容,由TRACELOOP_TRACE_CONTENT环境变量控制(默认true,见 config/init.py)。此外 SDK 内置ContentAllowList(tracing/content_allow_list.py):当全局内容追踪被关闭时,若当前关联属性命中了允许列表(从 Traceloop 平台同步的associationPropertyAllowList),该 span 的内容追踪会被重新打开(override_enable_content_tracing)。这对于"默认脱敏、白名单用户例外"的合规场景很有价值。
七、环境变量速查表
以下环境变量在init.py 与 config/init.py 中有明确实现:
| 环境变量 | 默认值 | 作用 |
|---|---|---|
TRACELOOP_API_KEY | 无 | Traceloop 平台 API Key |
TRACELOOP_BASE_URL | https://api.traceloop.com | OTLP 导出端点 |
TRACELOOP_HEADERS | 无 | 自定义导出请求头(K: V逗号分隔) |
TRACELOOP_TRACING_ENABLED | true | 总开关,置false时跳过 tracing 初始化 |
TRACELOOP_TRACE_CONTENT | true | 是否捕获 prompt/completion 内容 |
TRACELOOP_METRICS_ENABLED | true | 是否启用指标 |
TRACELOOP_METRICS_ENDPOINT/TRACELOOP_METRICS_HEADERS | 继承 tracing 配置 | 指标专用端点与请求头 |
TRACELOOP_LOGGING_ENABLED | false | 是否启用日志导出(默认关闭) |
TRACELOOP_LOGGING_ENDPOINT/TRACELOOP_LOGGING_HEADERS | 继承 tracing 配置 | 日志专用端点与请求头 |
TRACELOOP_SUPPRESS_WARNINGS | false | 抑制"未初始化"告警 |
OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT | 无 | 装饰器 JSON 入参/出参属性的截断长度(见 decorators/base.py) |
八、指标与日志
- 指标:SDK 会为 token 用量(
Meters.LLM_TOKEN_USAGE)等指标建立带显式 bucket 的直方图视图,并对 Pinecone 查询耗时/相似度等预置聚合(metrics/metrics.py)。传入metrics_exporter即可把指标导出到自定义后端。 - 日志:默认关闭(
TRACELOOP_LOGGING_ENABLED=false)。启用后通过opentelemetry-instrumentation-logging的LoggingInstrumentor自动接入标准logging,并挂载LoggingHandler到logging.basicConfig(logging/logging.py),实现 Python 日志的 OTel 结构化导出。
九、自定义导出:exporter 与 processor
9.1 传入自定义 exporter
适用于"导入到自有可观测性栈"的典型场景:
from opentelemetry.sdk.trace.export import SimpleSpanProcessor from my_backend import MySpanExporter Traceloop.init( app_name="my_app", exporter=MySpanExporter(), )9.2 传入自定义 processor 列表
processor参数支持单个或多个SpanProcessor。SDK 会链式包装每个 processor 的on_start,保证默认的实体属性注入(workflow/task 名称等)依然生效。测试 tests/conftest.py 展示了"默认 Traceloop processor + 自定义 processor"的组合用法:
default_processor = Traceloop.get_default_span_processor(disable_batch=True) custom_processor = MyCustomSpanProcessor() Traceloop.init( app_name="my_app", processor=[default_processor, custom_processor], )Traceloop.get_default_span_processor()是官方提供的辅助方法(init.py),方便用户把 SDK 默认处理器与其他自定义处理器合并使用。
9.3 span 后处理回调
span_postprocess_callback允许在 span 结束前对属性做脱敏/改写。由于 OTel 在Span.end()后会把属性标记为不可变,SDK 在回调执行期间临时解除冻结、回调结束后恢复(tracing/tracing.py)。tests/conftest.py 给出了把gen_ai.input.messages内容替换为"REDACTED"的脱敏示例,是生产环境治理敏感数据的常用手段。
十、Client 高级能力
当使用 Traceloop 平台(api_endpoint指向 traceloop.com 且提供api_key)时,Traceloop.init()会返回一个Client实例(client/client.py),聚合了以下能力(从 SDK 包结构 traceloop/sdk 可以看出):
- Prompt 管理:
prompts/registry.py维护PromptRegistry,支持按 key 加载平台同步的提示词版本(get_prompt_by_key/load),配合set_prompt可在 trace 中记录模板与变量; - Datasets / Experiment / Evaluator:数据集管理、离线实验与评估(datasets、experiment、evaluator);
- Guardrails:
@guardrail(*guards, input_mapper=..., on_failure=..., name=...)装饰器为函数附加输出校验,支持"raise"(默认)、"log"、"ignore"或自定义兜底字符串/回调(decorators/init.py); - User Feedback:
user_feedback子客户端收集用户反馈。
单例模式还支持Traceloop.get()获取共享 client;如需多实例,可直接构造Client(api_key=..., app_name=..., api_endpoint=...)。
十一、适用前提与限制
- Python 版本:SDK 要求
python >= 3.10, < 4(pyproject.toml)。 - 依赖体量:SDK 默认聚合了全部 40+ 插桩包(见 pyproject.toml 的
[project.optional-dependencies]与[tool.uv.sources])。插桩是否实际生效取决于对应三方库是否已安装——未安装的库会被自动跳过,因此不会因缺依赖而崩溃。 - 内容追踪注意点:
use_attributes=False走 OTel log events 路径,需要应用自行配置EventLoggerProvider(opentelemetry._events.set_event_logger_provider),否则 prompt/completion 数据将无处可去(init.py 的 docstring 明确说明)。 - 装饰器未初始化时的行为:若未调用
Traceloop.init(),被装饰函数会降级为直接执行原逻辑(TracerWrapper.verify_initialized()返回False),不产生 trace,也不抛异常,可通过TRACELOOP_SUPPRESS_WARNINGS=true关闭相关告警提示。 - 早退的生成器:源码注释提示,对异步生成器若消费者未
aclose()就提前break,实体名清理可能延迟到事件循环回收时才执行;需要确定性清理时应使用contextlib.aclosing()或排空生成器(decorators/base.py)。
结语
traceloop-sdk把 OpenTelemetry 的插桩能力与 LLM 业务语义(workflow/task/agent/tool、会话、关联属性)封装成极简 API:接入成本低至一行初始化,深度使用时又能精细控制插桩范围、内容脱敏、自定义导出与平台高级能力。若要继续深入,建议直接阅读 packages/traceloop-sdk/traceloop/sdk 下的源码与 packages/traceloop-sdk/tests 中的测试用例,前者是行为的最终权威,后者则提供了大量可直接复用的验证模式。
- LLMOps
- 可观测性
【免费下载链接】openllmetry
Open-source observability for your GenAI or LLM application, based on OpenTelemetry
相关推荐
OpenLLMetry终极指南:基于OpenTelemetry的LLM应用可观测性解决方案
OpenLLMetry终极指南:基于OpenTelemetry的LLM应用可观测性解决方案 OpenLLMetry是一个基于OpenTelemetry的开源项目
LLMOps可观测性OpenLLMetry:基于OpenTelemetry的LLM应用观测性解决方案
OpenLLMetry:基于OpenTelemetry的LLM应用观测性解决方案 项目概述 OpenLLMetry是一个建立在OpenTelemetry之上的扩
LLMOps可观测性OpenLLMetry 深度指南:基于 OpenTelemetry 的 LLM 应用全链路可观测性方案
OpenLLMetry 深度指南:基于 OpenTelemetry 的 LLM 应用全链路可观测性方案 OpenLLMetry 是构建在 OpenTelemet
LLMOps可观测性
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考