Interface DurableExecutionPlugin


public interface DurableExecutionPlugin
Plugin interface for instrumenting durable execution lifecycle events.

Implement this interface to integrate observability tools (OpenTelemetry, Datadog, etc.) with the durable execution SDK. The SDK calls these hooks at key lifecycle points without requiring modifications to core SDK code.

All methods have default no-op implementations, allowing plugins to override only the hooks they need.

Non-fatal plugin failures are caught and logged without disrupting SDK execution. VirtualMachineError and ThreadDeath propagate, including when wrapped by asynchronous completion/future exceptions.

  • Method Details

    • providePropagationMetadata

      default PropagationMetadata providePropagationMetadata(PropagationInput input)
      Optionally supplies operation-level trace propagation metadata synchronously. Return null to abstain. This hook runs when creating a new invoke START checkpoint after the operation-start hook. Replaying a checkpointed START or terminal result does not call it; an uncommitted START may call it again on a later invocation. Produce metadata deterministically from the input without mutating execution state or creating side effects.
    • providePropagationMetadata

      default String providePropagationMetadata(String executionArn, String operationId, String parentOperationId, String targetFunctionName)
      Optional layer-compatible X-Ray producer capability. String-only linkage lets a new plugin layer keep loading on older cores that do not know PropagationInput/PropagationMetadata; those cores simply never call this hook. The typed hook above is the preferred core contract and adapts this capability into its immutable result.
    • onInvocationStart

      default void onInvocationStart(InvocationInfo info)
      Called at the start of each Lambda invocation. Use to set up per-invocation state (trace ID, invocation span).

      Check InvocationInfo.isFirstInvocation() to detect the first invocation of an execution (useful for sampling decisions or execution-level span creation). The runtime-thread snapshot is available through InvocationInfo.xRayTraceId().

    • onInvocationEnd

      default void onInvocationEnd(InvocationEndInfo info)
      Called at the end of each Lambda invocation. Use to flush spans/metrics before Lambda freezes.

      This hook runs on the root handler thread after body/scope unwinding, operation and checkpoint drain, and output preparation. It is awaited before the invocation returns and is the safe flush point before Lambda freezes the execution environment.

      Check InvocationEndInfo.invocationStatus() to detect if the execution reached a terminal state in this invocation (useful for writing summary records or flushing final data).

    • onOperationStart

      default void onOperationStart(OperationInfo info)
      Called when an operation starts (including replay). Use for logging/metrics that want replay visibility.
    • onOperationEnd

      default void onOperationEnd(OperationEndInfo info)
      Called once when an operation's terminal status is first observed.

      This is usually the invocation that completes the operation, but it can also be a later invocation that first observes a completion which happened while the execution was suspended (for example an operation that finished during a wait). In that case OperationEndInfo.isReplay() is true, so do not assume this hook only fires with isReplay() == false. It does not fire again on subsequent replays of an already-observed completion.

      The OTel plugin creates operation spans here with backfilled start/end timestamps (emitting a linked continuation span when the completion is observed on a replaying invocation).

    • onOperationChange

      default void onOperationChange(OperationChangeInfo info)
      Called when a checkpoint response changes the status of one or more operations.

      Receives the operations that changed and a snapshot of all operations.

    • onUserFunctionStart

      default void onUserFunctionStart(UserFunctionStartInfo info)
      Called when a user-provided function starts executing. This fires for both step attempts (with attempt set) and child context functions (with attempt null).

      This hook fires on the same thread as user code, so plugins can set OTel context via Context.makeCurrent() here.

    • onUserFunctionEnd

      default void onUserFunctionEnd(UserFunctionEndInfo info)
      Called when a user-provided function finishes executing. This fires for both step attempts and child context functions.

      This hook fires on the same thread as user code, so plugins can close OTel scopes here.

      If a later plugin's start hook fails fatally, plugins whose start hooks completed successfully receive this hook in reverse order on the same thread, with UserFunctionOutcome.FAILED and the original fatal error. The user function does not run in that case. Cleanup failures do not replace the original start-hook error.

      It fires for every outcome of the user function: normal return, a thrown failure, and suspension. Check UserFunctionEndInfo.outcome() to distinguish them. A suspended function reports UserFunctionOutcome.INCOMPLETE; its UserFunctionEndInfo.error() is the SDK's internal SuspendExecutionException, not a user error.