Skip to content

Series Limit picks the top N groups from the newest 15-minute chunk, not the whole time range #3204

Open

Description

@tefimov

What happened?

A time chart with a positive Series Limit picks its top N groups from the newest query chunk only. By default that chunk is the last 15 minutes of the range. A group that was busy earlier but quiet at the end drops off the chart, even if it was the biggest series in the range. On a 24h or 7d chart this can hide exactly the spike you are looking for.

The docs say something different:

  • The Series Limit field in Display Settings says it keeps "those with the largest values".
  • The MCP/API schema says it "keeps the top-N groups by aggregated value over the queried range".

Nothing tells the user that "largest" only covers the last few minutes.

What should happen: the top N groups are ranked over the whole chart range, as the docs describe. At minimum, the UI and API docs should say how the ranking works.

Steps to reproduce

  1. Use the default otel_logs schema. Insert logs for ServiceName = 'svc-a', 10,000 rows spread over 23 hours starting 24 hours ago, and none in the last hour. Insert logs for ServiceName = 'svc-b', 10 rows in the last 5 minutes.
  2. Create a dashboard tile: a line chart, count() grouped by ServiceName, granularity auto, time range "Last 24 hours".
  3. In Display Settings, set Series Limit to 1.
  4. The chart shows only svc-b. svc-a is gone, although it has 1,000 times more events in the range.
  5. Turn off query chunking for the tile, or set Series Limit to 0. svc-a comes back.

How are you running HyperDX?

ClickStack Cloud, where we saw the symptom on 24h dashboard tiles. The root cause below is traced in the code on main @ 6767349. The behaviour came in with #2449 and is still on main.

Where does it show up?

Dashboard and chart-explorer time charts (builder line and stacked bar charts with a group-by), and tiles created through the external API or MCP with seriesLimit.

Root cause

#2449 chose the newest window to keep the ranking scan small, so that every chunk returns the same top-N set. The goal of one shared set across chunks is right. The range it uses is the problem.

Suggested fix direction

  • Rank over the full chart range (config.dateRange) and keep one shared set across chunks. To avoid scanning the full range once per chunk, run the ranking once before the chunks, then pass the resulting group list to each chunk as an IN (...) filter instead of repeating the CTE.
  • If a full-range scan is too expensive by default, make the ranking range explicit, for example "rank over: full range / most recent window". Then document the choice in the Display Settings copy and the API/MCP schema.
  • Either way, update the Series Limit description in the UI and API docs so it matches the real behaviour.

Activity

  1. brandon-pereira commented on Sep 24, 2026

    @brandon-pereira
    Member

    Hey @tefimov - thanks for raising this.

    I see we even have a comment in the code highlighting this could be improved, so we agree! https://github.com/hyperdxio/hyperdx/blob/main/packages/app/src/hooks/useChartConfig.tsx#L197

    I agree with the approaches listed above. We just need to ensure we balance query and render performance with accuracy. For that reason, my vote would be that we go with option B

    If a full-range scan is too expensive by default, make the ranking range explicit, for example "rank over: full range / most recent window". Then document the choice in the Display Settings copy and the API/MCP schema.

    I will track this internally as well and get it prioritized - but if you need it sooner please feel free to open a PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions