Skip to main content

Metrics API

Table of Contents

Top

upsquad/metrics/v1/metrics.proto

ApproverStat

ApproverStat is one row of the top-approvers leaderboard.

FieldTypeLabelDescription
member_idstringmember_id is the approver's members.id (UUID as string). May be empty when the approver was a system actor or pre-Wave-D record.
namestringname is the human-readable approver name (members.full_name) or the resolved_by string when no member row matches.
countint64count is decisions made by this approver within the window.
p50_latency_secondsdoublep50_latency_seconds is the median (resolved_at - requested_at) for the approver's decisions in the window.

FailureBreakdownRow

FailureBreakdownRow is one row of the failures breakdown table. Maps to metrics.jsx lines 175-184 (Failure / Count / Rate / Last seen / Δ).

FieldTypeLabelDescription
namestringname is the human-readable workflow name (workflows.name) — we group failures by workflow rather than by error string so the table aligns with the "owning workflow" mental model the prototype uses.
failuresint64failures is the count of workflow_runs.status='failed'.
total_runsint64total_runs is the count of workflow_runs (any status) for the same workflow over the window — the denominator for rate.
ratedoublerate is failures/total_runs as a percentage (0..100).
trenddoubletrend is period-over-period delta on failures, as a signed %.
root_causestringroot_cause is best-effort: the most-recent run's context->>'error' (or 'root_cause') for this workflow's failures. Empty string when with_root_cause is false or no JSONB key found.
last_seen_atgoogle.protobuf.Timestamplast_seen_at is the most-recent created_at among failed runs.

GetApprovalMetricsRequest

GetApprovalMetricsRequest filters the approvals throughput card. range_start / range_end bound the window over which p50/p95 latency and the top-approvers leaderboard are computed; pending counts are snapshot-only (the queue at query time) and are not windowed — matches the prototype card semantics.

FieldTypeLabelDescription
scopeMetricsScopescope filters the aggregation. Same semantics as GetWorkflowsBreakdownRequest.
scope_idstringscope_id is the UUID of the org_unit when scope is pillar/team.
range_startgoogle.protobuf.Timestamprange_start defines the latency window start; defaults to range_end - 30d.
range_endgoogle.protobuf.Timestamprange_end defines the latency window end; defaults to server now.

GetApprovalMetricsResponse

GetApprovalMetricsResponse contains the approvals card payload.

FieldTypeLabelDescription
pending_totalint64pending_total is the snapshot count of governance_approvals rows whose status='pending' (not windowed).
pending_by_agePendingByAgeBucketrepeatedpending_by_age is a 4-bucket histogram of pending rows by age (now - requested_at). Always 4 entries, ordered youngest-first.
approved_todayint64approved_today is the count of approvals whose resolved_at >= today's UTC midnight AND status='approved'. Independent of the [range_start, range_end) latency window so the "today" tiles stay anchored to wall-clock today.
rejected_todayint64rejected_today is the same but for status='denied' resolutions.
p50_latency_secondsdoublep50_latency_seconds is the median (resolved_at - requested_at) across resolved approvals within [range_start, range_end). 0 when no resolved rows fall in the window.
p95_latency_secondsdoublep95_latency_seconds is the 95th percentile of the same series.
top_approversApproverStatrepeatedtop_approvers is the leaderboard for the window, ordered by count desc with a hard cap of 10 rows.
range_startgoogle.protobuf.Timestamprange_start echoes the resolved latency window start.
range_endgoogle.protobuf.Timestamprange_end echoes the resolved latency window end.
generated_atgoogle.protobuf.Timestampgenerated_at is the server wall-clock at query time (so the frontend can label "today's" counters relative to a known anchor even when a timezone is involved on the rendering side).

GetFailuresBreakdownRequest

GetFailuresBreakdownRequest filters the failures breakdown.

FieldTypeLabelDescription
scopeMetricsScopescope filters the aggregation. Same semantics as GetWorkflowsBreakdownRequest.
scope_idstringscope_id is the UUID of the org_unit when scope is pillar/team.
range_startgoogle.protobuf.Timestamprange_start defaults to range_end - 30d.
range_endgoogle.protobuf.Timestamprange_end defaults to server wall-clock now.
top_nint32top_n caps the returned rows (default 20, max 100, clamped not rejected).
with_root_causeboolwith_root_cause asks the server to populate the root_cause field (best-effort from workflow_runs.context). False keeps the row lighter for callers that only want the count surface.

GetFailuresBreakdownResponse

GetFailuresBreakdownResponse contains the ordered top-N rows.

FieldTypeLabelDescription
rowsFailureBreakdownRowrepeatedrows is ordered by failures descending, ties broken by name asc.
range_startgoogle.protobuf.Timestamprange_start echoes the resolved window start.
range_endgoogle.protobuf.Timestamprange_end echoes the resolved window end.

GetGuardrailsBreakdownRequest

GetGuardrailsBreakdownRequest filters the guardrails breakdown.

FieldTypeLabelDescription
scopeMetricsScopescope filters the aggregation. Same semantics as GetWorkflowsBreakdownRequest.
scope_idstringscope_id is the UUID of the org_unit when scope is pillar/team.
range_startgoogle.protobuf.Timestamprange_start defaults to range_end - 30d.
range_endgoogle.protobuf.Timestamprange_end defaults to server wall-clock now.
top_nint32top_n caps the returned rows (default 20, max 100, clamped not rejected).

GetGuardrailsBreakdownResponse

GetGuardrailsBreakdownResponse contains the ordered top-N rows.

FieldTypeLabelDescription
rowsGuardrailBreakdownRowrepeatedrows is ordered by fires descending, ties broken by name asc.
range_startgoogle.protobuf.Timestamprange_start echoes the resolved window start.
range_endgoogle.protobuf.Timestamprange_end echoes the resolved window end.

GetKPIsRequest

GetKPIsRequest selects the time window and hierarchical scope. All fields are optional. When range_start / range_end are unset the service defaults to the trailing 30-day window ending at the server's wall-clock now (UTC). When scope is METRICS_SCOPE_ORG (or unspecified) the scope_id field is ignored and the caller's org_id from the ambient JWT scope is used.

Tenant identity flows from the JWT-derived scope claims (org_id) on the gRPC metadata; never from the request payload.

FieldTypeLabelDescription
scopeMetricsScopescope filters the aggregation to org / pillar / team. When unspecified or METRICS_SCOPE_ORG, the caller's org is used and scope_id is ignored.
scope_idstringscope_id is the UUID of the org_unit (pillar or team) when scope is METRICS_SCOPE_PILLAR / METRICS_SCOPE_TEAM. Ignored when scope is METRICS_SCOPE_ORG. The pillar/team filter is wired in Metrics 5/8 (#1116) via GetPillarSpend joins; the v1 GetKPIs RPC accepts the value but applies it only on the spend / workflow_runs paths (the rest of the tiles are tenant-wide reads gated by RLS).
range_startgoogle.protobuf.Timestamprange_start is the inclusive start of the query window (UTC). When unset, defaults to range_end - 30 days.
range_endgoogle.protobuf.Timestamprange_end is the exclusive end of the query window (UTC). When unset, defaults to the server's current wall-clock.

GetKPIsResponse

GetKPIsResponse holds the 8 KPI tiles plus a server-side generated_at for client-side staleness display.

FieldTypeLabelDescription
tilesKPITilerepeatedtiles is ordered (see KPITile.id documentation). Always 8 entries for v1; new tiles will be appended as the proto evolves.
generated_atgoogle.protobuf.Timestampgenerated_at is the server wall-clock at aggregation time.
range_startgoogle.protobuf.Timestamprange_start is the resolved query window start (echoed back so the frontend can render "as of …" copy without re-deriving the default window).
range_endgoogle.protobuf.Timestamprange_end is the resolved query window end.

GetPillarSpendRequest

GetPillarSpendRequest filters the pillar rollup. Pillars = org_units rows with unit_type='pillar' AND parent_id IS NULL (top-level by convention pending #1090's structural rule). v1 always queries the caller's full org (the pillar list IS the partitioning). Scope is accepted for symmetry with the rest of the service and to permit a future "pillars under this division" query when #1090 lands.

FieldTypeLabelDescription
scopeMetricsScopescope filters the aggregation. Pillar/team scopes are accepted on the surface but v1 always returns the caller's full pillar list (the partitioning IS the pillars). #1090 will narrow under a division.
scope_idstringscope_id is the UUID of the org_unit when scope is pillar/team.
range_startgoogle.protobuf.Timestamprange_start defaults to range_end - 30d.
range_endgoogle.protobuf.Timestamprange_end defaults to server wall-clock now.

GetPillarSpendResponse

GetPillarSpendResponse contains the pillar rollup rows.

FieldTypeLabelDescription
pillarsPillarSpendRowrepeatedpillars is ordered by spend descending, ties broken by name asc.
range_startgoogle.protobuf.Timestamprange_start echoes the resolved window start.
range_endgoogle.protobuf.Timestamprange_end echoes the resolved window end.

GetTimeSeriesRequest

GetTimeSeriesRequest selects one metric, scope, range, and bucket size. Tenant identity comes from the JWT scope claim (org_id); scope_id is only honoured for PILLAR/TEAM scopes (and currently only applied where the underlying source carries a team_id, identical to GetKPIs — see Metrics 5/8 #1116 follow-up).

FieldTypeLabelDescription
metric_idMetricIDmetric_id selects the time-series projection. Required; METRIC_ID_UNSPECIFIED is rejected.
scopeMetricsScopescope filters the aggregation to org / pillar / team. When unspecified or METRICS_SCOPE_ORG, the caller's org is used.
scope_idstringscope_id is the UUID of the org_unit (pillar or team). Required when scope is METRICS_SCOPE_PILLAR / METRICS_SCOPE_TEAM. See GetKPIsRequest.scope_id for the v1 limitation note.
rangeTimeSeriesRangerange selects the trailing window or CUSTOM. Defaults to TIME_SERIES_RANGE_DAYS_30 when unspecified.
custom_startgoogle.protobuf.Timestampcustom_start is the inclusive start of the query window when range == TIME_SERIES_RANGE_CUSTOM. Required for CUSTOM, ignored otherwise.
custom_endgoogle.protobuf.Timestampcustom_end is the exclusive end of the query window when range == TIME_SERIES_RANGE_CUSTOM. Required for CUSTOM, ignored otherwise.
granularityTimeSeriesGranularitygranularity selects the bucket size. Defaults to TIME_SERIES_GRANULARITY_DAY when unspecified.

GetTimeSeriesResponse

GetTimeSeriesResponse holds the ordered points plus a unit and the resolved range. Empty buckets are omitted (the frontend interpolates or renders zero — same convention as analytics.GetTokenUsageTimeSeries).

FieldTypeLabelDescription
pointsTimeSeriesPointrepeatedpoints is the ordered (date, value) series. Capped at the per- granularity limit (168/90/13) — the service rejects over-cap requests with InvalidArgument so this field length is a hard ceiling.
unitstringunit is one of {"usd", "ratio", "count", "hours", "seconds"} — the frontend formatter switches on this. Locked to a closed set so client formatters stay stable.
range_startgoogle.protobuf.Timestamprange_start is the resolved query window start (UTC).
range_endgoogle.protobuf.Timestamprange_end is the resolved query window end (UTC, exclusive).
granularityTimeSeriesGranularitygranularity is the resolved bucket size (echoed for client display).

GetWorkflowsBreakdownRequest

GetWorkflowsBreakdownRequest filters the workflows breakdown.

FieldTypeLabelDescription
scopeMetricsScopescope filters the aggregation. METRICS_SCOPE_ORG (or unspecified) queries the full org. Pillar/team scoping is accepted on the surface; pillar narrowing is wired via workflows.team_id -> org_units.ancestor_path for descendants of the requested unit.
scope_idstringscope_id is the UUID of the org_unit (pillar or team) when scope is METRICS_SCOPE_PILLAR / METRICS_SCOPE_TEAM. Required in those cases; ignored otherwise.
range_startgoogle.protobuf.Timestamprange_start mirrors GetKPIsRequest: defaults to range_end - 30d.
range_endgoogle.protobuf.Timestamprange_end mirrors GetKPIsRequest: defaults to server wall-clock now.
top_nint32top_n caps the returned rows. 0 -> default (20). > MaxBreakdownTopN is clamped, not rejected.

GetWorkflowsBreakdownResponse

GetWorkflowsBreakdownResponse contains the ordered top-N rows.

FieldTypeLabelDescription
rowsWorkflowBreakdownRowrepeatedrows is ordered by runs descending, ties broken by name asc.
range_startgoogle.protobuf.Timestamprange_start echoes the resolved window start.
range_endgoogle.protobuf.Timestamprange_end echoes the resolved window end.

GuardrailBreakdownRow

GuardrailBreakdownRow is one row of the guardrails breakdown table. "fires" = blocked + allowed. The rule_id grouping derives from agent_audit_log.detail->>'rule_id' for forward compatibility with a canonical guardrail registry; rows without a rule_id fall back to the audit row's action_type as the id, with name = the verb.

FieldTypeLabelDescription
guardrail_idstringguardrail_id is detail->>'rule_id' or the action_type fallback.
namestringname is detail->>'rule_name' or guardrail_id when not provided.
firesint64fires = blocked + allowed.
blockedint64blocked is the count of rows whose action_type='action_blocked'.
allowedint64allowed is the count of rows whose action_type='action_auto_executed' for the same rule_id.
trenddoubletrend is period-over-period delta on fires, as a signed %.

KPITile

KPITile is one of the eight tiles surfaced by GetKPIs. The order in the response array matches the headline strip ordering documented in the v3 audit (#1096 §2.11): spend → runs → success → hours saved → backlog → guardrails → agents → cost-per-run.

FieldTypeLabelDescription
idstringid is a stable identifier the frontend keys off (e.g. "spend", "runs", "success_rate"). Stable across releases — append-only.
labelstringlabel is the human-readable display name (e.g. "Total spend"). Localised on the frontend; the server returns the canonical English string for the v1 contract.
valuedoublevalue is the scalar numeric value. Cost values are USD; rate values are 0..1; counts are integers represented as double for JSON-fidelity (Connect-Web JSON). Frontend formatters decide currency / percentage / integer presentation per id.
unitstringunit is one of {"usd", "ratio", "count", "hours"} — the frontend formatter switches on this. Empty when unit is implicit in the id.

PendingByAgeBucket

PendingByAgeBucket is one row of the pending-approvals histogram. Bucket strings are stable: "<1h", "1-4h", "4-24h", ">24h" — the frontend keys off these literal labels (metrics-data.jsx pendingByAge).

FieldTypeLabelDescription
bucketstringbucket is one of the literal strings above.
countint64count is the number of pending approvals in the bucket.

PillarSpendRow

PillarSpendRow is one row of the pillar rollup table. Maps to metrics-data.jsx pillarRollup (lines 161-169) and the pillar-mode columns in metrics.jsx TeamRollupCard.

FieldTypeLabelDescription
pillar_idstringpillar_id is the org_units.id (UUID as string).
namestringname is the org_units.name (e.g. "Engineering", "Product").
agentsint64agents is the COUNT(DISTINCT a.id) of agents whose pillar_id matches this org_unit (legacy column on agents — the structural rule from #1090 will replace this with the org_unit_memberships join graph).
runsint64runs is the COUNT(*) of workflow_runs whose owning workflow's team_id sits underneath this pillar (joined via org_units ancestor_path) within the window.
spenddoublespend is SUM(usage_records.cost_usd) for usage records owned by any agent in the pillar over the window.
success_ratedoublesuccess_rate is completed/runs (0..1). 0 when runs == 0.
hours_saveddoublehours_saved is runs * HoursPerWorkflowRunHeuristic (mirrors GetKPIs). Same heuristic applies until tenants supply per- workflow baselines.
trenddoubletrend is period-over-period delta on runs, as a signed %.
lead_member_idstringlead_member_id is one member with role='lead' on the pillar org_unit (org_unit_memberships). Empty when no lead is set.
headcountint64headcount is the COUNT(DISTINCT member_id) of org_unit_memberships rows for this pillar (any role).

TimeSeriesPoint

TimeSeriesPoint is a single (timestamp, value) datum. Ordered by date ascending in the response.

FieldTypeLabelDescription
dategoogle.protobuf.Timestampdate is the bucket boundary (UTC). For HOUR this is the start of the hour; DAY the start of the day; WEEK the ISO Monday.
valuedoublevalue is the scalar metric value. Cost values are USD; latency values are seconds; rate values are 0..1; counts are integers represented as double for JSON-fidelity (Connect-Web JSON).

WorkflowBreakdownRow

WorkflowBreakdownRow is one row of the workflows breakdown table. Field shape mirrors the columns rendered in metrics.jsx lines 163-173 (Workflow / Runs / Success / Avg / Esc. / Trend).

FieldTypeLabelDescription
workflow_idstringworkflow_id is the UUID of the underlying workflows row.
namestringname is the human-readable workflow name (workflows.name).
runsint64runs is the total workflow_runs in the window.
success_ratedoublesuccess_rate is completed/runs (0..1). 0 when runs == 0.
avg_duration_secondsdoubleavg_duration_seconds averages (completed_at - started_at) over completed runs only. NaN-protected: 0 when no completed runs.
escalation_ratedoubleescalation_rate is the share of workflow_actions for runs in this window whose status is 'escalated', 0..1.
trenddoubletrend is the period-over-period delta of runs against the immediately preceding window of equal length, expressed as a signed percentage (-100..+inf). 0 when the prior window is empty.

MetricID

MetricID is the discriminator for GetTimeSeries. Each value names a single time-series projection. Append-only: existing values keep their tag numbers across releases so the frontend can pin against a stable set.

NameNumberDescription
METRIC_ID_UNSPECIFIED0METRIC_ID_UNSPECIFIED is rejected with InvalidArgument — callers must pick an explicit metric.
METRIC_ID_SPEND1METRIC_ID_SPEND — sum of usage_records.cost_usd per bucket (USD).
METRIC_ID_RUNS2METRIC_ID_RUNS — count of workflow_runs per bucket.
METRIC_ID_SUCCESS_RATE3METRIC_ID_SUCCESS_RATE — completed/total ratio per bucket (0..1).
METRIC_ID_APPROVALS_BACKLOG4METRIC_ID_APPROVALS_BACKLOG — count of governance_approvals.status='pending' anchored at bucket end (snapshot semantic).
METRIC_ID_GUARDRAILS_FIRED5METRIC_ID_GUARDRAILS_FIRED — count of agent_audit_log action_type='action_blocked' per bucket.
METRIC_ID_LATENCY_P506METRIC_ID_LATENCY_P50 — p50 of workflow_runs (completed_at - started_at) in seconds per bucket.
METRIC_ID_COST_PER_RUN7METRIC_ID_COST_PER_RUN — spend/runs derived per bucket (USD; 0 when runs=0).
METRIC_ID_HOURS_SAVED8METRIC_ID_HOURS_SAVED — runs * HoursPerWorkflowRunHeuristic per bucket.

MetricsScope

MetricsScope mirrors AnalyticsService.Scope so callers can switch a metric query between org-wide, a single pillar, or a single team without touching the rest of the request shape. A separate enum is declared (rather than importing analytics.Scope) so MetricsService is not a leaf of analytics.proto — keeps the proto package self-contained for the redesign tracker. Wave-K.2 may later rename "team" → "org units"; the enum naming is intentionally left as TEAM/PILLAR for alignment with the existing analytics surface and the v3 audit doc.

NameNumberDescription
METRICS_SCOPE_UNSPECIFIED0METRICS_SCOPE_UNSPECIFIED defaults to organisation-wide.
METRICS_SCOPE_ORG1METRICS_SCOPE_ORG queries across the entire organisation.
METRICS_SCOPE_PILLAR2METRICS_SCOPE_PILLAR queries within a single pillar (org_unit).
METRICS_SCOPE_TEAM3METRICS_SCOPE_TEAM queries within a single team (org_unit).

TimeSeriesGranularity

TimeSeriesGranularity selects the date_trunc bucket size for GetTimeSeries. HOUR/DAY/WEEK mirror analytics.Granularity but a separate enum is declared so MetricsService stays self-contained.

NameNumberDescription
TIME_SERIES_GRANULARITY_UNSPECIFIED0TIME_SERIES_GRANULARITY_UNSPECIFIED defaults to DAY.
TIME_SERIES_GRANULARITY_HOUR1TIME_SERIES_GRANULARITY_HOUR — bucket by hour (cap 168 points / 7 days).
TIME_SERIES_GRANULARITY_DAY2TIME_SERIES_GRANULARITY_DAY — bucket by day (cap 90 points).
TIME_SERIES_GRANULARITY_WEEK3TIME_SERIES_GRANULARITY_WEEK — bucket by ISO week (cap 13 points).

TimeSeriesRange

TimeSeriesRange is the canonical preset for the trends-grid range dropdown. CUSTOM unlocks the optional custom_start / custom_end pair in the request envelope.

NameNumberDescription
TIME_SERIES_RANGE_UNSPECIFIED0TIME_SERIES_RANGE_UNSPECIFIED defaults to DAYS_30.
TIME_SERIES_RANGE_DAYS_71TIME_SERIES_RANGE_DAYS_7 — trailing 7 days ending now (UTC).
TIME_SERIES_RANGE_DAYS_302TIME_SERIES_RANGE_DAYS_30 — trailing 30 days ending now (UTC).
TIME_SERIES_RANGE_DAYS_903TIME_SERIES_RANGE_DAYS_90 — trailing 90 days ending now (UTC).
TIME_SERIES_RANGE_CUSTOM4TIME_SERIES_RANGE_CUSTOM — uses custom_start / custom_end on the request. Both are required when this range is selected.

MetricsService

MetricsService exposes aggregator RPCs that compose multiple existing reads into a single response for the redesigned Metrics page. All RPCs are tenant-scoped via the JWT-derived scope claims injected by the scope middleware. There is no direct DB access that an existing service does not already permit; this is purely a composition boundary.

Method NameRequest TypeResponse TypeDescription
GetKPIsGetKPIsRequestGetKPIsResponseGetKPIs returns the 8-tile headline KPI strip for the calling tenant over the requested range and scope. Composes: 1. total spend (USD) over [range_start, range_end) 2. workflow run count over [range_start, range_end) 3. workflow success rate (completed / total) over the same window 4. hours-saved heuristic = workflow_runs * 0.5 5. approvals backlog (pending count, age-agnostic) 6. guardrails fired (action_blocked count over the window) 7. active agents count (current snapshot, not windowed) 8. cost per run = spend / runs (0 when runs == 0)

The aggregation reuses the same data sources that AnalyticsService.GetDashboardKPIs / GetWorkflowMetrics / GetCostBreakdown already query, so the security boundary is identical (RLS on every base table). | | GetTimeSeries | GetTimeSeriesRequest | GetTimeSeriesResponse | GetTimeSeries returns a single metric as an array of (timestamp, value) points over the requested range and granularity. Powers the 6-chart trends grid on the redesigned Metrics page (v3 audit #1096 §2.11; prototype docs/design/redesign-2026-04/project/metrics.jsx lines 112-132).

Internally maps to existing time-series sources: SPEND -> usage_records.cost_usd (matches AnalyticsService.GetTokenUsageTimeSeries) RUNS -> workflow_runs aggregated by created_at SUCCESS_RATE -> derived (completed / total) per bucket APPROVALS_BACKLOG -> snapshot count of governance_approvals.status='pending' per bucket GUARDRAILS_FIRED -> agent_audit_log filtered on action_type='action_blocked' LATENCY_P50 -> workflow_runs duration p50 (percentile_cont) COST_PER_RUN -> derived (spend / runs) per bucket HOURS_SAVED -> derived (runs * HoursPerWorkflowRunHeuristic) per bucket

Response is capped at 168 points (HOUR), 90 (DAY), 13 (WEEK). Over-cap requests are rejected with InvalidArgument so the chart grid can never pull an unbounded series. | | GetWorkflowsBreakdown | GetWorkflowsBreakdownRequest | GetWorkflowsBreakdownResponse | GetWorkflowsBreakdown returns the top-N workflows by run volume over the requested window. Powers the "Workflows · by volume" table in the redesigned Metrics page (#1031, v3 audit §2.11). See metrics.jsx prototype lines 163-173 for the rendered shape. | | GetGuardrailsBreakdown | GetGuardrailsBreakdownRequest | GetGuardrailsBreakdownResponse | GetGuardrailsBreakdown returns the top-N guardrails by activity over the window. Source is agent_audit_log rows whose action_type is either 'action_blocked' (rejected) or 'action_auto_executed' (allowed) — the canonical "guardrail intercepted" surface today. Rows are grouped by detail->>'rule_id' (falling back to action_type when no rule id is present). Powers the "Guardrails · by activity" table; see metrics.jsx prototype lines 150-161. | | GetFailuresBreakdown | GetFailuresBreakdownRequest | GetFailuresBreakdownResponse | GetFailuresBreakdown returns the top-N failures (by count) over the window. Source is workflow_runs rows with status='failed'; root_cause is best-effort from the run's context JSONB. Powers the "Top failures" table; see metrics.jsx prototype lines 175-184. | | GetApprovalMetrics | GetApprovalMetricsRequest | GetApprovalMetricsResponse | GetApprovalMetrics returns the operational-health approvals card payload: pending total + age histogram, today's approved/rejected counters, p50/p95 latency, and the top approvers ranked by today's decision count. Powers the "Approvals throughput" card; see metrics.jsx prototype lines 320-356 (ApprovalsCard). | | GetPillarSpend | GetPillarSpendRequest | GetPillarSpendResponse | GetPillarSpend returns per-pillar rollup rows (pillars = unit_type='pillar' org_units, top-level by convention pending the structural rule from #1090). Powers the pillar-mode of the team rollup card on the Metrics page; see metrics.jsx prototype lines 358-435 (TeamRollupCard with mode='pillar') and metrics-data.jsx pillarRollup (lines 161-169). |

Scalar Value Types

.proto TypeNotesC++JavaPythonGoC#PHPRuby
doubledoubledoublefloatfloat64doublefloatFloat
floatfloatfloatfloatfloat32floatfloatFloat
int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32intintint32intintegerBignum or Fixnum (as required)
int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64longint/longint64longinteger/stringBignum
uint32Uses variable-length encoding.uint32intint/longuint32uintintegerBignum or Fixnum (as required)
uint64Uses variable-length encoding.uint64longint/longuint64ulonginteger/stringBignum or Fixnum (as required)
sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32intintint32intintegerBignum or Fixnum (as required)
sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64longint/longint64longinteger/stringBignum
fixed32Always four bytes. More efficient than uint32 if values are often greater than 2^28.uint32intintuint32uintintegerBignum or Fixnum (as required)
fixed64Always eight bytes. More efficient than uint64 if values are often greater than 2^56.uint64longint/longuint64ulonginteger/stringBignum
sfixed32Always four bytes.int32intintint32intintegerBignum or Fixnum (as required)
sfixed64Always eight bytes.int64longint/longint64longinteger/stringBignum
boolboolbooleanbooleanboolboolbooleanTrueClass/FalseClass
stringA string must always contain UTF-8 encoded or 7-bit ASCII text.stringStringstr/unicodestringstringstringString (UTF-8)
bytesMay contain any arbitrary sequence of bytes.stringByteStringstr[]byteByteStringstringString (ASCII-8BIT)