Table of Contents

Class OpenTelemetryOperationMiddleware

Namespace
WorkflowForge.Extensions.Observability.OpenTelemetry
Assembly
WorkflowForge.Extensions.Observability.OpenTelemetry.dll

Creates one span per operation and records operation metrics, honouring the WorkflowForgeOpenTelemetryOptions the foundry was enabled with.

public sealed class OpenTelemetryOperationMiddleware : IWorkflowOperationMiddleware
Inheritance
OpenTelemetryOperationMiddleware
Implements
Inherited Members

Constructors

OpenTelemetryOperationMiddleware(WorkflowForgeOpenTelemetryService)

Initializes a new instance of the OpenTelemetryOperationMiddleware class.

public OpenTelemetryOperationMiddleware(WorkflowForgeOpenTelemetryService service)

Parameters

service WorkflowForgeOpenTelemetryService

The telemetry service that owns the activity source and meter.

Exceptions

ArgumentNullException

Thrown when service is null.

Methods

ExecuteAsync(IWorkflowOperation, IWorkflowFoundry, object?, Func<CancellationToken, Task<object?>>, CancellationToken)

Executes the operation middleware logic.

public Task<object?> ExecuteAsync(IWorkflowOperation operation, IWorkflowFoundry foundry, object? inputData, Func<CancellationToken, Task<object?>> next, CancellationToken cancellationToken = default)

Parameters

operation IWorkflowOperation

The operation being executed.

foundry IWorkflowFoundry

The foundry context providing properties, logger, and services.

inputData object

Input data passed to the operation.

next Func<CancellationToken, Task<object>>

Delegate to invoke the next middleware in the pipeline or the operation itself. Call this to continue the operation execution. Not calling this will short-circuit the operation.

cancellationToken CancellationToken

Cancellation token for the operation execution.

Returns

Task<object>

A task representing the operation execution result. The result can be null or any object depending on the operation.

Remarks

Middleware should:

  • Call next(cancellationToken) to continue operation execution
  • Handle exceptions appropriately (log, transform, or rethrow)
  • Clean up resources in finally blocks
  • Respect cancellation tokens
  • Preserve operation results unless intentionally transforming them

Example implementation:

public async Task<object?> ExecuteAsync(
    IWorkflowOperation operation,
    IWorkflowFoundry foundry,
    object? inputData,
    Func<CancellationToken, Task<object?>> next,
    CancellationToken cancellationToken)
{
    // Pre-execution logic
    Logger.LogInformation("Starting operation: {Name}", operation.Name);

    try
    {
        // Execute operation
        var result = await next(cancellationToken).ConfigureAwait(false);

        // Post-execution logic (success)
        Logger.LogInformation("Operation completed: {Name}", operation.Name);
        return result;
    }
    catch (Exception ex)
    {
        // Post-execution logic (failure)
        Logger.LogError(ex, "Operation failed: {Name}", operation.Name);
        throw;
    }
}

Exceptions

OperationCanceledException

Thrown when the operation execution is cancelled.