opentelemetry
Setup
pip install opentelemetry-api
pip install opentelemetry-sdk
trace
获取tracer
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
BatchSpanProcessor,
ConsoleSpanExporter,
)
provider = TracerProvider()
processor = BatchSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(processor)
# Sets the global default tracer provider
trace.set_tracer_provider(provider)
# Creates a tracer from the global tracer provider
tracer = trace.get_tracer("my.tracer.name")
在上述代码中
BatchSpanProcessor 和 ConsoleSpanExporter 是用于处理和导出追踪数据(spans)的组件。这些组件通常用于监控和诊断分布式系统的行为。
- BatchSpanProcessor:它收集完成的 spans,并将它们以批量的形式发送到配置的导出器(如 ConsoleSpanExporter)。这种批量处理可以提高性能,因为它减少了与导出器的交互次数。你可以配置批处理的大小和导出间隔,以适应不同的性能和精度需求。
- ConsoleSpanExporter:它将收到的 spans 输出到控制台。这对于调试和开发阶段非常有用,因为你可以立即在控制台中看到追踪数据,而无需设置复杂的后端系统来接收和处理这些数据。
创建span
def do_work():
with tracer.start_as_current_span("span-name") as span:
# do some work that 'span' will track
print("doing some work...")
# When the 'with' block goes out of scope, 'span' is closed for you
运行do_work函数可以创建一个span,并跟踪do_work函数中发生的所有事件,将span传递到tracer中
创建嵌套span
如果您希望将一个不同的子操作作为另一个子操作的一部分进行跟踪,则可以创建跨度来表示关系:
def do_work():
with tracer.start_as_current_span("parent") as parent:
# do some work that 'parent' tracks
print("doing some work...")
# Create a nested span to track nested work
with tracer.start_as_current_span("child") as child:
# do some work that 'child' tracks
print("doing some nested work...")
# the nested span is closed when it's out of scope
# This span is also closed when it goes out of scope
当您在跟踪可视化工具中查看跨度时,child将作为 下的嵌套跨度进行跟踪parent,形成相应的父子id对应关系
使用装饰器创建span
使用单个span跟踪整个函数的执行是很常见的。在这种情况下,您可以使用一个装饰器来减少代码:
@tracer.start_as_current_span("do_work")
def do_work():
print("doing some work...")
使用装饰器相当于在内部创建跨度do_work()并在do_work()完成时结束它。
要使用装饰器,您必须有一个tracer可用于函数声明的全局实例。
如果您需要添加属性、事件或链接,那么使用装饰器不太方便。
获取当前span
访问当前trace到的span
from opentelemetry import trace
current_span = trace.get_current_span()
向span添加属性
属性允许您将键/值对附加到范围,以便它携带有关其正在跟踪的当前操作的更多信息。
比如我们可以添加time等参数
from opentelemetry import trace
current_span = trace.get_current_span()
current_span.set_attribute("operation.value", 1)
current_span.set_attribute("operation.name", "Saying hello!")
current_span.set_attribute("operation.other-stuff", [1, 2, 3])
添加语义属性
首先需要安装语义约定包
pip install opentelemetry-semantic-conventions
然后你可以在代码中使用它:
from opentelemetry import trace
from opentelemetry.semconv.trace import SpanAttributes
// ...
current_span = trace.get_current_span()
current_span.set_attribute(SpanAttributes.HTTP_METHOD, "GET")
current_span.set_attribute(SpanAttributes.HTTP_URL, "https://opentelemetry.io/")
添加事件
事件是一段人类可读的消息,代表在其生命周期内“发生的事情”。您可以将其视为原始日志。
from opentelemetry import trace
current_span = trace.get_current_span()
current_span.add_event("Gonna try it!")
# Do the thing
current_span.add_event("Did it!")
添加链接
可以使用零个或多个将其因果性链接到另一个跨度的跨度链接来创建跨度。链接需要创建跨度上下文。
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("span-1"):
# Do something that 'span-1' tracks.
ctx = trace.get_current_span().get_span_context()
link_from_span_1 = trace.Link(ctx)
with tracer.start_as_current_span("span-2", links=[link_from_span_1]):
# Do something that 'span-2' tracks.
# The link in 'span-2' is causally associated it with the 'span-1',
# but it is not a child span.
pass
注意:这里的两个span不存在父子关系,span-1和span-2是两个独立的span,“span-2”中的链接在因果上与“span-1”相关联,
设置span状态
可以在Span上设置 Status ,通常用于指定 Span 尚未成功完成。默认情况下,所有跨度都是 ,这意味着跨度完成且没有错误。当您需要显式地将跨度标记为成功而不是坚持默认值(即“没有错误”)时,会保留该状态,在跨度完成之前可以随时设置状态。
from opentelemetry import trace
from opentelemetry.trace import Status, StatusCode
current_span = trace.get_current_span()
try:
# something that might fail
except:
current_span.set_status(Status(StatusCode.ERROR))
在span中记录异常
当异常发生时记录它们可能是一个好主意。建议与设置span status结合执行此操作。
from opentelemetry import trace
from opentelemetry.trace import Status, StatusCode
current_span = trace.get_current_span()
try:
# something that might fail
# Consider catching a more specific exception in your code
except Exception as ex:
current_span.set_status(Status(StatusCode.ERROR))
current_span.record_exception(ex)
创建和使用异步仪器
异步仪器 为用户提供了一种注册回调函数的方法,这些回调函数可以根据需要调用来进行测量。这对于定期测量无法直接测量的值很有用。异步工具是使用零个或多个回调创建的,这些回调将在指标收集期间调用。每个回调接受来自 SDK 的选项并返回其观察结果。
此示例使用 异步仪表 仪器通过抓取 HTTP 端点来报告配置服务器提供的当前配置版本。首先,编写一个回调来进行观察:
from typing import Iterable
from opentelemetry.metrics import CallbackOptions, Observation
def scrape_config_versions(options: CallbackOptions) -> Iterable[Observation]:
r = requests.get(
"http://configserver/version_metadata", timeout=options.timeout_millis / 10**3
)
for metadata in r.json():
yield Observation(
metadata["version_num"], {"config.name": metadata["version_num"]}
)
请注意,OpenTelemetry 会将包含超时的选项传递给您的回调。回调应遵守此超时以避免无限期阻塞。最后,使用回调创建仪器来注册它:
meter.create_observable_gauge(
"config.version",
callbacks=[scrape_config_versions],
description="The active config version for each configuration",
)