Skip to content

Hourly Breakdown chart permanently shows "No data" for active users (hard 200-segment cap) #952

Description

@NuclleaR

The Hourly Breakdown chart on the summary page silently renders "No data" for any
interval whose 24h window contains more than 200 duration segments — even when there is
plenty of activity and every other widget on the page is populated.

In routes/summary.go, the view model is only built when the segment count is <= 200:

if durations, err := h.durationSrvc.Get(...); err == nil {
    // for excessively many small segments, plotting is too performance-heavy ...
    if len(durations) <= 200 {
        hourlyBreakdown = view.NewHourlyBreakdownViewModel(...)
    }
}

If the threshold is exceeded, hourlyBreakdown stays empty and the frontend falls back to
the "No data" placeholder. There is no log line or UI hint that the chart was disabled
rather than empty, so it looks like a bug/data loss.

To Reproduce

Have a day with many short, fragmented segments (easy to hit when using AI coding agents / editors that rapidly switch files, branches, etc.).
Open Summary → interval=today.
Every chart shows data, but Hourly Breakdown shows "No data".
Why segment counts explode
Durations are split on every change of the group hash (project, entity, branch,
language, editor, category, …). Tooling that touches many files in quick succession
(AI agents, formatters, etc.) easily produces several hundred sub-minute segments per day.
In my case a normal ~4.5h day produced 396 segments, so the chart was never shown.

Inconsistent client metadata makes it worse (e.g. category reported as both "AI Coding"
and "ai coding", or editor as "Claude code"/"Opus"/"VS Code" for the same work),
since each variation starts a new segment — but that's a separate, client-side issue.

Expected behavior

The chart should remain readable (and visible) regardless of how fragmented the underlying
heartbeats are — similar to WakaTime's per-project "Today" timeline, which coalesces
contiguous activity into solid blocks instead of plotting every micro-segment.

Proposed fix

Coalesce chronologically-contiguous segments of the same project (gap smaller than the
user's heartbeat timeout) into single blocks inside NewHourlyBreakdownViewModel, before
they reach the chart. This:

  • collapses hundreds of slivers into a handful of readable blocks per project;
  • removes the need for the hard <= 200 cap entirely (addresses the original browser-freeze concern from Statistics won't load if there are too many heart beats #871 at its root, since the bar count is now bounded by activity blocks, not raw segment count);
  • lets the projects be ordered deterministically (e.g. by total activity) instead of the current random map-iteration order on the Y-axis.

I have a working implementation and would be happy to open a PR.

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions