Durable Task Scheduler を使用してオーケストレーション履歴をエクスポートする (プレビュー)

オーケストレーション履歴のエクスポート機能を使用すると、アプリは、Durable Task Scheduler からターミナル オーケストレーション インスタンス (完了、失敗、または終了状態) の実行履歴を抽出し、Azure Blob Storageに書き込みます。 この機能は、スケジューラの外部でのオーケストレーション データの監査、コンプライアンス、分析、および長期アーカイブに使用します。

オーケストレーション履歴のエクスポート機能は現在プレビュー段階であり、Durable Task .NET SDK で使用できます。 Microsoft.DurableTask.ExportHistory パッケージが必要です。

ヒント

完全で実行可能な参照サンプルは、ExportHistoryWebApp で入手できます。 このガイドに従う場合は、参照として使用することをお勧めします。

オーケストレーション履歴のエクスポートのしくみ

エクスポート履歴では、永続的なエンティティとオーケストレーションを内部的に使用して、次のプロセスでエクスポート ジョブを確実に管理します。

  1. ExportHistoryClientを使用してエクスポート ジョブを作成し、時間枠とエクスポート モードを指定します。
  2. SDK は、ジョブの状態と進行状況を追跡する永続的エンティティ (ExportJob) を作成します。
  3. 内部オーケストレーションは、指定された時間枠と状態フィルターに一致するターミナル オーケストレーション インスタンスを一覧表示します。
  4. 一致するインスタンスごとに、アクティビティは Durable Task Scheduler から完全な実行履歴をフェッチします。
  5. 履歴はシリアル化され (既定では gzip 圧縮を使用した JSONL)、Azure Blob Storageに書き込まれます。
  6. ジョブはその進行状況をチェックポイントとして保存するため、中断された場合でも再開できます。

バッチおよび連続ジョブのエクスポートモード

エクスポート履歴では、次の 2 つのモードがサポートされます。

モード 行動
バッチ 固定時間内に終了状態に達したインスタンスをエクスポートし (completedTimeFrom から completedTimeTo)、ジョブを完了としてマークします。
連続 終了時刻なしで、 completedTimeFrom 以降のターミナル インスタンスを継続的に終了します。 ジョブは、削除するまでアクティブなままです。

前提条件

  • .NET 8 SDK 以降
  • Durable Task Scheduler タスク ハブ (またはローカル エミュレーター)
  • ローカル開発用のAzure Storage アカウント (または Azurite)
  • 次の NuGet パッケージ:
    • Microsoft.DurableTask.ExportHistory
    • Microsoft.DurableTask.Client.AzureManaged
    • Microsoft.DurableTask.Worker.AzureManaged

オーケストレーション履歴のエクスポートを有効にする

  1. エクスポート履歴パッケージをインストールします。

    dotnet add package Microsoft.DurableTask.ExportHistory
    
  2. Durable Task Scheduler 用の Azure Managed クライアント パッケージと worker パッケージをインストールします。

    dotnet add package Microsoft.DurableTask.Client.AzureManaged
    dotnet add package Microsoft.DurableTask.Worker.AzureManaged
    
  3. ワーカーとクライアントの両方にエクスポート履歴を登録します。

    using Microsoft.DurableTask.Client;
    using Microsoft.DurableTask.Client.AzureManaged;
    using Microsoft.DurableTask.ExportHistory;
    using Microsoft.DurableTask.Worker;
    using Microsoft.DurableTask.Worker.AzureManaged;
    
    string connectionString = builder.Configuration.GetValue<string>("DURABLE_TASK_CONNECTION_STRING")
        ?? throw new InvalidOperationException("Missing DURABLE_TASK_CONNECTION_STRING");
    
    string storageConnectionString = builder.Configuration.GetValue<string>("EXPORT_HISTORY_STORAGE_CONNECTION_STRING")
        ?? throw new InvalidOperationException("Missing EXPORT_HISTORY_STORAGE_CONNECTION_STRING");
    
    string containerName = builder.Configuration.GetValue<string>("EXPORT_HISTORY_CONTAINER_NAME")
        ?? throw new InvalidOperationException("Missing EXPORT_HISTORY_CONTAINER_NAME");
    
    // Register the worker with export history support.
    // This registers internal entities, orchestrations, and activities that manage export jobs.
    builder.Services.AddDurableTaskWorker(worker =>
    {
        worker.UseDurableTaskScheduler(connectionString);
        worker.UseExportHistory();
    });
    
    // Register the client with export history support.
    // This configures the Azure Blob Storage destination and registers the ExportHistoryClient.
    builder.Services.AddDurableTaskClient(client =>
    {
        client.UseDurableTaskScheduler(connectionString);
        client.UseExportHistory(options =>
        {
            options.ConnectionString = storageConnectionString;
            options.ContainerName = containerName;
    
            // Optional: set a virtual folder path prefix for blob names (for example, "exports/daily").
            // When set, blobs are written to "{prefix}/{hash}.{ext}" instead of "{hash}.{ext}".
            options.Prefix = builder.Configuration.GetValue<string>("EXPORT_HISTORY_PREFIX");
        });
    });
    

