計装

OpenTelemetry Ruby計装

計装とは、あなた自身がアプリにオブザーバビリティコードを追加する行為です。

アプリを計装する場合、あなたが使用する言語に対応したOpenTelemetry SDKを使用する必要があります。 次に、SDKを使用してOpenTelemetryを初期化し、APIを使用してコードを計装します。 これにより、アプリ本体だけでなく、計装が含まれるライブラリからもテレメトリーが出力されるようになります。

ライブラリを計装する場合、使用する言語に対応したOpenTelemetry APIパッケージのみをインストールしてます。 ライブラリ自体はテレメトリーを出力しません。 ライブラリの計装についての詳細は、ライブラリを参照してください。

OpenTelemetry APIとSDKについての詳細は、仕様を参照してください。

セットアップ

はじめに、SDKパッケージがインストールされていることを確認してください。

gem install opentelemetry-sdk

次に、プログラムの初期化時に実行される、設定コードを記述します。 サービス名を設定して(たとえば OTEL_SERVICE_NAME 環境変数を使って)、service.name が設定されていることを確認してください。

各計装を個別に有効にせずに、多くの一般的なライブラリを計装するには、opentelemetry-instrumentation-all を使用します。

gem install opentelemetry-instrumentation-all

次に、利用可能な計装を有効にするように SDK を設定します。

require 'opentelemetry/sdk'
OpenTelemetry::SDK.configure do |c|
  c.use_all
end

このアプローチにより、サポートされているライブラリの計装が自動的に有効になります(そのため、通常は以下のトレースセクションにある個別の計装手順に従う必要はありません)。 デプロイメントに適したエクスポーターと環境変数の設定は、別途必要になる場合があります。

トレース

トレーサーの取得

トレースを開始するには、トレーサープロバイダーから取得する、初期化されたトレーサーが必要です。

最も簡単で一般的な方法は、グローバルに登録されたトレーサープロバイダーを使用することです。 Railsアプリなどで計装ライブラリを使用している場合、トレーサープロバイダーは自動的に登録されます。

# Railsアプリの場合、このコードはconfig/initializers/opentelemetry.rbにあります。
require "opentelemetry/sdk"

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

# `トレーサー`は、コード全体で使用できるようになっています。
MyAppTracer = OpenTelemetry.tracer_provider.tracer('<YOUR_TRACER_NAME>')

トレーサーを取得することで、コードを手動でトレースできます。

現在のスパンを取得

プログラム内のどこかで現在のスパンに情報を追加することは、ごく一般的です。 そのためには、現在のスパンを取得して、それに属性を追加することができます。

require "opentelemetry/sdk"

def track_extended_warranty(extended_warranty)
  # 現在のスパンを取得する
  current_span = OpenTelemetry::Trace.current_span

  # さらに、現在のスパンに有用な情報を追加します!
  current_span.add_attributes({
    "com.extended_warranty.id" => extended_warranty.id,
    "com.extended_warranty.timestamp" => extended_warranty.timestamp
  })
end

新しいスパンの作成

スパンを作成するには、構成済みのトレーサーが必要です。

通常、新しいスパンを作成するときは、そのスパンをアクティブもしくは現在のスパンにしたいと思うでしょう。 それには、in_spanを使用します。

require "opentelemetry/sdk"

def do_work
  MyAppTracer.in_span("do_work") do |span|
    # `do_work`スパンが追跡する何らかの処理を実行
  end
end

in_span ブロックから例外がエスケープした場合、トレーサーはデフォルトでスパンに例外を記録し、スパンステータスを Error に設定して、例外を再度発生させます。 in_span メソッドの引数として record_exception: false を渡すことで、自動例外記録を無効にできます。

ブロック内で例外をレスキューし、再度発生させない場合は、必要に応じてスパンステータスの設定と例外の記録を手動で行います。

MyAppTracer.in_span("do_work") do |span|
  begin
    # 例外を発生させる可能性のある処理を実行
  rescue StandardError => e
    span.status = OpenTelemetry::Trace::Status.error(e.message)
    span.record_exception(e)

    # フォールバックを返すなど、再度発生させずに例外を処理する
  end
end

ネストされたスパンの作成

別の操作の一部として追跡したい個別のサブ操作がある場合、関係を表すためにネストされたスパンを作成できます。

require "opentelemetry/sdk"

def parent_work
  MyAppTracer.in_span("parent") do |span|
    # `parent`スパンが追跡する何らかの処理を実行!

    child_work

    # 何らかの後続処理
  end
end

def child_work
  MyAppTracer.in_span("child") do |span|
    # `child`スパンが追跡する何らかの処理を実行!
  end
end

前述の例では、parentchild という名前の2つのスパンが作成され、childparent の下にネストされています。 トレース可視化ツールでこれらのスパンを表示すると、childparent の下にネストされていることがわかります。

スパンへの属性の追加

属性によって、スパンにキー/値のペアを追加し、追跡している現在の操作に関するより多くの情報を保持することができます。

スパンに単一の属性を追加するには、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|
  # スパンを使用した何らかの処理を実行
end

⚠ スパンは、変更されるときにロックを必要とするスレッドセーフなデータ構造です。 したがって、set_attribute を複数回呼び出すことは避け、代わりにスパンの作成中または既存のスパンの add_attributes を使用して、ハッシュで属性を一括で割り当てることが望ましいです。

⚠ サンプリングの決定は、スパンの作成時に行われます。 サンプラーがスパンをサンプリングするか決定する際にスパン属性を考慮する場合は、スパン作成の一部としてそれらの属性を渡す 必要があります 。 スパン作成後に追加された属性は、サンプリングの決定がすでに行われているため、サンプラーには表示されません。

セマンティック属性の追加

セマンティック属性は、一般的な種類のデータに対するよく知られた命名規則に基づいた、事前定義された属性です。 セマンティック属性を使用することで、システム全体でこの種の情報を正規化できます。

Rubyでセマンティック属性を使用するには、適切なgemを追加します。