OpenTelemetryのサポート
このページでは、AIエージェントのトレースと監視のために、KoogエージェントフレームワークにおけるOpenTelemetryのサポートについて詳しく説明します。
概要
OpenTelemetryは、アプリケーションからテレメトリーデータ(トレース)を生成、収集、エクスポートするためのツールを提供する可観測性フレームワークです。KoogのOpenTelemetry機能を使用すると、AIエージェントを計装してテレメトリーデータを収集できます。これは、以下の点で役立ちます。
- エージェントのパフォーマンスと挙動を監視する
- 複雑なエージェントのワークフローにおける問題をデバッグする
- エージェントの実行フローを可視化する
- LLM呼び出しとツール使用状況を追跡する
- エージェントの挙動パターンを分析する
OpenTelemetryの主要な概念
- Spans: スパンは、分散トレース内の個々の作業単位または操作を表します。これらは、エージェントの実行、関数呼び出し、LLM呼び出し、ツール呼び出しなど、アプリケーション内の特定の活動の開始と終了を示します。
- Attributes: 属性は、スパンなどのテレメトリー関連アイテムに関するメタデータを提供します。属性はキーと値のペアとして表現されます。
- Events: イベントは、スパンのライフタイム中の特定の時点(スパン関連イベント)であり、発生した可能性のある注目すべき事柄を表します。
- Exporters: エクスポーターは、収集されたテレメトリーデータをさまざまなバックエンドまたは宛先に送信する役割を担うコンポーネントです。
- Collectors: コレクターは、テレメトリーデータを受信、処理、エクスポートします。これらはアプリケーションと可観測性バックエンドの間の仲介役として機能します。
- Samplers: サンプラーは、サンプリング戦略に基づいてトレースを記録するかどうかを決定します。これらはテレメトリーデータのボリュームを管理するために使用されます。
- Resources: リソースは、テレメトリーデータを生成するエンティティを表します。これらはリソース属性によって識別され、リソースに関する情報を提供するキーと値のペアです。
KoogのOpenTelemetry機能は、さまざまなエージェントイベントに対してスパンを自動的に作成します。これには以下が含まれます。
- エージェントの実行開始と終了
- ノードの実行
- LLM呼び出し
- ツール呼び出し
インストール
KoogでOpenTelemetryを使用するには、OpenTelemetry機能をエージェントに追加します。
val agent = AIAgent(
executor = simpleOpenAIExecutor(apiKey),
llmModel = OpenAIModels.Chat.GPT4o,
systemPrompt = "You are a helpful assistant.",
installFeatures = {
install(OpenTelemetry) {
// Configuration options go here
}
}
)
設定
基本設定
エージェントでOpenTelemetry機能を設定する際に設定できる利用可能なプロパティの完全なリストを以下に示します。
Name | Data type | Default value | Description |
---|---|---|---|
serviceName | String | ai.koog | 計装されるサービスの名前。 |
serviceVersion | String | Current Koog library version | 計装されるサービスのバージョン。 |
isVerbose | Boolean | false | OpenTelemetry設定のデバッグのための詳細ログを有効にするかどうか。 |
sdk | OpenTelemetrySdk | テレメトリー収集に使用するOpenTelemetry SDKインスタンス。 | |
tracer | Tracer | スパン作成に使用するOpenTelemetryトレーサーインスタンス。 |
NOTE
sdk
およびtracer
プロパティは、アクセス可能なパブリックプロパティですが、以下にリストされているパブリックメソッドを使用してのみ設定できます。
OpenTelemetryConfig
クラスには、異なる設定項目に関連するアクションを表すメソッドも含まれています。以下は、基本的な設定項目セットでOpenTelemetry機能をインストールする例です。
install(OpenTelemetry) {
// Set your service configuration
setServiceInfo("my-agent-service", "1.0.0")
// Add the Logging exporter
addSpanExporter(LoggingSpanExporter.create())
}
利用可能なメソッドのリファレンスについては、以下のセクションを参照してください。
setServiceInfo
名前とバージョンを含むサービス情報を設定します。以下の引数を取ります。
Name | Data type | Required | Default value | Description |
---|---|---|---|---|
serviceName | String | Yes | 計装されるサービスの名前。 | |
serviceVersion | String | Yes | 計装されるサービスのバージョン。 |
addSpanExporter
テレメトリーデータを外部システムに送信するためのスパンエクスポーターを追加します。以下の引数を取ります。
Name | Data type | Required | Default value | Description |
---|---|---|---|---|
exporter | SpanExporter | Yes | カスタムスパンエクスポーターのリストに追加するSpanExporter インスタンス。 |
addSpanProcessor
スパンがエクスポートされる前に処理するためのスパンプロセッサーを追加します。以下の引数を取ります。
Name | Data type | Required | Default value | Description |
---|---|---|---|---|
processor | SpanProcessor | Yes | エクスポート前にテレメトリーデータを処理するためのカスタムロジックを含むスパンプロセッサー。 |
addResourceAttributes
サービスに関する追加のコンテキストを提供するためのリソース属性を追加します。以下の引数を取ります。
Name | Data type | Required | Default value | Description |
---|---|---|---|---|
attributes | Map<AttributeKey<T>, T> | Yes | サービスに関する追加の詳細を提供するキーと値のペア。 |
setSampler
どのスパンを収集するかを制御するためにサンプリング戦略を設定します。以下の引数を取ります。
Name | Data type | Required | Default value | Description |
---|---|---|---|---|
sampler | Sampler | Yes | OpenTelemetry設定のために設定するサンプラーインスタンス。 |
setVerbose
OpenTelemetry設定のデバッグ用の詳細ログを有効または無効にします。以下の引数を取ります。
Name | Data type | Required | Default value | Description |
---|---|---|---|---|
verbose | Boolean | Yes | false | trueの場合、アプリケーションはより詳細なテレメトリーデータを収集します。 |
高度な設定
より高度な設定については、以下の設定オプションもカスタマイズできます。
- Sampler: 収集されるデータの頻度と量を調整するためにサンプリング戦略を設定します。
- Resource attributes: テレメトリーデータを生成しているプロセスに関する情報を追加します。
install(OpenTelemetry) {
// Set your service configuration
setServiceInfo("my-agent-service", "1.0.0")
// Add the Logging exporter
addSpanExporter(LoggingSpanExporter.create())
// Set the sampler
setSampler(Sampler.traceIdRatioBased(0.5))
// Add resource attributes
addResourceAttributes(mapOf(
AttributeKey.stringKey("custom.attribute") to "custom-value")
)
}
Sampler
サンプラーを定義するには、使用したいサンプリング戦略を表すopentelemetry-java
SDKのSampler
クラス(io.opentelemetry.sdk.trace.samplers.Sampler
)の対応するメソッドを使用します。
デフォルトのサンプリング戦略は以下の通りです。
Sampler.alwaysOn()
: すべてのスパン(トレース)がサンプリングされるデフォルトのサンプリング戦略。
利用可能なサンプラーとサンプリング戦略の詳細については、OpenTelemetryのSamplerドキュメントを参照してください。
Resource attributes
リソース属性は、テレメトリーデータを生成するプロセスに関する追加情報を表します。Koogには、デフォルトで設定される一連のリソース属性が含まれています。
service.name
service.version
service.instance.time
os.type
os.version
os.arch
service.name
属性のデフォルト値はai.koog
であり、service.version
のデフォルト値は現在使用されているKoogライブラリのバージョンです。
デフォルトのリソース属性に加えて、カスタム属性を追加することもできます。KoogでOpenTelemetry設定にカスタム属性を追加するには、OpenTelemetry設定でaddResourceAttributes()
メソッドを使用します。このメソッドはキーと値を引数として取ります。
addResourceAttributes(mapOf(
AttributeKey.stringKey("custom.attribute") to "custom-value")
)
スパンの種類と属性
OpenTelemetry機能は、エージェント内のさまざまな操作を追跡するために、異なるタイプのスパンを自動的に作成します。
- CreateAgentSpan: エージェントを実行すると作成され、エージェントが閉じられるか、プロセスが終了すると閉じられます。
- InvokeAgentSpan: エージェントの呼び出し。
- NodeExecuteSpan: エージェントの戦略におけるノードの実行。これはカスタムのKoog固有スパンです。
- InferenceSpan: LLM呼び出し。
- ExecuteToolSpan: ツール呼び出し。
スパンはネストされた階層構造で整理されます。以下はスパン構造の例です。
CreateAgentSpan
InvokeAgentSpan
NodeExecuteSpan
InferenceSpan
NodeExecuteSpan
ExecuteToolSpan
NodeExecuteSpan
InferenceSpan
スパン属性
スパン属性は、スパンに関連するメタデータを提供します。各スパンは独自の属性セットを持ち、一部のスパンは属性を繰り返すこともできます。
Koogは、OpenTelemetryの生成AIイベントのセマンティック規約に従う事前定義された属性のリストをサポートしています。たとえば、規約ではgen_ai.conversation.id
という名前の属性が定義されており、これは通常、スパンに必須の属性です。Koogでは、この属性の値はエージェント実行の一意の識別子であり、agent.run()
メソッドを呼び出すと自動的に設定されます。
さらに、KoogはカスタムのKoog固有属性も含まれています。これらの属性のほとんどはkoog.
プレフィックスで識別できます。利用可能なカスタム属性は以下の通りです。
koog.agent.strategy.name
: エージェント戦略の名前。戦略は、エージェントの目的を説明するKoog関連エンティティです。InvokeAgentSpan
スパンで使用されます。koog.node.name
: 実行中のノードの名前。NodeExecuteSpan
スパンで使用されます。
イベント
スパンには_イベント_もアタッチできます。イベントは、何か関連する出来事が起こった特定の時点を表します。たとえば、LLM呼び出しが開始または終了したときなどです。イベントには属性もあり、さらにイベントの_本体フィールド_も含まれます。
OpenTelemetryの生成AIイベントのセマンティック規約に沿って、以下のイベントタイプがサポートされています。
- SystemMessageEvent: モデルに渡されるシステム指示。
- UserMessageEvent: モデルに渡されるユーザーメッセージ。
- AssistantMessageEvent: モデルに渡されるアシスタントメッセージ。
- ToolMessageEvent: モデルに渡されるツールまたは関数呼び出しからの応答。
- ChoiceEvent: モデルからの応答メッセージ。
NOTE
optentelemetry-java
SDKは、イベントを追加する際にイベント本体フィールドパラメータをサポートしていません。したがって、KoogのOpenTelemetryサポートでは、イベント本体フィールドはキーがbody
で値の型が文字列である個別の属性です。この文字列には、イベント本体フィールドのコンテンツまたはペイロードが含まれており、通常はJSONのようなオブジェクトです。イベント本体フィールドの例については、OpenTelemetryドキュメントを参照してください。opentelemetry-java
におけるイベント本体フィールドのサポート状況については、関連するGitHubイシューを参照してください。
エクスポーター
エクスポーターは、収集されたテレメトリーデータをOpenTelemetry Collectorまたは他の種類の宛先やバックエンド実装に送信します。エクスポーターを追加するには、OpenTelemetry機能をインストールする際にaddSpanExporter()
メソッドを使用します。このメソッドは以下の引数を取ります。
Name | Data type | Required | Default | Description |
---|---|---|---|---|
exporter | SpanExporter | Yes | カスタムスパンエクスポーターのリストに追加するSpanExporter インスタンス。 |
以下のセクションでは、opentelemetry-java
SDKの最も一般的に使用されるエクスポーターのいくつかについて説明します。
ロギングエクスポーター
トレース情報をコンソールに出力するロギングエクスポーターです。LoggingSpanExporter
(io.opentelemetry.exporter.logging.LoggingSpanExporter
)は、opentelemetry-java
SDKの一部です。
このタイプのエクスポートは、開発およびデバッグ目的で役立ちます。
install(OpenTelemetry) {
// Add the logging exporter
addSpanExporter(LoggingSpanExporter.create())
// Add more exporters as needed
}
OpenTelemetry HTTPエクスポーター
OpenTelemetry HTTPエクスポーター(OtlpHttpSpanExporter
)は、opentelemetry-java
SDK(io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter
)の一部であり、HTTP経由でスパンデータをバックエンドに送信します。
install(OpenTelemetry) {
// Add OpenTelemetry HTTP exporter
addSpanExporter(
OtlpHttpSpanExporter.builder()
// Set the maximum time to wait for the collector to process an exported batch of spans
.setTimeout(30, TimeUnit.SECONDS)
// Set the OpenTelemetry endpoint to connect to
.setEndpoint("http://localhost:3000/api/public/otel/v1/traces")
// Add the authorization header
.addHeader("Authorization", "Basic $AUTH_STRING")
.build()
)
}
OpenTelemetry gRPCエクスポーター
OpenTelemetry gRPCエクスポーター(OtlpGrpcSpanExporter
)は、opentelemetry-java
SDK(io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter
)の一部です。gRPC経由でテレメトリーデータをバックエンドにエクスポートし、データを受信するバックエンド、コレクター、またはエンドポイントのホストとポートを定義できます。デフォルトのポートは4317
です。
install(OpenTelemetry) {
// Add OpenTelemetry gRPC exporter
addSpanExporter(
OtlpGrpcSpanExporter.builder()
// Set the host and the port
.setEndpoint("http://localhost:4317")
.build()
)
}
Jaegerとの統合
Jaegerは、OpenTelemetryと連携する人気の分散トレースシステムです。Koogリポジトリのexamples
内のopentelemetry
ディレクトリには、JaegerとKoogエージェントでOpenTelemetryを使用する例が含まれています。
前提条件
KoogとJaegerでOpenTelemetryをテストするには、提供されているdocker-compose.yaml
ファイルを使用してJaeger OpenTelemetryオールインワンプロセスを開始します。以下のコマンドを実行してください。
docker compose up -d
提供されているDocker Compose YAMLファイルには、以下の内容が含まれています。
# docker-compose.yaml
services:
jaeger-all-in-one:
image: jaegertracing/all-in-one:1.39
container_name: jaeger-all-in-one
environment:
- COLLECTOR_OTLP_ENABLED=true
ports:
- "4317:4317"
- "16686:16686"
Jaeger UIにアクセスしてトレースを表示するには、http://localhost:16686
を開いてください。
例
Jaegerで使用するためのテレメトリーデータをエクスポートするために、この例ではopentelemetry-java
SDKのLoggingSpanExporter
(io.opentelemetry.exporter.logging.LoggingSpanExporter
)とOtlpGrpcSpanExporter
(io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter
)を使用しています。
以下に完全なコードサンプルを示します。
fun main() {
runBlocking {
val agent = AIAgent(
executor = simpleOpenAIExecutor(openAIApiKey),
llmModel = OpenAIModels.Reasoning.O4Mini,
systemPrompt = "You are a code assistant. Provide concise code examples."
) {
install(OpenTelemetry) {
// Add a console logger for local debugging
addSpanExporter(LoggingSpanExporter.create())
// Send traces to OpenTelemetry collector
addSpanExporter(
OtlpGrpcSpanExporter.builder()
.setEndpoint("http://localhost:4317")
.build()
)
}
}
agent.use { agent ->
println("Running the agent with OpenTelemetry tracing...")
val result = agent.run("Tell me a joke about programming")
println("Agent run completed with result: '$result'." +
"
Check Jaeger UI at http://localhost:16686 to view traces")
}
}
}
トラブルシューティング
よくある問題
JaegerまたはLangfuseにトレースが表示されない
- サービスが実行されており、OpenTelemetryポート(4317)にアクセス可能であることを確認してください。
- OpenTelemetryエクスポーターが正しいエンドポイントで設定されていることを確認してください。
- トレースがエクスポートされるまで、エージェントの実行後に数秒待つようにしてください。
スパンが見つからない、またはトレースが不完全
- エージェントの実行が正常に完了したことを確認してください。
- エージェントの実行後にアプリケーションを早すぎる段階で終了させていないことを確認してください。
- スパンがエクスポートされる時間を確保するために、エージェント実行後に遅延を追加してください。
過剰な数のスパン
sampler
プロパティを設定して、別のサンプリング戦略の使用を検討してください。- たとえば、
Sampler.traceIdRatioBased(0.1)
を使用して、トレースの10%のみをサンプリングします。