DocumentsDosu Decant
Session Analytics and Statistics
Session Analytics and Statistics
Type
Topic
Status
Published
Created
Aug 4, 2026
Updated
Aug 4, 2026
Created by
Dosu Bot
Updated by
Dosu Bot

Session Analytics and Statistics#

Decant's analytics layer queries the local SQLite archive and is governed by three core rules: inclusive UTC date filtering, root-session-only session counts with inclusive subagent metric aggregation, and recursive subagent cost summation in per-session summaries. The authoritative implementation is split across src/date-filter.ts, src/stats.ts, src/query.ts, and src/ui/session-summary.ts. The methodology is documented in docs/analytics-methodology.md and practical query patterns are in docs/api/recipes.md.


Date Filtering#

Date ranges are applied by sessionDatePredicate in src/date-filter.ts. Both from and to are inclusive — a session belongs to the window when the date prefix of its started_at ISO timestamp falls within [from, to] . Filtering uses a substr(started_at, 1, 10) >= ? / <= ? comparison, so the timezone of started_at (UTC) is what matters — not the caller's local time .

Inputs that don't match YYYY-MM-DD or that represent an invalid calendar date are silently discarded by isoDate(). Callers that need a strict contract should validate dates before sending them .

Practical note: Exclude the current UTC date when you want only complete days, since an in-progress day is still open .

The same predicate is reused by listSessions, searchPage, listToolCalls, fileHotspots, mcpUsage, and every other query that accepts from/to — so date semantics are uniform across the API .


Session Counts vs. Metric Aggregation#

The sessions field in aggregate statistics counts only top-level (non-subagent) sessions — those where is_subagent = 0 . Message, tool-call, token, and estimated-cost totals include all visible sessions (root + subagent) in the filtered scope .

The same split applies to dimension breakdowns: the byDimension function sums CASE WHEN s.is_subagent = 0 THEN 1 ELSE 0 END for session counts, while token/cost columns sum across every row in the filtered set .

Why this matters: A single top-level session can spawn many separately metered subagent runs. Counting only roots keeps the session count comparable across different parallelism strategies, while including subagents in cost/token totals gives a complete picture of spend .

The GET /api/sessions list endpoint mirrors this by omitting subagents as top-level rows by default; include_subagents=true includes them as list entries, and with_subagents=true attaches nested summaries .

Warning on double-counting: Do not add a parent session's estimated_cost_usd to archive-wide totals: aggregate statistics already include every visible run .


Subagent Cost Summation#

Each session row carries two subagent cost fields:

FieldMeaning
subagent_countNumber of direct child subagent sessions
subagent_estimated_cost_usdCost of direct children only

These are computed by a LEFT JOIN aggregation in sessionSummarySelect, which groups session rows where is_subagent = 1 and parent_session_id IS NOT NULL .

For nested subagent trees, the UI computes the full recursive cost via sessionThreadCost in src/ui/session-summary.ts:

  • If the session has loaded subagents (i.e., with_subagents=true was requested), the function recurses into them.
  • Otherwise, it falls back to session.estimated_cost_usd + subagent_estimated_cost_usd (direct children only) .

This means the cost shown in summary cards is a thread total (session + all visible descendants), while the raw estimated_cost_usd on each row is the session's own spend only .

Nested summaries are capped at five levels deep — see buildSubagentDetails and the recursive CTE in getSession . For a complete deeper tree, request subagents as rows and join by parent_session_id .


Key Files#

FileRole
src/date-filter.tssessionDatePredicate — inclusive UTC date SQL fragments
src/stats.tstotals, byDimension, toolUsage, mcpUsage — aggregate statistics with root/subagent split
src/query.tslistSessions, sessionSummarySelect — per-session summaries and subagent rollups
src/ui/session-summary.tssessionThreadCost, sessionCardMetrics — recursive UI-side cost summation
docs/analytics-methodology.mdCanonical definitions for all metric semantics
docs/api/recipes.mdReproducible curl query patterns with date windows