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.

Edited by Vasyl Pedak

Merge request reports

Loading
Loading