Skip to content

feat: execution analytics pipeline (backend) — engine reports stats, platform stores + serves#149

Merged
Pama-Lee merged 1 commit into
mainfrom
feat/execution-analytics-backend
Jul 5, 2026
Merged

feat: execution analytics pipeline (backend) — engine reports stats, platform stores + serves#149
Pama-Lee merged 1 commit into
mainfrom
feat/execution-analytics-backend

Conversation

@Pama-Lee

@Pama-Lee Pama-Lee commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

Fixes "Studio shows zero execution data." Execution counts lived only in each engine's local Prometheus registry; nothing flowed to the control plane. This wires the full backend pipeline so Studio can chart call volume, decision-code distribution, and latency. (The Studio view is PR-2.)

Data flow

engine prometheus::gather() → NATS ServerExecutionStats (every ~60s) → platform worker ingest → execution_metric_snapshots (raw cumulative) → analytics API diffs consecutive snapshots into time-bucketed rates → Studio.

Engine (ordo-server)

  • SyncEvent::ServerExecutionStats carrying per-ruleset cumulative counters (exec success/error, terminal decision codes, duration count+sum).
  • sync/exec_stats.rs reads them structurally from prometheus::gather() (no text parsing), groups by ruleset. Published from the NATS presence task, skipped when empty.

