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.

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 byWHERE TenantId = '${tenantId}'. No cross-tenant leak possible. - Auth via reverse-proxy header: portal forwards
X-WEBAUTH-USER+ tenantId, Grafana'sauth.proxyconsumes 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 |