エクスポート ジョブの作成と管理

エクスポート履歴を有効にした後、 ExportHistoryClient を使用してジョブを作成および管理します。

バッチ エクスポート ジョブを作成する

次の例では、バッチ エクスポート ジョブは、固定時間内に終了状態に達したすべてのオーケストレーション インスタンスをエクスポートします。

ExportHistoryClient exportClient = app.Services.GetRequiredService<ExportHistoryClient>();

ExportJobCreationOptions options = new(
    mode: ExportMode.Batch,
    completedTimeFrom: DateTimeOffset.UtcNow.AddHours(-24),
    completedTimeTo: DateTimeOffset.UtcNow,
    destination: new ExportDestination("my-export-container")
    {
        // Virtual folder path prefix applied to all blob names for this job
        Prefix = "exports/daily",
    });

ExportHistoryJobClient jobClient = await exportClient.CreateJobAsync(options);
ExportJobDescription description = await jobClient.DescribeAsync();

連続エクスポート ジョブを作成する

次の例では、連続エクスポート ジョブは、開始時刻からターミナル インスタンスを無期限に終了します。

ExportJobCreationOptions options = new(
    mode: ExportMode.Continuous,
    completedTimeFrom: DateTimeOffset.UtcNow,
    completedTimeTo: null,
    destination: null);

ExportHistoryJobClient jobClient = await exportClient.CreateJobAsync(options);

destinationが null の場合、ジョブは ExportHistoryStorageOptions で構成された既定のコンテナーとプレフィックスを使用します。

エクスポート ジョブの詳細を取得する

ジョブの状態、進行状況カウンター、エラーなど、ジョブの完全な説明を取得するには、次のコードを使用します。

ExportJobDescription? job = await exportClient.GetJobAsync("my-job-id");

GetJobAsync は、指定したジョブ ID が存在しない場合に ExportJobNotFoundException をスローします。 削除された可能性のあるジョブのクエリを実行するときに、この例外を処理します。

ExportJobDescriptionには次のものが含まれます。

財産 説明
JobId 一意のジョブ識別子。
Status 現在の状態: PendingActiveFailed、または Completed
CreatedAt ジョブが生成された時。
LastModifiedAt ジョブが最後に更新された日時。
ScannedInstances これまでにスキャンされたインスタンスの合計数。
ExportedInstances これまでにエクスポートされたインスタンスの合計数。
LastError 最後のエラー メッセージ (存在する場合)。

ジョブを一覧表示する

次の例のようなコードを使用して、アクティブなジョブの一覧をエクスポートします。

ExportJobQuery query = new()
{
    Status = ExportJobStatus.Active,
    CreatedFrom = DateTimeOffset.UtcNow.AddDays(-7),
    PageSize = 50,
};

AsyncPageable<ExportJobDescription> jobs = exportClient.ListJobsAsync(query);

await foreach (ExportJobDescription job in jobs)
{
    Console.WriteLine($"{job.JobId}: {job.Status} ({job.ExportedInstances} exported)");
}

ExportJobQueryでは、次のフィルター プロパティがサポートされています。

財産 説明
Status ジョブの状態 ( PendingActiveFailed、または Completed) でフィルター処理します。
JobIdPrefix ID がこのプレフィックスで始まるジョブをフィルター処理します。
CreatedFrom この時刻以降に作成されたジョブのみを返します。
CreatedTo この時刻以前に作成されたジョブのみを返します。
PageSize 1 ページあたりの結果の最大数。
ContinuationToken 結果の次のページを取得するためのトークン。

ジョブを削除する

ジョブを削除するには、次のコードを使用します。

ExportHistoryJobClient jobClient = exportClient.GetJobClient("my-job-id");
await jobClient.DeleteAsync();

ジョブが存在しない場合、DeleteAsyncExportJobNotFoundException をスローします。 ジョブを削除しても既にエクスポートされている BLOB はAzure Blob Storageから削除されません。

ジョブ作成オプションをエクスポートする

ExportJobCreationOptions クラスは、エクスポート ジョブの動作を制御し、次のパラメーターを含みます。