Platform (ordo-platform)

  • Mirrors the enum; the control consumer already filters control.> so servers.stats needs no filter change.
  • Worker ingest arm resolves the org from server_id (the engine doesn't know its own org — same keying as heartbeats) and appends snapshots.
  • Migration 0021_execution_metric_snapshots + store/execution_metrics.rs (insert / fetch / prune / project-ruleset + server-org lookups).
  • analytics.rs: reset-safe delta aggregation of cumulative snapshots into time-bucketed rates (handles engine restarts, isolates per-server), served at GET /api/v1/orgs/:oid/projects/:pid/analytics (resolve_project auth, scoped to the project's rulesets). 30-day retention sweep on the existing maintenance loop.

Why diffing

Prometheus counters are cumulative and reset to 0 on restart. Storing raw snapshots + diffing consecutive ones (reset-safe: new < old ⇒ the new value is the delta) is robust to dropped/duplicated NATS messages.

Verification

  • Unit: aggregation (delta / reset-safety / per-server isolation / range parsing) + exec_stats grouping.
  • cargo test -p ordo-platform --lib (32) + -p ordo-server --features nats-sync (180) green; clippy clean.
  • All SQL validated against a real Postgres: the full migration chain (incl. 0021) applies, and the snapshot insert + ANY($4::text[]) fetch + JSONB extraction all run.

Deploy note

Requires engine↔platform NATS (Lumo has it). Deploy the platform worker before the engine — an unknown event type fails deserialize and is dropped (lost stats during the window, no crash).

Part 1 of 2 — PR-2 adds the Studio Analytics view (echarts).

…tores + serves

The control plane could show nothing about running decisions because execution
counts lived only in each engine's local Prometheus registry. This wires the
full pipeline so Studio can chart call volume, decision-code distribution, and
latency (backend half; the Studio view follows).

Engine (ordo-server):
- New SyncEvent::ServerExecutionStats carrying per-ruleset cumulative counters
  (exec success/error, terminal decision codes, duration count+sum).
- sync/exec_stats.rs reads them structurally from prometheus::gather() and
  groups by ruleset; the NATS presence task publishes every ~60s (skips empty).

Platform (ordo-platform):
- Mirrors the SyncEvent variant; the control consumer already filters control.>
  so the new servers.stats subject needs no filter change.
- Worker ingest arm resolves org from server_id and appends snapshots; migration
  0021 + store/execution_metrics.rs (insert / fetch / prune / lookups).
- analytics.rs: reset-safe delta aggregation into time-bucketed rates, served at
  GET /api/v1/orgs/:oid/projects/:pid/analytics (resolve_project auth, scoped to
  the project's rulesets). 30-day retention sweep.

Counters are cumulative + reset on restart, so the platform diffs consecutive
snapshots — unit-tested incl. reset-safety + per-server isolation. All SQL
validated against a real Postgres. Requires engine<->platform NATS; deploy the
worker before the engine.

Tests: aggregation (4) + exec_stats (1); ordo-platform lib (32) + ordo-server
(180) green; clippy clean.
@vercel

vercel Bot commented Jul 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ordo_docs Ready Ready Preview, Comment Jul 5, 2026 5:11pm
ordo-app Error Error Jul 5, 2026 5:11pm

@Pama-Lee Pama-Lee merged commit 7e309bc into main Jul 5, 2026
15 of 16 checks passed
Pama-Lee added a commit that referenced this pull request Jul 5, 2026
Adds the Analytics tab to a project — the UI half of the execution-analytics
pipeline. Renders live call volume, decision-code distribution, and latency
from the platform's /analytics endpoint.

- AnalyticsView.vue: range picker (1h/24h/7d), totals tiles (calls / error
  rate / avg latency / active rulesets), a traffic-over-time line chart
  (calls + errors), a decision-distribution pie, and a per-ruleset table.
  Charts use echarts, lazy-imported (raw, matching the docs app) so it
  code-splits out of the main bundle. Empty state hints that the engine needs
  NATS connectivity to the platform.
- analyticsApi + AnalyticsResponse types + useAnalyticsStore.
- Route (project-analytics), an 'Analytics' project nav tab, and i18n across
  all three locales (en / zh-CN / zh-TW).

Typecheck + production build clean; the AnalyticsView + echarts are separate
lazy chunks. Pairs with #149 (backend).
Pama-Lee added a commit that referenced this pull request Jul 5, 2026
Patch release to ship the execution-analytics reporter (#149) in the engine
image. Bumps the engine/server crates 0.5.0 -> 0.5.1; the CLI family stays on
the workspace version (0.5.0). Tagging v0.5.1 builds
ghcr.io/ordo-engine/ordo:0.5.1 with the ServerExecutionStats push, so a
connected engine starts reporting execution stats to the platform.
@Pama-Lee Pama-Lee deleted the feat/execution-analytics-backend branch July 6, 2026 09:53
Pama-Lee added a commit that referenced this pull request Jul 6, 2026
…tores + serves (#149)

The control plane could show nothing about running decisions because execution
counts lived only in each engine's local Prometheus registry. This wires the
full pipeline so Studio can chart call volume, decision-code distribution, and
latency (backend half; the Studio view follows).

Engine (ordo-server):
- New SyncEvent::ServerExecutionStats carrying per-ruleset cumulative counters
  (exec success/error, terminal decision codes, duration count+sum).
- sync/exec_stats.rs reads them structurally from prometheus::gather() and
  groups by ruleset; the NATS presence task publishes every ~60s (skips empty).

Platform (ordo-platform):
- Mirrors the SyncEvent variant; the control consumer already filters control.>
  so the new servers.stats subject needs no filter change.
- Worker ingest arm resolves org from server_id and appends snapshots; migration
  0021 + store/execution_metrics.rs (insert / fetch / prune / lookups).
- analytics.rs: reset-safe delta aggregation into time-bucketed rates, served at
  GET /api/v1/orgs/:oid/projects/:pid/analytics (resolve_project auth, scoped to
  the project's rulesets). 30-day retention sweep.

Counters are cumulative + reset on restart, so the platform diffs consecutive
snapshots — unit-tested incl. reset-safety + per-server isolation. All SQL
validated against a real Postgres. Requires engine<->platform NATS; deploy the
worker before the engine.

Tests: aggregation (4) + exec_stats (1); ordo-platform lib (32) + ordo-server
(180) green; clippy clean.
Pama-Lee added a commit that referenced this pull request Jul 6, 2026
Adds the Analytics tab to a project — the UI half of the execution-analytics
pipeline. Renders live call volume, decision-code distribution, and latency
from the platform's /analytics endpoint.

- AnalyticsView.vue: range picker (1h/24h/7d), totals tiles (calls / error
  rate / avg latency / active rulesets), a traffic-over-time line chart
  (calls + errors), a decision-distribution pie, and a per-ruleset table.
  Charts use echarts, lazy-imported (raw, matching the docs app) so it
  code-splits out of the main bundle. Empty state hints that the engine needs
  NATS connectivity to the platform.
- analyticsApi + AnalyticsResponse types + useAnalyticsStore.
- Route (project-analytics), an 'Analytics' project nav tab, and i18n across
  all three locales (en / zh-CN / zh-TW).

Typecheck + production build clean; the AnalyticsView + echarts are separate
lazy chunks. Pairs with #149 (backend).
Pama-Lee added a commit that referenced this pull request Jul 6, 2026
Patch release to ship the execution-analytics reporter (#149) in the engine
image. Bumps the engine/server crates 0.5.0 -> 0.5.1; the CLI family stays on
the workspace version (0.5.0). Tagging v0.5.1 builds
ghcr.io/ordo-engine/ordo:0.5.1 with the ServerExecutionStats push, so a
connected engine starts reporting execution stats to the platform.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant