Skip to Content
Evaluate Get Started

Process Logs

Key takeaways

Process Logs automatically record every state change on a process instance, capturing the source and destination activity, timestamp, actor identity, and trigger for each transition. The history is stored in the same persistence provider as process instances and is queryable through GetProcessHistoryAsync. Each ProcessHistoryItem entry includes the transition duration, classifier, and executor identity - providing a complete audit trail for compliance without custom logging code. A separate runtime log via IProcessLogProvider captures operational events and exceptions during execution.

Compliance regulations such as HIPAA, SOX, and GDPR require a record of who moved a process from one state to another and when. Without built-in logging, every workflow system needs custom code to capture audit data - and auditors need to trust that the data is complete.

Workflow Engine records every state change on a process instance automatically, creating a permanent audit trail of every transition, timer firing, and command execution. Each entry captures the source and destination activity, the timestamp, the actor identity, and the trigger that caused the change.

With Process Logs, you get a complete, queryable history of every process instance from start to completion - with no custom logging code. For example, after a purchase order is approved, the log shows who approved it, when, from which activity, and whether a timer or user command triggered the transition.

What it is

Every time a process instance changes activity - through a command, a timer firing, setting state directly, or any other mechanism that triggers a transition - the runtime writes a history record to the persistence provider. Think of it as a black box for each process instance: every state change is recorded automatically, and the sequence of entries reconstructs the exact path the instance followed through the scheme.

The history is stored separately from the active instance state. You can query the log for a completed instance, a running instance, or even an instance that has been deleted from the active store - as long as the history table still has the data.

For developers: The ProcessHistoryItem class captures each transition. Query it with GetProcessHistoryAsync(processId, paging) on WorkflowRuntime, which returns a List<ProcessHistoryItem> ordered by timestamp.

// Get the full history for a process instanceList<ProcessHistoryItem> history = await runtime    .GetProcessHistoryAsync(processId);foreach (var entry in history){    Console.WriteLine(        $"[{entry.TransitionTime:u}] {entry.FromActivityName} " +        $"-> {entry.ToActivityName} by {entry.ActorIdentityId}");}

What each log entry contains

ProcessHistoryItem captures the following data for every state change:

Process history item fields
FieldDescription
ProcessIdThe process instance ID
FromActivityNameThe source activity name before the transition
FromStateNameThe source state name (if set on the activity)
ToActivityNameThe destination activity name after the transition
ToStateNameThe destination state name (if set on the activity)
TransitionTimeUTC timestamp when the transition executed
StartTransitionTimeUTC timestamp when the transition started executing
TransitionDurationDuration of the transition execution in milliseconds
TransitionClassifierClassifier of the transition direction (direct, or other)
TriggerNameThe command or timer name that triggered the transition
ActorIdentityIdThe user ID on whose behalf the command was executed
ExecutorIdentityIdThe user ID who executed the command
ActorNameThe user name on whose behalf the command was executed
ExecutorNameThe user name who executed the command
IsFinalisedWhether this transition finalized the process

Separate runtime logging

In addition to the transition history, Workflow Engine has a separate runtime log system via IProcessLogProvider. This captures runtime-level events - messages, errors, exceptions - as ProcessLogEntry objects. The default implementation is MemoryProcessLogger(100, 100), which keeps the last 100 entries per process for up to 100 processes in memory.

// Configure a custom process log providerruntime.WithProcessLogger(new MyDatabaseProcessLogger());

The runtime log is distinct from the transition history. Transition history records state changes; the process log records operational events, exceptions, and debugging information during execution.

Paging support

For instances with many transitions, use the Paging parameter with GetProcessHistoryAsync to paginate results:

var firstPage = await runtime.GetProcessHistoryAsync(    processId, new Paging(1, 50));var totalCount = await runtime.GetProcessHistoryCountAsync(processId);

Why it matters

