Durable Functions には、オーケストレーションをトラブルシューティングするための診断ツールがいくつか用意されています。 この記事では、追跡とログ記録の構成、再生セーフ コードの記述、分散トレースの検査、ローカルでのデバッグを行う方法について説明します。
この記事では、次の方法について説明します。
- ライフサイクル イベントの Application Insights 追跡を構成する
- Kusto を使用してオーケストレーション インスタンスをクエリする
- 低レベルの診断のために Durable Task Framework (DTFx) ログを有効にする
- エンドツーエンドのオーケストレーション フローを視覚化するように分散トレースを設定する
- オーケストレーター関数でリプレイ セーフログを書き込む
- カスタム オーケストレーションの状態 を外部クライアントに報告する
- ブレークポイントを使用してオーケストレーションをローカルでデバッグする
Application Insights の追跡を構成する
Application Insights は、Durable Functions を監視するための推奨される方法です。 Durable 拡張機能は、オーケストレーションのエンドツーエンドの実行をトレースできる 追跡イベント を出力します。 これらの追跡イベントの検索とクエリは、Azure ポータルの Application Insights Analytics ツールを使用して実行できます。
ログ レベルの構成
host.json ファイル内の Application Insights に出力される追跡データの詳細度を構成します。
{
"logging": {
"logLevel": {
"Host.Triggers.DurableTask": "Information",
},
}
}
既定では、すべての "再生以外" の追跡イベントが出力されます。
Host.Triggers.DurableTaskを"Warning"または"Error"に設定することで、データの量を減らすことができます。つまり、追跡イベントは例外的な状況でのみ生成されます。 詳細なオーケストレーション再生イベントを有効にするには、host.json 構成ファイルで、logReplayEvents を true に設定します。
注
既定では、Azure Functions ランタイムは Application Insights テレメトリをサンプリングして、データの出力頻度が高くなりすぎないようにします。 サンプリングにより、短期間に多数のライフサイクル イベントが発生すると、追跡情報が失われる可能性があります。 この動作を構成する方法については、Azure Functions の監視に関する記事で説明しています。
入力ログと出力ログ
既定では、オーケストレーター、アクティビティ、エンティティ関数の入力と出力はログに記録されません。 入力と出力をログに記録すると Application Insights のコストが増加する可能性があるため、この方法をお勧めします。 関数の入力および出力ペイロードには、機密情報も含まれる場合があります。 代わりに、関数の入力と出力のバイト数がログに記録されます。 Durable Functions 拡張機能で入力と出力のペイロードをすべてログに記録するには、traceInputsAndOutputs 構成ファイル内でtrue プロパティを に設定します。
オーケストレーション インスタンスのクエリを実行する
Application Insights Analytics で次の Kusto クエリを使用して、オーケストレーション インスタンスを検査します。
シングル インスタンス クエリ
次のクエリでは、Hello シーケンス関数オーケストレーションの単一インスタンスに関する履歴追跡データが表示されます。 再生実行を除外して、論理実行パスだけを表示するためです。 次のクエリに示すように、 timestamp と sequenceNumber で並べ替えることで、イベントを並べ替えることができます。
let targetInstanceId = "ddd1aaa685034059b545eb004b15d4eb";
let start = datetime(2018-03-25T09:20:00);
traces
| where timestamp > start and timestamp < start + 30m
| where customDimensions.Category == "Host.Triggers.DurableTask"
| extend functionName = customDimensions["prop__functionName"]
| extend instanceId = customDimensions["prop__instanceId"]
| extend state = customDimensions["prop__state"]
| extend isReplay = tobool(tolower(customDimensions["prop__isReplay"]))
| extend sequenceNumber = tolong(customDimensions["prop__sequenceNumber"])
| where isReplay != true
| where instanceId == targetInstanceId
| sort by timestamp asc, sequenceNumber asc
| project timestamp, functionName, state, instanceId, sequenceNumber, appName = cloud_RoleName
結果では、実行時刻の昇順に並べ替えられたアクティビティ関数など、オーケストレーションの実行パスを示す追跡イベントが一覧表示されます。
インスタンス概要クエリ
次のクエリでは、指定した時間範囲内で実行されたすべてのオーケストレーション インスタンスの状態が表示されます。
let start = datetime(2017-09-30T04:30:00);
traces
| where timestamp > start and timestamp < start + 1h
| where customDimensions.Category == "Host.Triggers.DurableTask"
| extend functionName = tostring(customDimensions["prop__functionName"])
| extend instanceId = tostring(customDimensions["prop__instanceId"])
| extend state = tostring(customDimensions["prop__state"])
| extend isReplay = tobool(tolower(customDimensions["prop__isReplay"]))
| extend output = tostring(customDimensions["prop__output"])
| where isReplay != true
| summarize arg_max(timestamp, *) by instanceId
| project timestamp, instanceId, functionName, state, output, appName = cloud_RoleName
| order by timestamp asc
結果では、インスタンス ID とその現在の実行状態が一覧表示されます。
追跡データのリファレンス
すべてのオーケストレーション インスタンスは、ライフサイクルを進むにつれて追跡イベントを生成します。 各ライフサイクル イベントには、複数のフィールドを含む customDimensions ペイロードが含まれています。 フィールド名は、いずれも prop__ で始まります。
| フィールド名 | 説明 |
|---|---|
hubName |
オーケストレーションが実行されているタスク ハブの名前。 |
appName |
関数アプリの名前。 このフィールドは、複数の関数アプリで同じ Application Insights インスタンスを共有しているときなどに使用できます。 |
slotName |
現在の関数アプリが実行されている デプロイ スロット 。 このフィールドは、デプロイ スロットを使用してご自分のオーケストレーションのバージョン管理を行うときに便利です。 |
functionName |
オーケストレーターまたはアクティビティ関数の名前。 |
functionType |
オーケストレーターやアクティビティなどの関数の型。 |
instanceId |
オーケストレーション インスタンスの一意の ID。 |
state |
インスタンスのライフサイクル実行状態。 |
state.Scheduled |
関数は実行するようにスケジュールされましたが、まだ実行を開始していません。 |
state.Started |
関数の実行が開始されましたが、まだ待機または完了していません。 |
state.Awaited |
オーケストレーターは作業をスケジュールし、完了を待機しています。 |
state.Listening |
オーケストレーターは外部イベント通知を待機しています。 |
state.Completed |
関数は正常に完了しました。 |
state.Failed |
関数がエラーで失敗しました。 |
reason |
追跡イベントに関連付けられている追加データ。 たとえば、インスタンスが外部イベント通知を待機している場合、このフィールドは待機しているイベントの名前を示します。 関数が失敗した場合、このフィールドにはエラーの詳細が含まれます。 |
isReplay |
追跡イベントが再生実行用かどうかを示すブール値。 |
extensionVersion |
Durable Task 拡張機能のバージョン。 このバージョン情報は、拡張機能にバグの可能性があることを報告するときに特に重要です。 インスタンスの実行中に更新が発生した場合、実行時間の長いインスタンスは複数のバージョンを報告する場合があります。 |
sequenceNumber |
イベントの実行シーケンス番号。 タイムスタンプと組み合わせることで、イベントを実行時間別に並べ替えるのに役立ちます。 インスタンスの実行中にホストが再起動した場合、この数値は 0 にリセットされるため、常にタイムスタンプ順に並べ替え、次に sequenceNumber キーを押す必要があります。 |
Durable Task Framework のログ記録 (DTFx)
Durable 拡張機能のログは、オーケストレーション ロジックの動作を理解するのに役立ちます。 ただし、これらのログには、フレームワークレベルのパフォーマンスと信頼性の問題をデバッグするのに十分な情報が必ず含まれているわけではありません。 Durable 拡張機能の v 2.3.0 以降では、基になる Durable Task Framework (DTFx) によって出力されたログもコレクションに使用できます。
DTFx によって出力されるログを確認するときは、DTFx エンジンにコア ディスパッチ エンジン (DurableTask.Core) と サポートされている多くのストレージ プロバイダーの 1 つという 2 つのコンポーネントがあることを理解しておくことが重要です。
| コンポーネント | 説明 |
|---|---|
DurableTask.Core |
コアオーケストレーションの実行と、低レベルのスケジューリングログおよびテレメトリ。 |
DurableTask.DurableTaskScheduler |
Durable Task Scheduler に固有のバックエンド ログ。 |
DurableTask.AzureStorage |
Azure Storage 状態プロバイダーに特化したバックエンドログ。 これらのログには、内部オーケストレーション状態を格納およびフェッチするために使用される内部キュー、BLOB、およびストレージ テーブルとの詳細な対話が含まれます。 |
DurableTask.Netherite |
Netherite ストレージ プロバイダーに固有のバックエンド ログ (有効な場合)。 |
DurableTask.SqlServer |
Microsoft SQL (MSSQL) ストレージ プロバイダーに固有のバックエンド ログ (有効な場合)。 |
これらのログを有効にするには、関数アプリの logging/logLevel ファイルの セクションを更新します。 次の例は、DurableTask.Core と DurableTask.AzureStorage の両方からの警告とエラーのログを有効にする方法を示しています。
{
"version": "2.0",
"logging": {
"logLevel": {
"DurableTask.AzureStorage": "Warning",
"DurableTask.Core": "Warning"
}
}
}
Application Insights が有効になっている場合、これらのログは trace コレクションに自動的に追加されます。 Kusto クエリを使用して他の trace ログを検索するのと同じ方法で検索できます。
注
運用アプリケーションでは、DurableTask.Core フィルターを使用して、DurableTask.AzureStorageと適切なストレージ プロバイダー ("Warning" など) ログを有効にすることをお勧めします。
"Information"などの詳細度の高いフィルターは、パフォーマンスの問題のデバッグに役立ちます。 ただし、これらのログ イベントは大量になる可能性があるため、Application Insights のデータ ストレージ コストが大幅に増加する可能性があります。
次の Kusto クエリは DTFx ログのクエリを実行する方法を示しています。 クエリの最も重要な部分は、where customerDimensions.Category startswith "DurableTask"がDurableTask.CoreおよびDurableTask.AzureStorageカテゴリのログに結果をフィルタリングするためです。
traces
| where customDimensions.Category startswith "DurableTask"
| project
timestamp,
severityLevel,
Category = customDimensions.Category,
EventId = customDimensions.EventId,
message,
customDimensions
| order by timestamp asc
結果は、Durable Task Framework ログ プロバイダーによって書き込まれたログのセットになります。
使用できるログ イベントの詳細については、GitHub の Durable Task Framework 構造化ログに関するドキュメントを参照してください。
分散トレース
分散トレースは、要求を追跡し、さまざまなサービスが相互に対話する方法を示します。 Durable Functionsでは、オーケストレーション、エンティティ、およびアクティビティが相互に関連付けられます。 分散トレースは、オーケストレーション全体に対する各オーケストレーション ステップの実行時間を示し、問題または例外が発生する場所を識別します。 この機能は、すべての言語とストレージ プロバイダーの Application Insights でサポートされています。
前提条件
分散トレースには、特定の最小拡張機能バージョンが必要です。
- .NET Isolated アプリの場合、 Microsoft.Azure.Functions.Worker.Extensions.DurableTask>= v1.4.0。
- non-.NET アプリの場合は、 次の手順に従って 、現時点では Microsoft.Azure.WebJobs.Extensions.DurableTask>= v3.2.0 を手動でインストールします。 分散トレースは、拡張バンドル >v4.24.x で使用できます。
分散トレースの設定
分散トレースを構成するには、 host.json を更新し、Application Insights リソースを設定します。
host.json
{
"extensions": {
"durableTask": {
"tracing": {
"distributedTracingEnabled": true,
"version": "V2"
}
}
}
}
Application Insights
Application Insights リソースを使用して関数アプリを構成します。
トレースの検査
Application Insights リソースで、[ トランザクション検索] に移動します。 結果で、Durable 固有のプレフィックス (Request、Dependency など) で始まるorchestration:イベントとactivity: イベントを探します。 これらのイベントのいずれかを選択すると、エンドツーエンドの分散トレースを示すガント チャートが開きます。 チャートには、各オーケストレーション ステップが水平バーとして視覚的に表示され、アクティビティとサブオーケストレーションの呼び出しが親オーケストレーションの下にネストされます。 バーの長さは、各ステップの実時間を表し、ボトルネックや予期せず遅いアクティビティを簡単に見つけることができます。
注
Application Insights にトレースが表示されない場合 アプリケーションを実行してから約 5 分待ってから、すべてのデータが Application Insights リソースに伝達されるようにします。
オーケストレーター関数でのリプレイ安全なログ記録
オーケストレーター関数は、新しい入力が受信されるたびに 再生 されます。つまり、オーケストレーター内のすべてのログ ステートメントは、1 回の論理実行に対して複数回実行されます。 たとえば、アクティビティ呼び出しが 3 つの関数では、再生中に次のようなログ出力が生成されます。
Calling F1.
Calling F1.
Calling F2.
Calling F1.
Calling F2.
Calling F3.
Calling F1.
Calling F2.
Calling F3.
Done!
ログ行の重複を防ぐには、ログが最初の (再生以外の) パスでのみ実行されるように、"再生中" フラグを確認します。 次の例は、各プログラミング言語におけるリプレイ安全なログ記録を示しています。
Durable Functions 2.0 以降では、 CreateReplaySafeLogger を使用して、再生中にログ ステートメントを自動的に除外します。
[FunctionName("FunctionChain")]
public static async Task Run(
[OrchestrationTrigger] IDurableOrchestrationContext context,
ILogger log)
{
log = context.CreateReplaySafeLogger(log);
log.LogInformation("Calling F1.");
await context.CallActivityAsync("F1");
log.LogInformation("Calling F2.");
await context.CallActivityAsync("F2");
log.LogInformation("Calling F3");
await context.CallActivityAsync("F3");
log.LogInformation("Done!");
}
リプレイ セーフ ログでは、ログ出力は次のようになります。
Calling F1.
Calling F2.
Calling F3.
Done!
カスタム オーケストレーションの状態
カスタム オーケストレーションの状態を使用して、ワークフローの進行状況を外部クライアントに報告します。 一般的なパターンには、完了率、ステップの説明、エラーの概要が含まれます。 外部クライアントは、 HTTP 状態クエリ API または言語固有の API 呼び出しを使用してカスタム状態を表示できます。
次のコードは、オーケストレーター関数でカスタム状態値を設定する方法を示しています。
[FunctionName("SetStatusTest")]
public static async Task SetStatusTest([OrchestrationTrigger] IDurableOrchestrationContext context)
{
// ...do work...
// update the status of the orchestration with some arbitrary data
var customStatus = new { completionPercentage = 90.0, status = "Updating database records" };
context.SetCustomStatus(customStatus);
// ...do more work...
}
注
前の C# の例は Durable Functions 2.x 用です。 Durable Functions 1.x の場合、DurableOrchestrationContext の代わりに IDurableOrchestrationContext を使用する必要があります。 バージョン間の相違点の詳細については、Durable Functions のバージョンに関する記事を参照してください。
オーケストレーションの実行中に、外部クライアントはこのカスタム状態を取り込むことができます:
GET /runtime/webhooks/durabletask/instances/instance123?code=XYZ
クライアントは次の応答を受け取ります。
{
"runtimeStatus": "Running",
"input": null,
"customStatus": { "completionPercentage": 90.0, "status": "Updating database records" },
"output": null,
"createdTime": "2017-10-06T18:30:24Z",
"lastUpdatedTime": "2017-10-06T19:40:30Z"
}
Warnung
カスタム 状態ペイロードは、Azure Table Storage列に収まる必要があるため、UTF-16 JSON テキストの 16 KB に制限されています。 より大きなペイロードが必要な場合は、外部ストレージを使用できます。
デバッグ
Azure Functions ではデバッグ関数コードが直接サポートされており、それと同じ機能が Durable Functions でも利用できます。Azure 内で実行するか、ローカルで実行するかは関係ありません。 最適なデバッグ エクスペリエンスを実現するために、次のワークフローを使用します。
新しいタスク ハブを使用して新しいデバッグ セッションを開始するか、セッション間でタスク ハブの内容をクリアします。 前の実行からのメッセージが残ると、予期しない再実行が発生する可能性があります。
オーケストレーターまたはアクティビティ関数にブレークポイントを設定します。 オーケストレーター関数の場合は、"再生中" の値が
false場合にのみ中断する条件付きブレークポイントを使用して、再生中に同じブレークポイントに複数回ヒットしないようにします。普段通りにコードをステップ実行します。 次の動作に注意してください。
再生:
オーケストレーター関数は、新しい入力を受信すると定期的に 再生 されます。 オーケストレーター関数を 1 回 論理 実行すると、同じブレークポイントに複数回ヒットする可能性があります(特に、関数コードの早い段階で設定されている場合)。待つ:
オーケストレーター関数でawaitが発生するたびに、Durable Task Framework ディスパッチャーに制御が戻されます。 特定のawaitが初めて発生した場合、関連付けられているタスクは再開 されません 。 タスクが再開しないため、await をステップオーバー (Visual Studio の F10) することはできません。 ステップ オーバーが機能するのは、タスクが再生されているときだけです。メッセージングのタイムアウト:
Durable Functions は、キュー メッセージを内部的に使用して、オーケストレーター、アクティビティ、エンティティ関数の実行を促進します。 マルチ VM 環境では、拡張デバッグ セッションによって別の VM がメッセージを処理し、その結果、実行が重複する可能性があります。 この動作は通常のキュー トリガー関数にも存在しますが、キューは実装の詳細であるため、このコンテキストを強調することが重要です。停止と開始:
Durable Functions のメッセージは、デバッグ セッション間で保持されます。 永続関数の実行中にデバッグを停止し、ローカル ホスト プロセスを終了すると、その関数は将来のデバッグ セッションで自動的に再実行される可能性があります。
その他のツール
ストレージの状態を検査する
既定では、Durable Functionsは状態をAzure Storageに格納します。 Microsoft Azure Storage Explorer などのツールを使用して、オーケストレーションの状態とメッセージを検査できます。
Warnung
テーブル ストレージ内の実行履歴を確認できるのは便利ですが、このテーブルに依存することは避けてください。 Durable Functions拡張機能の進化に伴って変更される可能性があります。
注
既定のAzure Storage プロバイダーではなく、他のストレージ プロバイダーを構成できます。 アプリ用に構成されているストレージ プロバイダーによっては、さまざまなツールを使用して基になる状態を調べる必要がある場合があります。
Durable Functions モニター
Durable Functions Monitor は、オーケストレーションインスタンスとエンティティ インスタンスを監視、管理、デバッグするためのグラフィカル ツールです。 Visual Studio Code拡張機能またはスタンドアロン アプリとして使用できます。 セットアップ手順と機能の一覧については、Durable Functions Monitor Wikiを参照してください。
Azure ポータルの診断
Azure ポータルには、関数アプリ用の組み込みの診断ツールが用意されています。
問題を診断して解決する: Azure Function App Diagnostics は、アプリケーションの潜在的な問題を監視および診断するのに役立つリソースです。 診断に基づく問題の解決に役立つ提案も提供されます。 詳細については、「Azure Function App Diagnostics」を参照してください。
オーケストレーション トレース: Azure portal には、各オーケストレーション インスタンスの状態を理解し、エンドツーエンドの実行をトレースするのに役立つオーケストレーション トレースの詳細が用意されています。 Azure Functions アプリ内の関数の一覧を表示すると、トレースへのリンクを含む Monitor 列が表示されます。 この情報にアクセスするには、アプリで Application Insights を有効にする必要があります。
Roslyn アナライザー
Durable Functions Roslyn Analyzer は、C# 開発者が Durable Functions 固有のコード制約に従うよう誘導するリアルタイムコードアナライザーです。 Visual StudioおよびVisual Studio Codeで有効にする方法については、「Durable Functions Roslyn Analyzerを参照してください。
Troubleshooting
オーケストレーションの停止、開始の失敗、実行速度の低下などの一般的な問題のトラブルシューティングを行うには、Durable Functionsトラブルシューティング ガイドを参照してください。