パラメーター 必須 説明 デフォルト
mode はい Batch 固定ウィンドウの場合は ゚、進行中のエクスポートの場合は Continuous
completedTimeFrom はい (バッチ) インスタンスが終了状態に達したタイミングに基づく時間枠の開始 (開始時点を含む)。 連続モードの場合、既定値は UtcNow (指定されていない場合) です。
completedTimeTo はい (バッチ) 時間枠の終了 (終了時点を含む)。 連続モードでは省略する必要があります。 今後は使用できません。
destination いいえ このジョブの既定の BLOB コンテナーとプレフィックスをオーバーライドします。 の既定値を使用します。 ExportHistoryStorageOptions
jobId いいえ カスタム ジョブ識別子。 自動生成された GUID
format いいえ エクスポート形式: JSONL (gzip 圧縮) または JSON (非圧縮)。 gzip を使用した JSONL
runtimeStatus いいえ ターミナルの状態 ( CompletedFailedTerminated) でフィルター処理します。 すべてのターミナルの状態
maxInstancesPerBatch いいえ バッチごとに処理するインスタンスの数 (1 ~ 1000)。 100

エクスポートされたデータがAzure Blob Storageに格納される場所

エクスポートされた履歴は、次のパラメーターを使用してAzure Blob Storageに書き込まれます。

  • コンテナー: EXPORT_HISTORY_CONTAINER_NAMEからの既定値、またはジョブごとの destination オーバーライド。
  • BLOB 名: (completedTimestamp, instanceId)の SHA-256 ハッシュから派生します。
  • ファイル形式:
    • 既定値: .jsonl.gz (JSON Lines,gzip-compressed — 1 行に 1 つの履歴イベント)
    • 省略可能: .json (履歴イベントの非圧縮 JSON 配列)
  • プレフィックスを持つ BLOB パス: プレフィックスが構成されている場合 (たとえば、 exports/daily)、BLOB パスは exports/daily/{hash}.{ext}になります。 プレフィックスがない場合、BLOB は {hash}.{ext}としてコンテナー ルートに直接書き込まれます。

各 BLOB には、追跡可能な instanceId メタデータ タグが含まれています。

エクスポート履歴構成の環境変数

これらの環境変数は、Durable Task .NET SDK エクスポート履歴サンプルと共に使用します。

Variable 説明 サンプルの既定値
DURABLE_TASK_CONNECTION_STRING Durable Task Scheduler 接続文字列 Endpoint=http://localhost:8080;TaskHub=default;Authentication=None
EXPORT_HISTORY_STORAGE_CONNECTION_STRING Azure Storage の接続文字列(エクスポートされた履歴 BLOB 用) UseDevelopmentStorage=true
EXPORT_HISTORY_CONTAINER_NAME エクスポートされた履歴の BLOB コンテナー export-history
EXPORT_HISTORY_PREFIX BLOB 名に対するオプションの仮想フォルダー パスのプレフィックス 設定解除する
ASPNETCORE_URLS サンプルの HTTP ホスト用のリッスン URL フレームワークの既定値

エクスポート履歴のAzureアクセス許可

ローカル エミュレーターの代わりに Azure リソースを使用する場合、アプリ ID は Durable Task Scheduler と Blob Storage にアクセスする必要があります。

  1. アプリのタスク ハブに Durable Task Data Contributor を付与します。
  2. エクスポートされた履歴 BLOB を格納するストレージ アカウントに Storage Blob Data Contributor を付与します。

エクスポート ジョブに関する重要な考慮事項

  • 同時消去操作:
    エクスポート ジョブの実行中にオーケストレーション インスタンスを消去すると、エクスポートが影響を受ける可能性があります。 エクスポートが読み取る前に消去されたインスタンスは、エクスポートされたデータから欠落します。 同じ時間枠をカバーするアクティブなエクスポート ジョブと同時に消去操作を実行しないようにします。

  • BLOB のクリーンアップ:
    エクスポート ジョブを削除しても、エクスポートされた BLOB はAzure Blob Storageから削除されません。 エクスポートされたデータを削除する必要がある場合は、ストレージ アカウントから BLOB を個別に削除します。

エクスポートが機能することを確認する

エクスポート ジョブを作成した後、両方のシグナルをチェックして動作することを確認します。

  • ジョブの状態は、 Pending から Active に移行し、最終的には Completed に移行します (バッチ モードの場合)。
  • BLOB エントリは、構成済みのエクスポート コンテナーに表示されます。

ジョブの状態をプログラムを使ってポーリングできます。

ExportJobDescription? job;
do
{
    await Task.Delay(TimeSpan.FromSeconds(5));
    job = await exportClient.GetJobAsync(jobId);
    Console.WriteLine($"Status: {job?.Status}, Exported: {job?.ExportedInstances}");
}
while (job?.Status is ExportJobStatus.Pending or ExportJobStatus.Active);

ローカル開発の場合は、次のAzure CLI コマンドを実行してコンテナーを検査します。

az storage blob list \
  --connection-string "UseDevelopmentStorage=true" \
  --container-name export-history \
  --output table

ヒント

ExportHistoryWebApp サンプルには、VS Code に対する既製の REST クライアント要求を含む ExportHistoryWebApp.http ファイルが含まれています。 それを開き、[ 要求の送信 ] をクリックして、作成、取得、一覧表示、削除操作をすばやくテストします。

次のステップ