On this page

Processes and event logs

A lifecycle says which states a row's history contains. A process says how that history unfolds: which step follows which, how often a case loops back (a reopened ticket, a failed payment retried, a claim sent back for more documents), and how long each step takes. It writes one row per event, the shape process-mining tools read.

YAML
tables:
  tickets:
    rows: 5000
    columns:
      ticket_id: {type: int, primary_key: true}
      opened_at: {type: datetime, start: "2024-01-01", end: "2024-06-30"}
      status: {type: text}

processes:
  - name: ticket_flow
    cases_table: tickets
    case_key: ticket_id
    start_column: opened_at          # the first event is at the case's start
    initial: opened
    transitions:                     # a state with no row is terminal (closed)
      opened:    {triaged: 1.0}
      triaged:   {resolved: 0.85, escalated: 0.15}
      escalated: {resolved: 1.0}
      resolved:  {closed: 0.9, reopened: 0.1}
      reopened:  {triaged: 1.0}
    dwell:                           # time in a state before leaving it
      opened: {distribution: lognormal, mu: 0, sigma: 0.8, unit: hours}
      "escalated->resolved": {distribution: exponential, scale: 2, unit: days}
    final_state_column: status       # the ticket agrees with its log
    max_steps: 25                    # bounds rework loops

This produces a ticket_flow_events table (event_id, ticket_id, step, activity, timestamp; names configurable) next to tickets, from Python, YAML, dict schemas and the CLI alike.

What is exact and what is drawn#

Exact, and re-checked from the rows by misata.process_audit(events, spec, cases):

  • every case starts in initial, at or after its start_column;
  • only declared transitions occur, numbered 1..n per case;
  • timestamps never go backwards, in whole seconds;
  • every case ends in a terminal state or at max_steps;
  • with final_state_column, the case row holds its log's last state.

Drawn from the declaration (emergent, not exact): which path each case takes, so the share of escalations or reopens lands near, not on, 15% and 10%; and each step's duration.

Dwell times#

Keyed by state (opened), or by one transition ("escalated->resolved"), which wins. Distributions: lognormal (mu, sigma), exponential (scale), gamma (shape, scale), uniform (min, max), fixed (value), each with a unit of seconds, minutes, hours or days. Steps without one take lognormal(0, 1) hours.

Export for process mining#

Python
misata.to_xes(tables["ticket_flow_events"], "tickets.xes", case_column="ticket_id")

writes IEEE 1849 XES, which ProM, PM4Py, Disco and Celonis import.

What it is not#

A semi-Markov chain, simulated for every case at once with numpy (200,000 tickets in about a second), not a discrete-event simulation. There are no queues or shared resources, so a step does not take longer because the system is busy. If waits that depend on load are what you need to test, that is a simulator's job (SimPy, salabim); a process here gives you the event log's structure and timing shape without one.

Prefer generating data visually?

Misata Studio lets you turn natural language prompts into relational schemas with exact outcome invariants, live preview tables, and one-click database seeding without writing code.

Last updated Edit this page.md