Skip to content

Metrics Reference

The API serves Prometheus metrics at GET /api/v1/admin/metrics in text exposition format 0.0.4. This page lists every family it can emit. For scraping, authentication and Helm setup, see Self-Hosted: Operator metrics.

  • Closed vocabularies only. Every label value comes from a fixed list shown on this page. A value outside the list is recorded as other.
  • No names and no ids by default. Labels never carry persona names, template, suite or policy slugs, step names, titles, emails, or user, ticket, meeting, session, project or org ids.
  • No dollar metrics. Agent spend is reported in tokens only.
  • Bounded cardinality. Each family is capped at 10,000 series per process. Past the cap, samples are dropped and counted in sessionfs_metrics_series_dropped_total. With the default settings every family’s worst case is far below the cap.

Set SFS_METRICS_TENANT_LABELS=true (Helm: api.metrics.tenantLabels: true) to add org_id and project_id labels to the families marked tenant below. The value is always an id, never a name. A sample with no org or project (for example a run in a personal project, which has no org) leaves that label out.

It is off by default, and the hosted service leaves it off: series then add up across every tenant. Turn it on only on a self-hosted install where you want per-team dashboards. Series then grow with the number of orgs and projects, still capped at 10,000 per family.

Counters and histograms are per process. Sum them across replicas with sum() or sum by (...).

Families marked DB-derived are computed from the database when the endpoint is scraped and cached for 30 seconds. Every replica reports the same cluster-wide value, so take max() or max by (...) instead of summing. sessionfs_sweep_lag_seconds is set by whichever replica ran the sweep last, so take max() across replicas too.

Metric Type Labels and values
http_request_duration_seconds histogram method: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, other. route: the matched route template (for example /api/v1/sessions/{session_id}/sync), or unmatched for every 404 and 405. status_class: 2xx, 3xx, 4xx, 5xx. For a streaming response this is the time to first headers.
sessionfs_push_total counter outcome: ok, conflict, rejected_quota, rejected_dlp, error. size_bucket: <1MB, 1-10MB, 10-50MB, 50-100MB, >100MB.
sessionfs_sync_pull_total counter none. Successful session downloads.
sessionfs_handoff_create_total counter none. Handoffs created.
sessionfs_handoff_claim_total counter none. Handoffs claimed.
sessionfs_dlp_findings_total counter severity: critical, high, medium, low, other. action: block, redact, warn, other.
sessionfs_auth_failures_total counter reason: missing_bearer, invalid_key, revoked, inactive_key, expired, inactive_user.
sessionfs_metrics_series_dropped_total counter none. Samples dropped by the series cap.
Metric Type Labels and values
sessionfs_active_users gauge window: 1h, 1d, 7d. Distinct users with a sync in the window. Take max().
sessionfs_sessions gauge none. Non-deleted sessions. Take max().
sessionfs_db_pool_size gauge none. This process’s pool size. Absent without a live pool (SQLite). Sum across replicas.
sessionfs_db_pool_checked_out gauge none. Connections checked out in this process.
sessionfs_db_pool_overflow gauge none. Overflow connections in this process.

Sweep labels: org-digest, ticket-notifications, kb-compile, jira-sync, confluence-publish, helper-retention, meeting-retention, contact-retention, eval-outputs, reminders-due, attention-hides, idempotency-keys, github-webhook-deliveries (both its /sweep and /purge paths), skills-verify, skills-catalogs-regenerate, skills-rescan, marketplace-freshness, marketplace-publishers-recheck.

