Exportar histórico de orquestração com o Durable Task Scheduler (versão preliminar)

A funcionalidade de exportação do histórico de orquestração permite à sua aplicação extrair históricos de execução para instâncias de orquestração de terminais (estado concluído, falhado ou terminado) de Durable Task Scheduler e escrevê-los em Armazenamento de Blobs do Azure. Use esta funcionalidade para auditoria, conformidade, análises e arquivamento a longo prazo de dados de orquestração fora do escalonador.

Observação

A funcionalidade de exportação do histórico de orquestração está atualmente em pré-visualização e disponível para o SDK Durable Task .NET. Requer o pacote Microsoft.DurableTask.ExportHistory.

Sugestão

Uma amostra de referência completa e executável está disponível em ExportHistoryWebApp. Recomendamos usá-lo como referência enquanto segue este guia.

Como funciona a exportação do histórico de orquestração

O histórico de exportação utiliza entidades duráveis e orquestrações internamente para gerir tarefas de exportação de forma fiável, utilizando o seguinte processo.

  1. Cria um trabalho de exportação através do ExportHistoryClient, especificando uma janela temporal e o modo de exportação.
  2. O SDK cria uma entidade duradoura (ExportJob) que acompanha o estado e o progresso do trabalho.
  3. Uma orquestração interna lista instâncias de orquestração de terminais que correspondem à janela temporal e aos filtros de estado especificados.
  4. Para cada instância correspondente, uma atividade recupera o histórico completo de execução do Durable Task Scheduler.
  5. O histórico dos dados é serializado (JSONL com compressão gzip por padrão) e escrito no Armazenamento de Blobs do Azure.
  6. O trabalho verifica o seu progresso, por isso pode retomar se for interrompido.

Modos de exportação para trabalhos em lote e contínuos

O histórico de exportação suporta dois modos:

Mode Comportamento
Batch Exporta instâncias que atingiram um estado terminal dentro de uma janela de tempo fixa (completedTimeFrom para completedTimeTo), e depois marca o trabalho como concluído.
Contínuo As instâncias do terminal são processadas continuamente a partir de completedTimeFrom, sem fim definido. A tarefa mantém-se ativa até a apagares.

Pré-requisitos

  • .NET 8 SDK ou posterior
  • Um hub de tarefas do Durable Task Scheduler (ou o emulador local)
  • Uma conta Armazenamento do Azure (ou Azurite para desenvolvimento local)
  • Os seguintes pacotes NuGet:
    • Microsoft.DurableTask.ExportHistory
    • Microsoft.DurableTask.Client.AzureManaged
    • Microsoft.DurableTask.Worker.AzureManaged

Permitir a exportação do histórico de orquestração

  1. Instala o pacote de histórico de exportação.

    dotnet add package Microsoft.DurableTask.ExportHistory
    
  2. Instale os pacotes de cliente e trabalhador geridos pelo Azure para o Durable Task Scheduler.

    dotnet add package Microsoft.DurableTask.Client.AzureManaged
    dotnet add package Microsoft.DurableTask.Worker.AzureManaged
    
  3. Regista o histórico de exportação tanto do trabalhador como do cliente.

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

Criar e gerir empregos de exportação

Depois de ativares o histórico de exportação, usa o ExportHistoryClient para criar e gerir jobs.

Criar um trabalho de exportação em lote

No exemplo seguinte, um trabalho de exportação em lote exporta todas as instâncias de orquestração que atingiram um estado terminal dentro de uma janela de tempo fixa.

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

Criar um trabalho de exportação contínuo

No exemplo seguinte, uma tarefa de exportação contínua rastreia as instâncias terminais indefinidamente a partir de um momento inicial.

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

ExportHistoryJobClient jobClient = await exportClient.CreateJobAsync(options);

Quando destination é nulo, a tarefa utiliza o contentor predefinido e o prefixo configurados em ExportHistoryStorageOptions.

Obtenha detalhes do trabalho de exportação

Use o código seguinte para obter a descrição completa de um trabalho, incluindo o seu estado, contadores de progresso e quaisquer erros.

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

Observação

GetJobAsync lança ExportJobNotFoundException se o ID de trabalho especificado não existir. Lide com esta exceção ao consultar trabalhos que possam ter sido eliminados.

O ExportJobDescription inclui:

Propriedade Descrição
JobId O identificador de trabalho exclusivo.
Status Estado atual: Pending, Active, Failed, ou Completed.
CreatedAt Quando o cargo foi criado.
LastModifiedAt Quando a vaga foi atualizada pela última vez.
ScannedInstances Número total de instâncias digitalizadas até agora.
ExportedInstances Número total de instâncias exportadas até agora.
LastError Última mensagem de erro, se houver.

Listar vagas

Exporte uma lista de trabalhos ativos usando código semelhante ao seguinte exemplo.

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

O ExportJobQuery suporta as seguintes propriedades do filtro:

Propriedade Descrição
Status Filtrar por estado do trabalho: Pending, Active, Failed, ou Completed.
JobIdPrefix Filtra trabalhos cujo ID começa com este prefixo.
CreatedFrom Só devolvam os empregos criados nessa altura ou depois deste período.
CreatedTo Apenas devolvam empregos criados nessa altura ou antes.
PageSize Número máximo de resultados por página.
ContinuationToken Token para recuperar a página seguinte de resultados.

Eliminar um trabalho

Use o código seguinte para eliminar um trabalho.

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

Observação

DeleteAsync lança uma exceção se ExportJobNotFoundException o trabalho não existir. Eliminar um trabalho não remove blobs já exportados do Armazenamento de Blobs do Azure.

Opções de criação de emprego para exportação

A ExportJobCreationOptions classe controla o comportamento de tarefas de exportação e inclui os seguintes parâmetros.

Parâmetro Obrigatório Descrição Predefinição
mode Sim Batch para uma janela fixa ou Continuous para exportação contínua.
completedTimeFrom Sim (Lote) Início da janela temporal (inclusive), com base em quando as instâncias atingiram um estado terminal. Para o modo Contínuo, o padrão é UtcNow se não for fornecido.
completedTimeTo Sim (Lote) Fim da janela temporal (inclusive). Deve ser omitido para o modo Contínuo. Não pode ser no futuro.
destination No Substitua o contentor e prefixo padrão do blob para este trabalho. Utiliza o padrão de ExportHistoryStorageOptions
jobId No Identificador de trabalho personalizado. GUID gerado automaticamente
format No Formato de exportação: JSONL (comprimido em gzip) ou JSON (não comprimido). JSONL com gzip
runtimeStatus No Filtrar por estados terminais: Completed, Failed, Terminated. Todos os estados dos terminais
maxInstancesPerBatch No Número de instâncias a processar por lote (1–1000). 100

Onde os dados exportados são armazenados no Armazenamento de Blobs do Azure

O histórico exportado é escrito no Armazenamento de Blobs do Azure com os seguintes parâmetros.

  • Contentor: por predefinição de EXPORT_HISTORY_CONTAINER_NAME, ou substituição por tarefa destination.
  • Nome do blob: derivado de um hash SHA-256 de (completedTimestamp, instanceId).
  • Formato de ficheiro:
    • Predefinido: .jsonl.gz (Linhas JSON, comprimido em gzip — um evento de histórico por linha)
    • Opcional: .json (array JSON não comprimido de eventos históricos)
  • Caminho do blob com prefixo: quando um prefixo é configurado (por exemplo, exports/daily), o caminho do blob torna-se exports/daily/{hash}.{ext}. Sem prefixo, o blob é escrito diretamente na raiz do contentor como {hash}.{ext}.

Cada blob inclui uma instanceId etiqueta de metadados para rastreabilidade.

Variáveis de ambiente para configuração do histórico de exportação

Use estas variáveis de ambiente com o exemplo de histórico de exportação do Durable Task .NET SDK.

Variable Descrição Exemplo padrão
DURABLE_TASK_CONNECTION_STRING Cadeia de conexão do Durable Task Scheduler Endpoint=http://localhost:8080;TaskHub=default;Authentication=None
EXPORT_HISTORY_STORAGE_CONNECTION_STRING Armazenamento do Azure cadeia de ligação para blobs de histórico exportados UseDevelopmentStorage=true
EXPORT_HISTORY_CONTAINER_NAME Contentor de blob para histórico exportado export-history
EXPORT_HISTORY_PREFIX Prefixo opcional de caminho de pasta virtual para nomes de blobs unset
ASPNETCORE_URLS URLs de escuta para o host HTTP do exemplo padrão do framework

Permissões do Azure para o histórico de exportação

Quando usa recursos do Azure em vez de emuladores locais, a identidade da aplicação precisa de acesso ao Durable Task Scheduler e ao Armazenamento de Blobs:

  1. Autorizar Durable Task Data Contributor no hub de tarefas da app.
  2. Conceda Storage Blob Data Contributor na conta de armazenamento que armazena os blobs de histórico exportados.

Considerações importantes para os empregos de exportação

  • Operações de purga simultâneas:
    Se eliminar instâncias de orquestração enquanto um trabalho de exportação está em execução, a exportação pode ser afetada. As instâncias que são eliminadas antes de serem lidas pela exportação estarão em falta nos dados exportados. Evite executar operações de purga em simultâneo com trabalhos de exportação ativos que cobrem a mesma janela temporal.

  • Limpeza de blobs:
    Eliminar um trabalho de exportação não remove os blobs exportados do Armazenamento de Blobs do Azure. Se precisares de remover dados exportados, elimina os blobs da conta de armazenamento separadamente.

Verifique se a exportação funciona

Depois de criar um trabalho de exportação, verifique se funciona verificando ambos os sinais:

  • O estado da tarefa transita de Pending para Active e, eventualmente, para Completed (para o modo de processamento em lote).
  • As entradas do blob aparecem no contentor de exportação configurado.

Pode consultar o estado do emprego de forma programática:

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

Para desenvolvimento local, execute este comando CLI do Azure para inspecionar o contentor:

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

Sugestão

O exemplo ExportHistoryWebApp inclui um ficheiro ExportHistoryWebApp.http com pedidos REST Client prontos para VS Code. Abre-o e clica em Enviar Pedido para testar rapidamente as operações de criar, obter, listar e eliminar.

Passos seguintes