Esportare la cronologia dell'orchestrazione con Durable Task Scheduler (anteprima)

La funzionalità di esportazione della cronologia dell'orchestrazione consente all'app di estrarre le cronologie di esecuzione per le istanze di orchestrazione del terminale (stato completato, non riuscito o terminato) da Durable Task Scheduler e scriverle in Archiviazione BLOB di Azure. Usare questa funzionalità per il controllo, la conformità, l'analisi e l'archiviazione a lungo termine dei dati di orchestrazione all'esterno del schedulatore.

Annotazioni

La funzionalità di esportazione della cronologia di orchestrazione è attualmente disponibile in anteprima e disponibile per Durable Task .NET SDK. Richiede il pacchetto Microsoft.DurableTask.ExportHistory.

Suggerimento

Un esempio di riferimento eseguibile completo è disponibile in ExportHistoryWebApp. È consigliabile usarlo come riferimento seguendo questa guida.

Funzionamento dell'esportazione della cronologia dell'orchestrazione

La cronologia di esportazione utilizza entità e orchestrazioni durevoli internamente per gestire in modo affidabile i processi di esportazione con il seguente metodo.

  1. Si crea un processo di esportazione tramite ExportHistoryClient, specificando un intervallo di tempo e la modalità di esportazione.
  2. L'SDK crea un'entità persistente (ExportJob) che tiene traccia dello stato e dell'avanzamento del processo.
  3. Un'orchestrazione interna elenca le istanze di orchestrazione del terminale che corrispondono all'intervallo di tempo e ai filtri di stato specificati.
  4. Per ogni istanza corrispondente, un'attività recupera la cronologia di esecuzione completa da Durable Task Scheduler.
  5. La cronologia viene serializzata (JSONL con compressione gzip per impostazione predefinita) e scritta in Archiviazione BLOB di Azure.
  6. Il processo inserisce checkpoint nel progresso così da poter riprendere in caso di interruzione.

Modalità di esportazione per processi in lotti e continui

La cronologia di esportazione supporta due modalità:

Modalità Comportamento
Batch Esporta le istanze che hanno raggiunto uno stato del terminale in un intervallo di tempo fisso (completedTimeFrom a completedTimeTo), quindi contrassegna il processo come completato.
Continuo Accoda le istanze del terminale con continuità a partire da completedTimeFrom, senza ora di fine. Il processo rimane attivo finché non viene eliminato.

Prerequisiti

  • .NET 8 SDK o versione successiva
  • Un hub di attività di Durable Task Scheduler (o l'emulatore locale)
  • Un account Archiviazione di Azure (o Azurite per lo sviluppo locale)
  • I pacchetti NuGet seguenti:
    • Microsoft.DurableTask.ExportHistory
    • Microsoft.DurableTask.Client.AzureManaged
    • Microsoft.DurableTask.Worker.AzureManaged

Abilitare l'esportazione della cronologia di orchestrazione

  1. Installare il pacchetto della cronologia di esportazione.

    dotnet add package Microsoft.DurableTask.ExportHistory
    
  2. Installare i pacchetti Azure Managed Client e Worker per il Durable Task Scheduler.

    dotnet add package Microsoft.DurableTask.Client.AzureManaged
    dotnet add package Microsoft.DurableTask.Worker.AzureManaged
    
  3. Registrare la cronologia di esportazione sia sul worker che sul client.

    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");
        });
    });
    

Creare e gestire attività di esportazione

Dopo aver abilitato la cronologia di esportazione, usare il comando ExportHistoryClient per creare e gestire i processi.

Creare un processo di esportazione batch

Nell'esempio seguente, un processo di esportazione batch esporta tutte le istanze di orchestrazione che hanno raggiunto uno stato terminale in un intervallo di tempo fisso.

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();

Creare un'attività di esportazione continua

Nell'esempio seguente, un processo di esportazione continua accoda le istanze del terminale in modo continuo a partire da un'ora di inizio.

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

ExportHistoryJobClient jobClient = await exportClient.CreateJobAsync(options);

Quando destination è Null, il processo usa il contenitore predefinito e il prefisso configurati in ExportHistoryStorageOptions.

Ottieni dettagli del lavoro di esportazione

Usare il codice seguente per recuperare la descrizione completa di un job, inclusi lo stato, i contatori di avanzamento e gli eventuali errori.

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

Annotazioni

GetJobAsync genera ExportJobNotFoundException se l'ID lavoro specificato non esiste. Gestire questa eccezione durante l'esecuzione di query per i processi che potrebbero essere stati eliminati.

ExportJobDescription include:

Proprietà Descrizione
JobId Identificatore univoco del lavoro.
Status Stato corrente: Pending, Active, Failedo Completed.
CreatedAt Al momento della creazione del lavoro.
LastModifiedAt Data dell'ultimo aggiornamento del processo.
ScannedInstances Numero totale di istanze analizzate finora.
ExportedInstances Numero totale di istanze esportate finora.
LastError Ultimo messaggio di errore, se disponibile.

Elencare i lavori

Esportare un elenco di processi attivi utilizzando del codice simile a quello mostrato nell'esempio seguente.

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 Supporta le proprietà di filtro seguenti:

Proprietà Descrizione
Status Filtrare in base allo stato del lavoro: Pending, Active, Failed o Completed.
JobIdPrefix Filtrare i processi il cui ID inizia con questo prefisso.
CreatedFrom Restituire solo i processi creati in questo momento o in seguito.
CreatedTo Restituire solo i lavori creati in o prima di questo orario.
PageSize Numero massimo di risultati per pagina.
ContinuationToken Token per il recupero della pagina successiva dei risultati.

