Add distinct AI agent sessions Service Ping metrics
What does this MR do and why?
Work item 607935 asks for Service Ping metrics covering AI audit event activity, including:
- Number of distinct AI agent sessions audited
This MR adds that count:
| Metric | Time frames | How |
|---|---|---|
counts.count_distinct_ai_agent_sessions_with_audit_events |
28d, all | batched COUNT(DISTINCT workflow_id) on ai_audit_events in PostgreSQL |
counts.count_distinct_ai_agent_sessions_with_audit_events_clickhouse |
28d, all | uniqExact(workflow_id) in ClickHouse |
An AI agent session is a Ai::DuoWorkflows::Workflow; every AI audit event carries its workflow_id, so distinct workflow ids give the number of sessions that actually produced audit activity — which event totals alone cannot tell apart from a few very chatty sessions. The PostgreSQL and ClickHouse pair follows the merged count_ai_audit_events / count_ai_audit_events_clickhouse precedent: instances with ClickHouse analytics store AI audit events only there, everyone else uses the PostgreSQL fallback table.
References
Database review
The PostgreSQL metric batches with distinct_count (batch size 10,000) over unfiltered MIN/MAX(workflow_id) bounds.The production ai_audit_events table is empty (GitLab.com writes AI audit events to ClickHouse; the PostgreSQL table serves instances without ClickHouse analytics), so the Database Lab clone was seeded with 200,000 events for the plans (session).
-- Batch bounds
SELECT MIN("ai_audit_events"."workflow_id") FROM "ai_audit_events";
SELECT MAX("ai_audit_events"."workflow_id") FROM "ai_audit_events";
-- Per-batch, all time frame
SELECT COUNT(DISTINCT "ai_audit_events"."workflow_id") FROM "ai_audit_events"
WHERE "ai_audit_events"."workflow_id" >= 1 AND "ai_audit_events"."workflow_id" < 10001;
-- Per-batch, 28d time frame, batch overlapping the window
SELECT COUNT(DISTINCT "ai_audit_events"."workflow_id") FROM "ai_audit_events"
WHERE "ai_audit_events"."created_at" BETWEEN '2026-07-20 00:00:00' AND '2026-08-17 00:00:00'
AND "ai_audit_events"."workflow_id" >= 10001 AND "ai_audit_events"."workflow_id" < 20002;
-- Per-batch, 28d time frame, historical batch fully outside the window
SELECT COUNT(DISTINCT "ai_audit_events"."workflow_id") FROM "ai_audit_events"
WHERE "ai_audit_events"."created_at" BETWEEN '2026-07-20 00:00:00' AND '2026-08-17 00:00:00'
AND "ai_audit_events"."workflow_id" >= 1 AND "ai_audit_events"."workflow_id" < 10001;| Query | Plan | Execution | Buffers | Rows aggregated |
|---|---|---|---|---|
MIN(workflow_id) |
158592 | 0.46 ms | 19 hits | 1 |
MAX(workflow_id) |
158593 | 0.45 ms | 26 hits | 1 |
| Batch, all time | 158594 | 28.0 ms | 525 hits (4.1 MiB) | 99,999 |
| Batch, 28d, overlapping | 158595 | 17.2 ms | 443 hits (3.5 MiB) | 51,852 |
| Batch, 28d, outside window | 158597 | 0.17 ms | 10 hits | 0 |
Observations:
- Every query resolves through index-only scans on the per-partition
(workflow_id, created_at DESC, id DESC)indexes with zero heap fetches and no seq scans over populated partitions.
How to set up and validate locally
require_relative 'spec/support/helpers/service_ping_helpers.rb'
ServicePingHelpers.get_current_usage_metric_value('counts.count_distinct_ai_agent_sessions_with_audit_events')MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.