仪表化

OpenTelemetry Ruby 的仪器化

Instrumention 是指您自己向应用程序添加可观察性代码的过程。

如果您正在 instrumenting 应用程序,您需要为您使用的语言使用 OpenTelemetry SDK。然后,您将使用 SDK 初始化 OpenTelemetry,并使用 API instrument 您的代码。这将从您的应用程序和任何也带有 instrumention 的已安装库中发出遥测数据。

如果您正在 instrumenting 库,请仅安装您语言的 OpenTelemetry API 包。您的库不会自行发出遥测数据。只有当它作为使用 OpenTelemetry SDK 的应用程序的一部分时,它才会发出遥测数据。有关 instrumenting 库的更多信息,请参阅 Libraries

有关 OpenTelemetry API 和 SDK 的更多信息,请参阅 specification

设置

首先,请确保您已安装 SDK 包

gem install opentelemetry-sdk

然后包含在程序初始化时运行的配置代码。确保通过配置服务名称来设置 service.name

追踪

获取 Tracer

要开始 追踪,您需要确保已初始化一个来自 TracerProviderTracer

最简单、最常见的方法是使用全局注册的 TracerProvider。如果您使用的是 仪器化库(例如在 Rails 应用程序中),那么会为您注册一个。

# If in a Rails app, this lives in config/initializers/opentelemetry.rb
require "opentelemetry/sdk"

OpenTelemetry::SDK.configure do |c|
  c.service_name = '<YOUR_SERVICE_NAME>'
end

# 'Tracer' can be used throughout your code now
MyAppTracer = OpenTelemetry.tracer_provider.tracer('<YOUR_TRACER_NAME>')

获得 Tracer 后,您可以手动追踪代码。

获取当前 Span

在程序中的某个位置向当前 跨度添加信息非常常见。为此,您可以获取当前跨度并向其添加 属性

require "opentelemetry/sdk"

def track_extended_warranty(extended_warranty)
  # Get the current span
  current_span = OpenTelemetry::Trace.current_span

  # And add useful stuff to it!
  current_span.add_attributes({
    "com.extended_warranty.id" => extended_warranty.id,
    "com.extended_warranty.timestamp" => extended_warranty.timestamp
  })
end

创建新跨度

要创建 跨度,您需要一个 已配置的 Tracer

通常,当您创建新跨度时,您会希望它成为活动的/当前跨度。为此,请使用 in_span

require "opentelemetry/sdk"

def do_work
  MyAppTracer.in_span("do_work") do |span|
    # do some work that the 'do_work' span tracks!
  end
end

创建嵌套跨度

如果您有一个需要跟踪的独特子操作作为另一个操作的一部分,您可以创建嵌套的 跨度来表示这种关系。

require "opentelemetry/sdk"

def parent_work
  MyAppTracer.in_span("parent") do |span|
    # do some work that the 'parent' span tracks!

    child_work

    # do some more work afterwards
  end
end

def child_work
  MyAppTracer.in_span("child") do |span|
    # do some work that the 'child' span tracks!
  end
end

在前面的示例中,创建了两个跨度——名为 parentchild——其中 child 嵌套在 parent 下。如果您在追踪可视化工具中查看带有这些跨度的追踪,child 将嵌套在 parent 下。

向跨度添加属性

属性允许您将键值对附加到 跨度,以便它携带有关其正在跟踪的当前操作的更多信息。

您可以使用 set_attribute 向跨度添加单个属性。

require "opentelemetry/sdk"

current_span = OpenTelemetry::Trace.current_span

current_span.set_attribute("animals", ["elephant", "tiger"])

您可以使用 add_attributes 添加一个属性哈希表。

require "opentelemetry/sdk"

current_span = OpenTelemetry::Trace.current_span

current_span.add_attributes({
  "my.cool.attribute" => "a value",
  "my.first.name" => "Oscar"
})

您也可以在创建跨度 时添加属性

require "opentelemetry/sdk"

MyAppTracer.in_span('foo', attributes: { "hello" => "world", "some.number" => 1024 }) do |span|
  #  do stuff with the span
end

⚠ 跨度是线程安全的结构,在修改它们时需要锁定。因此,您应该避免多次调用 set_attribute,而是批量分配属性(使用 Hash),可以在创建跨度时进行,或者在现有跨度上使用 add_attributes

⚠ 采样决策在跨度创建时发生。如果您的采样器在决定采样跨度时考虑跨度属性,那么您必须将这些属性作为跨度创建的一部分传递。创建后添加的任何属性都将不会被采样器看到,因为采样决策已经做出。

添加语义属性

语义属性是预定义的 属性,它们是常见数据类型的通用命名约定。使用语义属性可以使您跨系统规范化此类信息。

要在 Ruby 中使用语义属性,请添加相应的 gem。