Eliminare un lavoro

Usa il seguente codice per eliminare un job.

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

Annotazioni

DeleteAsync genera ExportJobNotFoundException se il processo non esiste. L'eliminazione di un processo non rimuove i BLOB già esportati da Archiviazione BLOB di Azure.

Opzioni per la creazione di attività di esportazione

La classe controlla il ExportJobCreationOptions comportamento del processo di esportazione e include i parametri seguenti.

Parametro Obbligatorio Descrizione Impostazione predefinita
mode Batch per una finestra fissa o Continuous per l'esportazione in corso. -
completedTimeFrom Sì (Batch) Inizio dell'intervallo di tempo (inclusivo), in base al momento in cui le istanze hanno raggiunto uno stato terminale. Per la modalità continua, l'impostazione predefinita è UtcNow se non specificata. -
completedTimeTo Sì (Batch) Fine dell'intervallo di tempo (inclusivo). Deve essere omesso per la modalità continua. Non può essere nel futuro. -
destination No Eseguire l'override del contenitore BLOB predefinito e aggiungere il prefisso a questo processo. Usa l'impostazione predefinita da ExportHistoryStorageOptions
jobId No Identificatore di lavoro personalizzato. GUID generato automaticamente
format No Formato di esportazione: JSONL (compresso da gzip) o JSON (non compresso). JSONL con gzip
runtimeStatus No Filtrare in base allo stato del terminale: Completed, Failed, Terminated. Tutti gli stati del terminale
maxInstancesPerBatch No Numero di istanze da elaborare per batch (1-1000). 100

Dove vengono archiviati i dati esportati in Archiviazione BLOB di Azure

La cronologia esportata viene scritta in Archiviazione BLOB di Azure con i parametri seguenti.

  • Contenitore: valore predefinito da EXPORT_HISTORY_CONTAINER_NAME o override di destination per processo.
  • Nome BLOB: derivato da un hash SHA-256 di (completedTimestamp, instanceId).
  • Formato file:
    • Impostazione predefinita: .jsonl.gz (righe JSON, gzip-compressed - un evento di cronologia per riga)
    • Facoltativo: .json (matrice JSON non compressa di eventi di cronologia)
  • Percorso BLOB con prefisso: quando viene configurato un prefisso (ad esempio, exports/daily), il percorso DEL BLOB diventa exports/daily/{hash}.{ext}. Senza un prefisso, il BLOB viene scritto direttamente nella radice del contenitore come {hash}.{ext}.

Ogni BLOB include un instanceId tag di metadati per la tracciabilità.

Variabili di ambiente per la configurazione della cronologia di esportazione

Usare queste variabili di ambiente con l'esempio di cronologia di esportazione di .NET Durable Task SDK.

Variable Descrizione Impostazione predefinita di esempio
DURABLE_TASK_CONNECTION_STRING Stringa di connessione del pianificatore di attività durevole Endpoint=http://localhost:8080;TaskHub=default;Authentication=None
EXPORT_HISTORY_STORAGE_CONNECTION_STRING Archiviazione di Azure stringa di connessione per i blob della cronologia esportati UseDevelopmentStorage=true
EXPORT_HISTORY_CONTAINER_NAME Contenitore BLOB per la cronologia esportata export-history
EXPORT_HISTORY_PREFIX Prefisso del percorso della cartella virtuale facoltativo per i nomi BLOB non impostato
ASPNETCORE_URLS URL di ascolto per l'host HTTP dell'esempio framework predefinito

Azure autorizzazioni per la cronologia di esportazione

Quando si usano risorse Azure anziché emulatori locali, l'identità dell'app deve accedere a Durable Task Scheduler e gestione rete virtuale di Azure:

  1. Concedere il ruolo Durable Task Data Contributor nell'hub attività dell'app.
  2. Concedere Storage Blob Data Contributor all'account di archiviazione che archivia i BLOB di cronologia esportati.

Considerazioni importanti per le attività di esportazione

  • Operazioni di eliminazione simultanee:
    Se si eliminano le istanze di orchestrazione durante l'esecuzione di un processo di esportazione, l'esportazione può essere influenzata. Le istanze eliminate prima che l'esportazione le legga non saranno presenti nei dati esportati. Evitare di eseguire operazioni di eliminazione simultaneamente con processi di esportazione attivi che coprono lo stesso intervallo di tempo.

  • Pulizia dei BLOB:
    L'eliminazione di un processo di esportazione non rimuove i BLOB esportati da Archiviazione BLOB di Azure. Se è necessario rimuovere i dati esportati, eliminare i BLOB dall'account di archiviazione separatamente.

Verificare che l'esportazione funzioni

Dopo aver creato un processo di esportazione, verificare che funzioni controllando entrambi i segnali:

  • Lo stato del processo passa da Pending a Active e alla fine a Completed (per la modalità Batch).
  • Le voci blob vengono visualizzate nel contenitore di esportazione configurato.

È possibile eseguire il polling dello stato del processo a livello di codice:

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);

Per lo sviluppo locale, eseguire questo comando interfaccia della riga di comando di Azure per esaminare il contenitore:

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

Suggerimento

L'esempio ExportHistoryWebApp include un file ExportHistoryWebApp.http con richieste client REST pronte per VS Code. Aprirlo e fare clic su Invia richiesta per testare rapidamente le operazioni di creazione, recupero, elenco ed eliminazione.

Passaggi successivi