Process Logs deliver these outcomes:

  • Audit-ready compliance - Every state change is recorded by default. The ProcessHistoryItem contains actor identity, timestamp, and the transition taken - exactly what compliance frameworks require. No custom logging code needed.

  • Faster debugging - When a process takes an unexpected path, the log shows every transition the instance followed, the timestamps, and the actor that triggered each step. This is faster and more reliable than reproducing the sequence by re-running the process.

  • Complete path reconstruction - The sequence of log entries, from the initial activity through every transition to completion (or current activity), reconstructs the exact path the instance took through the scheme.

  • Separate operational logging - The runtime log via IProcessLogProvider captures exceptions, errors, and debug messages during execution, separate from the transition history. You can query recent logs, filter by time, or paginate results.

Who it is for

Evaluator (CEO, CTO, PM): Built-in process logs satisfy audit requirements without custom development. The transition history is automatically recorded, queryable, and contains the actor identity and timestamp data that compliance audits require.

Developer: Query ProcessHistoryItem records with GetProcessHistoryAsync on WorkflowRuntime. For runtime operational logging, configure an IProcessLogProvider with WithProcessLogger() and use ProcessLogger.ReadAllAsync, ReadLastAsync, or ReadEarlyAsync to query entries.

Enterprise architect: History records are stored in the same persistence provider as process instances, so they respect the same isolation and backup policies. The Paging parameter on GetProcessHistoryAsync supports large-scale queries without loading the full history into memory.

When to use it

Process logs are valuable in any workflow that needs an audit trail or debugging capability:

  • Compliance-required audit trails - Regulated workflows (healthcare approvals, financial transactions, document sign-offs) need a permanent record of every state change. The ProcessHistoryItem captures exactly the data auditors look for.

  • Debugging unexpected workflow paths - When a process takes an unexpected route, the log shows every transition, the conditions that led to it, and the actor that triggered each step. No need to reproduce the scenario.

  • User action tracking - The ActorIdentityId and ExecutorIdentityId fields capture who performed each action and on whose behalf, making it possible to trace user activity across the workflow.

  • Performance analysis - The StartTransitionTime and TransitionDuration fields capture how long each transition took to execute, helping identify slow activities or bottlenecks.

How it compares

The following table compares Workflow Engine's automatic process logging with the alternative of custom audit logging.

Comparison of process logging approaches
ApproachWhat it requiresResult
Custom audit loggingWrite logging code in every action, maintain a separate audit table, ensure it captures all transitionsFragile, easy to miss transitions, hard to keep in sync with the scheme
Workflow Engine Process LogsTransition history is recorded automatically for every state change; query with GetProcessHistoryAsyncComplete, consistent audit trail - no custom code, no missed transitions

The ProcessHistoryItem captures every state change by default, including the transition direction classifier, trigger name (command or timer), and execution duration - data a custom logging implementation would need to reconstruct manually.

Frequently asked questions

Does Workflow Engine capture process logs automatically?

Yes. Every transition - whether triggered by a command, timer, direct state change, or subprocess completion - writes a ProcessHistoryItem to the persistence provider. No configuration is needed to enable it.

What data does each process log entry capture?

Each ProcessHistoryItem records the source and destination activity names, the source and destination state names, the UTC transition time, the start transition time and duration, the transition classifier, the trigger name (command or timer), the actor identity, the executor identity, and whether the transition finalized the process.

Is the process log stored with the same persistence provider?

Yes. The transition history is stored in the same persistence provider (MSSQL, PostgreSQL, MySQL, etc.) as the process instances. It is a separate table indexed by process instance ID.

Is there a separate runtime log for debugging?

Yes. The runtime has an IProcessLogProvider interface (implemented by MemoryProcessLogger by default) that captures operational messages, exceptions, and debugging events during execution. This is separate from the ProcessHistoryItem transition history.

Can I customize what data gets logged during a state change?

The ProcessHistoryItem fields are fixed and automatically populated. For custom operational data, use the IProcessLogProvider runtime log, which accepts ProcessLogEntry objects with a free-form Properties field (JObject) and Message string.

See also