gem install opentelemetry-semantic_conventions

然后您可以在代码中使用它。

require 'opentelemetry/sdk'
require 'opentelemetry/semantic_conventions'

current_span = OpenTelemetry::Trace.current_span

current_span.add_attributes({
  OpenTelemetry::SemanticConventions::Trace::HTTP_METHOD => "GET",
  OpenTelemetry::SemanticConventions::Trace::HTTP_URL => "https://opentelemetry.org.cn/",
})

添加跨度事件

跨度事件是跨度上的一个人类可读的消息,表示在其生命周期中“发生的事情”。例如,设想一个函数需要对互斥锁下的资源进行独占访问。可以在两个点创建事件——一次是尝试访问资源时,另一次是获取互斥锁时。

require "opentelemetry/sdk"

span = OpenTelemetry::Trace.current_span

span.add_event("Acquiring lock")
if mutex.try_lock
  span.add_event("Got lock, doing work...")
  # some code here
  span.add_event("Releasing lock")
else
  span.add_event("Lock already in use")
end

事件的一个有用特性是,它们的 timestamp 显示为相对于跨度开始的偏移量,这使得您可以轻松地查看它们之间经过了多少时间。

事件本身也可以带有属性,例如:

require "opentelemetry/sdk"

span.add_event("Cancelled wait due to external signal", attributes: {
  "pid" => 4328,
  "signal" => "SIGHUP"
})

可以创建带有零个或多个 跨度链接跨度,这些链接在因果关系上将其与其他跨度链接。创建链接需要 跨度上下文

require "opentelemetry/sdk"

span_to_link_from = OpenTelemetry::Trace.current_span

link = OpenTelemetry::Trace::Link.new(span_to_link_from.context)

MyAppTracer.in_span("new-span", links: [link])
  # do something that 'new_span' tracks

  # The link in 'new_span' casually associated it with the span it's linked from,
  # but it is not necessarily a child span.
end

跨度链接通常用于链接以某种方式相关的不同追踪,例如,一个长时间运行的任务异步调用子任务。

链接也可以带有附加属性创建。

link = OpenTelemetry::Trace::Link.new(span_to_link_from.context, attributes: { "some.attribute" => 12 })

设置跨度状态

可以在 Span 上设置 Status,通常用于指定 Span 未成功完成 - Error。默认情况下,所有 spans 的状态都是 Unset,这意味着 span 完成时没有错误。Ok 状态保留给您需要明确将 span 标记为成功而不是坚持默认的 Unset(即,“无错误”)的情况。

可以在 span 完成之前的任何时间设置状态。

require "opentelemetry/sdk"

current_span = OpenTelemetry::Trace.current_span

begin
  1/0 # something that obviously fails
rescue
  current_span.status = OpenTelemetry::Trace::Status.error("error message here!")
end

在 Span 中记录异常

在发生异常时记录异常是个好主意。建议在 设置跨度状态的同时执行此操作。

require "opentelemetry/sdk"

current_span = OpenTelemetry::Trace.current_span

begin
  1/0 # something that obviously fails
rescue Exception => e
  current_span.status = OpenTelemetry::Trace::Status.error("error message here!")
  current_span.record_exception(e)
end

记录异常会在当前跨度上创建一个 跨度事件,并将堆栈跟踪作为该跨度事件的属性。

异常也可以记录带有附加属性。

current_span.record_exception(ex, attributes: { "some.attribute" => 12 })

Context Propagation

分布式追踪跟踪单个请求(称为追踪)的进展,因为该请求由构成应用程序的服务处理。分布式追踪会跨越进程、网络和安全边界。术语表

这需要上下文传播,一种将追踪的标识符发送到远程进程的机制。

ℹ OpenTelemetry Ruby SDK 将处理上下文传播,只要您的服务利用了自动仪器化库。请参阅 README 以获取更多详细信息。

为了通过网络传播追踪上下文,必须将 propagator 注册到 OpenTelemetry SDK。W3 TraceContext 和 Baggage propagators 默认配置。操作员可以通过将 OTEL_PROPAGATORS 环境变量设置为逗号分隔的 propagators 列表来覆盖此值。例如,要添加 B3 传播,请将 OTEL_PROPAGATORS 设置为您希望支持的传播格式的完整列表。

export OTEL_PROPAGATORS=tracecontext,baggage,b3

tracecontextbaggage 之外的 Propagators 必须作为 gem 依赖项添加到您的 Gemfile 中,例如:

gem 'opentelemetry-propagator-b3'

指标

指标 API 和 SDK 目前正在开发中。

日志

日志 API 和 SDK 目前正在开发中。

下一步

您还需要配置一个合适的导出器,将您的 遥测数据导出到一个或多个遥测后端。