Conversation
Fixes #58 - Timeline chart now accurately reflects when work actually happened. ## Problem Analytics bucketed ALL session cost into the session start time, even for long-running sessions. A session started at 05:00 with heavy work at 10:00-12:00 showed all cost at 05:00, creating misleading spikes at wrong hours. ## Solution - Added CostPoint interface to track per-message cost and timestamp - Created listSessionsForAnalytics() that parses cost points from JSONL files - Updated analytics aggregation to distribute cost across actual message times - Falls back to startedAt for sessions without cost points (backward compat) - Sessions counted once per bucket to avoid inflated sessionCount ## Impact Charts now show accurate usage patterns: - Spikes appear when work actually happened (e.g., 10:00-12:00 local time) - Multi-hour sessions distribute cost across their actual runtime - Timezone handling preserved (UTC storage, local display)
There was a problem hiding this comment.
Pull request overview
Fixes misleading “Total Usage Over Time” spikes by attributing usage to the actual message timestamps (when work happened) rather than the session startedAt.
Changes:
- Added per-message cost/token time series (
costPoints) collection during JSONL parsing for analytics. - Introduced
listSessionsForAnalytics()to load session summaries withcostPoints(separate cache key). - Updated
/api/analyticsaggregation to bucket cost/tokens bycostPointstimestamps and preventsessionCountinflation per bucket.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| backend/src/sessions.ts | Adds CostPoint + optional costPoints on SessionSummary, and an analytics-specific session listing that collects per-message cost points. |
| backend/src/routes.ts | Switches analytics endpoint to use cost points for bucketing and adjusts session counting to avoid double-counting within a bucket. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Comment on lines
795
to
801
| const from = req.query.from as string | undefined; | ||
| const to = req.query.to as string | undefined; | ||
|
|
||
| let sessions = await listSessions(profile); | ||
| let sessions = await listSessionsForAnalytics(profile); | ||
|
|
||
| // For hourly view, default to last 3 days if no from specified | ||
| let effectiveFrom = from; |
Comment on lines
+332
to
+339
| // Collect cost points for analytics time bucketing | ||
| if (collectCostPoints && msgCost > 0 && ts) { | ||
| costPoints.push({ | ||
| timestamp: ts, | ||
| costUsd: msgCost, | ||
| tokenCount: msgTokens, | ||
| }); | ||
| } |
…e zero-cost token points Addresses PR #70 review comments: - Filter sessions by lastActivityAt instead of startedAt so long-running sessions with activity inside the date range are included - Use epoch ms comparison instead of string ordering to avoid ISO format bugs - Collect cost points when tokens > 0 even if cost is 0, so cached/discounted usage is represented in analytics bucketing
This was referenced Apr 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The "Total Usage Over Time" chart was showing spikes at the wrong hours because all session cost was bucketed into the session start time, even for long-running sessions.
Example: A session started at 05:00 with heavy API usage from 10:00-12:00 would show all cost at 05:00, creating misleading spikes.
Root Cause
startedAttimestamp onlySolution
✅ Added per-message cost tracking (
CostPointinterface)✅ Created
listSessionsForAnalytics()that parses message timestamps from JSONL✅ Updated aggregation to distribute cost across actual message times
✅ Backward compatible: falls back to
startedAtfor sessions without cost points✅ Sessions counted once per bucket to avoid inflated
sessionCountImpact
Charts now accurately show:
Testing
startedAtCloses #58