Metric Type Labels and values
sessionfs_sweep_runs_total counter sweep. result: ok (2xx), rejected (the sweep refused its request, for example a retention override sent with a service key), error (5xx or crash). Only calls that passed authorization count.
sessionfs_sweep_duration_seconds histogram sweep. Wall-clock time of an authorized run. Buckets from 0.1 s to 30 min.
sessionfs_sweep_lag_seconds gauge sweep. How long the oldest due item had been waiting when the sweep last started; 0 when nothing was due. Reported for reminders-due (oldest unsent due reminder), jira-sync (oldest due outbox row) and ticket-notifications (oldest undelivered notification). Take max().
sessionfs_sweep_denied_total counter sweep. reason: unauthenticated (no or unknown key), rate_limited, auth_rejected (revoked, expired or otherwise refused key, or SSO enforcement), not_admin (a user key that isn’t a platform admin), insufficient_scope (a service key without platform_sweeps:run), owner_not_admin and minter_not_admin (the key’s owner or minter is no longer an active platform admin), minter_missing, other. Alert on any increase: a scheduler using a stopped key shows up here, not only in the logs.
Metric Type Labels and values
sessionfs_jira_sync_total counter, tenant (org_id) direction: outbound, inbound. result for outbound, one per delivery attempt from the outbox: done, skipped (sync turned off, link gone, superseded), failed (will retry), exhausted (gave up after five attempts). result for inbound, one per verified webhook event: applied, ignored (unsupported event, unknown issue, stale link, plan without Jira), duplicate. other is reserved.
sessionfs_jira_sync_lag_seconds histogram, tenant (org_id) direction. outbound: time from the change being queued to Jira accepting it. inbound: time from Jira’s event timestamp to SessionFS applying it (skipped when the timestamp is missing, in the future or older than 30 days).
sessionfs_confluence_publish_total counter, tenant result: published, in_progress (another publish holds the page), drifted (the page was edited in Confluence), conflict (title clash, page missing, superseded), too_large, timeout, rejected (other 4xx), error. Counts manual and swept publishes.
sessionfs_webhook_ingest_total counter source: github (GitHub App), gitlab (merge request webhooks), jira, delivery_github and delivery_gitlab (org delivery webhooks), plus one source used only by the hosted service’s billing, which a self-hosted server never reports. result: ok (any 2xx or 3xx, including deliveries the server ignores), unauthorized (401/403, for example a bad signature), not_found, too_large, rejected (other 4xx), unavailable (503, for example no webhook secret configured), error. Never carries an org id, even with tenant labels on.
Metric Type Labels and values
sessionfs_agent_tokens_total counter, tenant token_kind: input, output, cache_read, cache_write. model_family: anthropic, openai, google, openrouter, deepseek, kimi, xai, mistral, zai, qwen, minimax, groq, together, fireworks, other. The family is the run’s provider when it is one of these, else it is inferred from the model name; the model text itself is never a label. Incremented by the tokens each usage report, completion, worker finish and review round adds.
sessionfs_agent_runs_total counter, tenant status: passed, failed, errored, cancelled. role: implementer, ui-implementer, reviewer, design-reviewer, security-reviewer, release, grader, none (no role recorded), other. One per run reaching a terminal status.
sessionfs_approval_requests gauge, DB-derived, tenant status: pending, approved, rejected, expired, superseded. Take max().
sessionfs_approval_decision_seconds histogram, tenant decision: approved, rejected. Time from the request being raised to the decision that settled it. Buckets from 1 minute to 14 days.
sessionfs_review_loop_items gauge, DB-derived, tenant (project_id) status: pending, active, waiting, done, failed, needs_human (parked for a person by a budget or round cap). Counts work-queue items whose ticket belongs to a review loop. Take max().
Metric Type Labels and values
sessionfs_org_concurrency_rejected_total counter, tenant (org_id) route_class: extraction (meeting and chat extraction), helper (session helper turns), compile (knowledge compile, rebuild and group compile), export (CSV exports), other. One per request refused with 429 org_concurrency_limit. A refusal in a personal project carries no org id. See Tenancy and Isolation.
Metric Type Labels and values
sessionfs_extraction_server_seconds histogram kind: meeting, chat, other. result: done, failed, other. Time an extraction spent in the server: its wall time minus the time spent waiting on the model provider. Recorded for every extraction that finished, successfully or not. Buckets from 10 ms to 10 s. Used by the extraction SLO.
# Sweeps that failed or were refused in the last hour
sum by (sweep, result) (increase(sessionfs_sweep_runs_total{result!="ok"}[1h]))
sum by (sweep, reason) (increase(sessionfs_sweep_denied_total[1h]))
# Oldest due reminder, in minutes
max by (sweep) (sessionfs_sweep_lag_seconds) / 60
# Jira outbound p95 lag
histogram_quantile(0.95, sum by (le) (rate(sessionfs_jira_sync_lag_seconds_bucket{direction="outbound"}[15m])))
# Agent tokens per hour by model family
sum by (model_family) (increase(sessionfs_agent_tokens_total[1h]))
# Review-loop items waiting on a person
max(sessionfs_review_loop_items{status="needs_human"})

A ready-made Grafana dashboard with panels for every family ships in the repository at docs/observability/sessionfs-ops.json. The objectives built on these metrics, with their queries and alert rules, are on Service Level Objectives.