Reports and visualizations

ActivityLog has three consumption layers for the data you ingest. They have very different cost / benefit tradeoffs for the user (zero-config vs custom) and for us (zero-ops vs run-a-Grafana). All three coexist.

Layer Status What it gives you
Live activity feed Live Real-time strip of colored dots — "is something happening?"
Pre-canned report packs Coming soon Per-persona dashboards covering 80% of common questions
Embedded Grafana Deferred User-extensible dashboards: build your own panels, ad-hoc queries, alerts

Status as of 2026-05. See ../Reports-Architecture.md for the full design and roadmap.

1. Live activity feed (Live)

The activity-dots chart on the portal Dashboard and admin Activity pages shows your recent activity as colored dots over time.

Element What it shows
Color Event class (e.g. ingest, query, auth, audit, error)
Horizontal axis Time, most-recent on the right
Density of dots Volume of activity in each interval
Hover / click Per-message detail

The chart is live — new messages appear within seconds. Use it for the "is the platform healthy / is my app shipping events?" at-a-glance check.

Live activity-dots chart

Under the hood: GET /api/v1/messages/timeline with a 1-minute bucket. You can query the same data via 60-query-api.md.

2. Pre-canned report packs (Coming soon)

Each pack is a named set of visualizations tied to a data source you ingest. Tenants enable/disable packs from the portal (off by default until a relevant source is configured).

Pack Data source it needs Headline panels
Claude Code OTel from CLAUDE_CODE_ENABLE_TELEMETRY=1 Sessions/day, cost/user/model, token breakdown (input/output/cache), top tools used, errors, interaction-trace timeline
DevOps webhooks ADO/GitHub webhook system Deploys/day, PR cadence per repo, build-fail rate, release timeline, work-item state churn
App operator Native /messages ingest from your app Request volume, error rate, latency p50/p95/p99, system-health rollup, duration-message completions
LLM cost Any OTel source with gen_ai.* attrs Cost over time per model, per user, per feature, prompt/completion ratio, cache-hit rate, top-cost spans
Audit & compliance Internal __audit stream Admin actions timeline, login success/fail, invite issuance, token mints/revokes, who-did-what filters

When packs ship

The first pack lands next cycle (Claude Code, since Fyin is the lead user). Subsequent packs ship as the underlying data shows enough volume to design around real usage rather than imagined needs.

A pack is identified by pack_id (claude-code, llm-cost, etc.). Enabling a pack does no data work — it just unhides the visualization screens in the portal. Disabling hides them; data continues ingesting regardless.

Tier behavior

Tier Packs available
Free Read-only access to any pack a tenant admin has enabled
Pro All packs available, per-tenant enable/disable
Enterprise All packs + custom-pack assistance from Fyin (Phase β)

3. Embedded Grafana (Deferred)

The user-extensible dashboard layer. Not deployed today. Stand up when:

  • A customer specifically asks for ad-hoc dashboards, OR
  • Fyin's internal use needs panels we don't want to build as Razor pages, OR
  • We want to ship Cole Murray's Claude Code Grafana dashboard as a one-click import.

Planned architecture (when we deploy)

  • One Grafana instance per environment (staging + prod). Self-hosted on the API VM or a sidecar.
  • Single shared instance, multi-tenant via SQL filter: every dashboard query templates a ${tenantId} variable injected from the auth-passthrough JWT. Datasource queries are MANDATORY-filtered by WHERE TenantId = '${tenantId}'. No cross-tenant leak possible.
  • Auth via reverse-proxy header: portal forwards X-WEBAUTH-USER + tenantId, Grafana's auth.proxy consumes it, user lands in the right org with correct scope. No separate Grafana login.
  • Theming: Grafana CSS-themed to match the portal. Embedded as <iframe> panels in kiosk mode.
  • Read-only by default, edit for power users: Free = read-only; Pro = edit own dashboards; Enterprise = unlimited.
  • Dashboards as code: dashboards live in Docs/grafana-dashboards/ as JSON, provisioned via Grafana's file-based provisioning. Version-controlled.

Why Grafana over Power BI / Tableau / Metabase / Superset

Target audience is engineers (already running OTel). Grafana is the de-facto OTel-adjacent tool. Power BI / Tableau lose on licensing model; Metabase / Superset add runtime weight we'd rather not own.

Full reasoning: ../Reports-Architecture.md § 4.

User extensibility — three modes

Mode Audience Mechanism
Pick from packs Most users Toggle pre-canned packs on/off
Build dashboards Power users with Grafana experience Embedded Grafana with editor role
Bring your own viz Developers integrating ActivityLog data into their own tools Raw /messages REST API (already shipped); future SQL-passthrough endpoint for advanced ad-hoc queries

Honest "not yet" notes

Feature Why not When
Email / Slack alerts on a query result Requires alert routing + email infra Pro tier feature; Phase β
Scheduled exports of reports Same Pro tier feature; Phase β
Per-tenant custom dashboards Needs Grafana deployed When the first customer asks
Mobile app Out of scope No plan

What's next

Goal Doc
Architecture details ../Reports-Architecture.md
Query the data manually 60-query-api.md
Wire Claude Code (the pack-ready source) 72-integrations-claude-code.md
Status snapshot of what ships when ../Feature-Audit.md