例外の報告
このガイドでは、手動でアクティビティ(スパン)を作成する際に、OpenTelemetry トレーシングに例外を報告する方法について説明します。 計装ライブラリを使用している場合、これらの機能は自動的に提供されることがあります。
トレースにおける例外処理の理解
OpenTelemetry では、アプリケーションで発生するエラーに関するコンテキストを提供するために、トレースに例外を報告することが重要です。 基本的なステータス報告から完全な例外の詳細まで、これを処理する方法はいくつかあります。
ユーザーが処理する例外
ユーザーが処理する例外とは、アプリケーションによってキャッチされ処理される例外です。
try
{
Func();
}
catch (SomeException ex)
{
DoSomething();
}
catch (Exception ex)
{
DoSomethingElse();
throw;
}
OpenTelemetry .NET は、これらの例外をトレースに報告するためのいくつかのオプションを提供しています。
オプション 1:Activity のステータスを手動で設定する
もっとも基本的なオプションは、例外が発生したことを示すために Activity のステータスを Error に設定することです。
using (var activity = MyActivitySource.StartActivity("Foo"))
{
try
{
Func();
}
catch (SomeException ex)
{
activity?.SetStatus(ActivityStatusCode.Error);
DoSomething();
}
catch (Exception ex)
{
activity?.SetStatus(ActivityStatusCode.Error);
throw;
}
}
オプション 2:SetErrorStatusOnException 機能を使用する
深くネストされたアクティビティやサードパーティライブラリで作成されたアクティビティがある場合、手動でステータスを設定するのは困難になることがあります。 かわりに、例外を自動的に検出してアクティビティのステータスを設定するよう SDK を構成できます。
Sdk.CreateTracerProviderBuilder()
.SetErrorStatusOnException()
// その他の設定...
.Build();
この構成により、アクティビティがアクティブな間に発生した例外は、自動的にそのアクティビティのステータスを Error に設定します。
この機能は System.Runtime.InteropServices.Marshal.GetExceptionPointers に依存しているため、プラットフォームに依存します。
オプション 3:エラーの説明を含める
より多くのコンテキストを提供するために、例外メッセージをステータスの説明として含めることができます。
using (var activity = MyActivitySource.StartActivity("Foo"))
{
try
{
Func();
}
catch (SomeException ex)
{
activity?.SetStatus(ActivityStatusCode.Error, ex.Message);
}
}
オプション 4:完全な例外を記録する
もっとも詳細なデバッグ体験を得るために、Activity.RecordException() を使用して例外をイベントとしてアクティビティに保存します。
using (var activity = MyActivitySource.StartActivity("Foo"))
{
try
{
Func();
}
catch (SomeException ex)
{
activity?.SetStatus(ActivityStatusCode.Error, ex.Message);
activity?.RecordException(ex);
}
}
これにより、例外の型、メッセージ、スタックトレースがアクティビティにキャプチャされ、トレーシングバックエンドで利用可能になります。
未処理の例外
未処理の例外とは、アプリケーションによってキャッチおよび処理されない例外です。 通常、プロセスのクラッシュやスレッドの終了を引き起こします。
AppDomain.UnhandledException イベントハンドラーを使用することで、未処理の例外をキャプチャし、アクティブなアクティビティに記録できます。
using System;
using System.Diagnostics;
using OpenTelemetry;
using OpenTelemetry.Trace;
public class Program
{
private static readonly ActivitySource MyActivitySource = new ActivitySource("MyCompany.MyProduct.MyLibrary");
public static void Main()
{
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("MyCompany.MyProduct.MyLibrary")
.SetSampler(new AlwaysOnSampler())
.SetErrorStatusOnException()
.AddConsoleExporter()
.Build();
using (MyActivitySource.StartActivity("Foo"))
{
using (MyActivitySource.StartActivity("Bar"))
{
throw new Exception("Oops!");
}
}
}
private static void UnhandledExceptionHandler(object source, UnhandledExceptionEventArgs args)
{
var ex = (Exception)args.ExceptionObject;
var activity = Activity.Current;
while (activity != null)
{
activity.RecordException(ex);
activity.Dispose();
activity = activity.Parent;
}
}
}
AppDomain.UnhandledException は注意して使用してください。
このハンドラー内で例外をスローすると、プロセスが回復不能な状態になります。
ベストプラクティス
OpenTelemetry トレースで例外を報告する際のベストプラクティスは以下のとおりです。
常にステータスを Error に設定する:最低限、例外が発生した場合はアクティビティのステータスを Error に設定してください。
例外の詳細を含める:可能な場合は
RecordException()を使用して、完全な例外情報をキャプチャしてください。未処理の例外を処理する:未処理の例外がトレースにキャプチャされるよう、グローバルハンドラーの設定を検討してください。
自動化を検討する:例外のステータス設定を自動化するために、SDK の
SetErrorStatusOnException()オプションを使用してください。カーディナリティに注意する:変動性の高い例外メッセージをステータスの説明に直接含めると、スパンのカーディナリティが増加する可能性があるため注意してください。
さらに学ぶ
フィードバック
このページは役に立ちましたか?
Thank you. Your feedback is appreciated!
Please let us know how we can improve this page. Your feedback is appreciated!