Lightning.Workflows.Stats (Lightning v2.19.0-pre)
View SourceStats for a single workflow, shaped for the workflow health page.
One public function per chart, each returning only what that chart draws, so a cheap chart renders without waiting on an expensive one.
A failed work order is attributed to every failing step of its latest run, so a run that broke in two branches is a row in both. Each row counts work orders, not steps, which means the rows can sum past the failure total the donuts draw.
Deliberately independent of Lightning.DashboardStats, which serves the
workflow list view: it batches across many workflows to avoid an N+1 while
this page queries one, and it collapses every failure state into a single
:failed bucket — the granularity both donuts need apart.
Summary
Types
One bar of the runs chart: when its slot starts, and its counts.
Functions
Failed work orders grouped by error signature over the last days_back days.
Work order counts by final state over the last days_back days.
Final run counts per state, bucketed across the last days_back days:
2-hourly over a day, AM/PM over a week, daily over a month.
Types
@type run_bucket() :: %{:at => DateTime.t(), optional(atom()) => non_neg_integer()}
One bar of the runs chart: when its slot starts, and its counts.
Functions
Failed work orders grouped by error signature over the last days_back days.
The signature's parts are returned separately rather than as one string: the
table styles each part differently, and the tip is looked up by error_type.
A count is the number of work orders that hit that signature, so a work order that failed in two branches is counted once under each. That makes the rows sum past the failure total the outcomes donut draws, which is the trade: a second broken branch is its own thing to fix, not fallout from the first.
Work order counts by final state over the last days_back days.
@spec runs(Lightning.Workflows.Workflow.t(), 1 | 7 | 30) :: %{ window: %{from: DateTime.t(), to: DateTime.t()}, buckets: [run_bucket()] }
Final run counts per state, bucketed across the last days_back days:
2-hourly over a day, AM/PM over a week, daily over a month.
Bucketed here rather than in the browser, because the alternative is shipping every run in the window — six figures of rows on a busy workflow, cached whole and JSON-encoded — to draw thirty bars.
Buckets are counted on inserted_at — when the attempt started, not when it
settled — so a run stays in the bar the traffic arrived in. Every bucket and
every state is present, zero-filled: the chart draws a flat window without
reasoning about which bars are missing.
The last bucket is the one now falls in, so it is still filling; the first
reaches back past now - days_back, so nothing in the window goes undrawn.
window is the range the bars actually cover.
A bucket is at alongside one key per state, flat rather than nested, which
is the row shape Recharts takes as data — the list goes to the chart
untouched, and each Bar names the state it draws.