Skip to content

[HDX-5076] Expand int test coverage for multi-series metric merge (regression baseline) - #2858

Merged
kodiakhq[bot] merged 1 commit into
mainfrom
warren/hdx-5076-multi-series-merge-baseline-tests
Aug 11, 2026
Merged

[HDX-5076] Expand int test coverage for multi-series metric merge (regression baseline)#2858
kodiakhq[bot] merged 1 commit into
mainfrom
warren/hdx-5076-multi-series-merge-baseline-tests

Conversation

@wrn14897

Copy link
Copy Markdown
Member

Why

HDX-5076 — regression baseline for HDX-5077 (moving the node-side multi-series metric merge into a single composed ClickHouse query).

Today a metric chart with N series fans out into N ClickHouse queries that are merged node/browser-side in mergeResultSets / computeResultSetRatio. That merge's semantics are only covered by unit tests that will be deleted along with the code they test. This PR pins the current behavior with black-box integration tests through queryChartConfig, written against the current implementation, so the HDX-5077 rewrite must reproduce it exactly.

What

12 new int tests in packages/common-utils/src/__tests__/queryChartConfig.int.test.ts (new gauge/sum/histogram fixture tables, deterministic values):

  • Gap semantics: full-outer join on time buckets; a series with no data at a joined row reads as a gap (nullish/NaN, never 0)
  • Grouped merge: rows keyed by (bucket, group); one-sided groups preserved
  • Ratio (seriesReturnType: 'ratio'): ungrouped + grouped per_group + grouped share_of_total; missing numerator → 0, missing/zero denominator → gap; output column named <num>/<denom>, operand columns stripped
  • Alias collision: same-alias series renamed with __{splitIndex} suffix; suffix stripped from the ratio label
  • Mixed metric types: gauge + sum (increase) from different physical tables join on bucket (and group); grouped histogram rows keep their Array group column and never join with gauge/sum rows
  • Non-timeseries shapes: table (group-key merge) and number (single row)
  • Meta contract asserted throughout: value columns first in select order (positional dependency of useChartNumberFormats), numeric type class via convertCHDataTypeToJSType

Gaps are asserted via a tolerance helper (nullish or NaN, never 0) rather than pinning the exact nullish representation — the current merge yields an absent key / JS NaN, a SQL-side merge yields JSON null, and every consumer treats all three identically (formatResponseForTimeChart coerces both to NaN).

Test plan

  • make dev-int-common-utils FILE=queryChartConfig — 26/26 pass (12 new + 14 pre-existing)
  • ci:lint clean (0 errors, warning count unchanged at baseline)

No production code changes.

@changeset-bot

changeset-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 227416f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hyperdx-oss Ready Ready Preview Aug 11, 2026 7:28am
hyperdx-storybook Ready Ready Preview Aug 11, 2026 7:28am

Request Review

@github-actions github-actions Bot added the review/tier-2 Low risk — AI review + quick human skim label Aug 11, 2026
@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

🔵 Tier 2 — Low Risk

Small, isolated change with no API route or data model modifications.

Why this tier:

  • Standard feature/fix — introduces new logic or modifies core functionality

Review process: AI review + quick human skim (target: 5–15 min). Reviewer validates AI assessment and checks for domain-specific concerns.
SLA: Resolve within 4 business hours.

Stats
  • Production files changed: 0
  • Production lines changed: 0 (+ 781 in test files, excluded from tier calculation)
  • Branch: warren/hdx-5076-multi-series-merge-baseline-tests
  • Author: wrn14897

To override this classification, remove the review/tier-2 label and apply a different review/tier-* label. Manual overrides are preserved on subsequent pushes.

@greptile-apps

greptile-apps Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds black-box integration coverage that establishes the current multi-series metric merge behavior as a baseline for its planned ClickHouse-side rewrite.

  • Covers gap and full-outer merge semantics for timeseries and grouped results.
  • Exercises ratio modes, alias collisions, mixed metric types, and non-timeseries result shapes.
  • Verifies value-column ordering and numeric metadata contracts.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
packages/common-utils/src/tests/queryChartConfig.int.test.ts Adds deterministic ClickHouse fixtures and integration scenarios covering multi-series metric merging without changing production behavior.

Reviews (3): Last reviewed commit: "test: pin multi-series metric merge beha..." | Re-trigger Greptile

expect(Number(ratio)).toBeCloseTo(17 / 68, 5);
});
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Oversized metric regression suite

This block adds roughly 740 lines to an already large test module, bringing it to about 1,633 lines and making fixture ownership, cleanup, and individual scenarios harder to maintain; move the suite into a dedicated integration-test file.

Context Used: AGENTS.md (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code Fix in Conductor Fix in Cursor Fix in Codex

@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Deep Review

No critical issues found. This is a test-only PR: one file, ~776 insertions, zero production code changes. The new describe('multi-series metric merge (regression baseline)') block (lines 896–1663) pins the observable contract of the node-side merge (mergeResultSets / computeResultSetRatio in packages/common-utils/src/clickhouse/index.ts) end-to-end through queryChartConfig. I verified the key assertions against the current implementation and they reproduce its actual behavior: full-outer bucket join with gaps, (bucket, group) keying, ungrouped/per-group/share_of_total ratio math, the __{splitIndex} alias-collision suffix and its stripping in the ratio label, gauge+sum+histogram mixing, and the table/number shapes. The expectGap helper (value == null || Number.isNaN(Number(value))) correctly rejects a real 0 (0 == null is false and Number(0) is not NaN), so gap assertions cannot be satisfied by a legitimate zero.

🟡 P2 -- recommended

  • packages/common-utils/src/__tests__/queryChartConfig.int.test.ts:944 -- Bucket/timestamp helpers hard-code single-digit minutes (`2025-04-15 10:0${minute}:00`), so any future fixture using minute ≥ 10 silently produces a malformed timestamp string that ClickHouse will reject or misparse rather than fail with a clear message; as a baseline other engineers will extend, this trap is worth closing now.
    • Fix: Pad the minute with String(minute).padStart(2, '0') in both insertTs and bucket so the helpers stay correct as fixtures grow.
🔵 P3 nitpicks (2)
  • packages/common-utils/src/__tests__/queryChartConfig.int.test.ts:939 -- Bucket-key assertions depend on the ClickHouse server running in UTC; this is documented in the comment and matches the rest of the file, but a local run against a non-UTC server would fail every bucket lookup rather than skip.
    • Fix: Consider pinning the session timezone explicitly (e.g. a timezone ClickHouse setting) so the tests are self-contained rather than relying on the ambient server zone.
  • packages/common-utils/src/__tests__/queryChartConfig.int.test.ts:1115 -- The col accessor rebuilds new Map(Object.entries(row)) on every single lookup purely to avoid the security/detect-object-injection lint rule, which is wasteful for the many per-row assertions.
    • Fix: Read the value once per row or hoist the map, rather than reconstructing it on each col() call.

Reviewers (6): correctness, testing, maintainability, project-standards, kieran-typescript, learnings-researcher.

Testing gaps:

  • No docs/solutions/ learnings exist in this repo, so there is no prior institutional context on ClickHouse int-test flakiness to reconcile against; consider capturing the timezone/denormal quirks encountered here after merge.
  • Fixture cleanup relies on afterAll DROP TABLE; tables created with CREATE OR REPLACE are self-healing on rerun, so a mid-suite throw leaves at most stale fixture tables rather than corrupting later runs.

@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

E2E Test Results

All tests passed • 276 passed • 1 skipped • 1101s

Status Count
✅ Passed 276
❌ Failed 0
⚠️ Flaky 1
⏭️ Skipped 1

Tests ran across 4 shards in parallel.

View full report →

Regression baseline for HDX-5077 (moving the node-side mergeResultSets /
computeResultSetRatio merge into a single composed ClickHouse query).
Pins the observable contract of queryChartConfig for multi-series metric
charts end-to-end:

- full-outer join on time buckets (and group-by values when grouped),
  with gaps (nullish/NaN, never 0) where a series has no data
- meta lists value columns first in select order (useChartNumberFormats
  positional contract), with numeric type class
- ratio semantics: column named <num>/<denom> replaces the operands,
  missing numerator reads 0, missing/zero denominator is a gap,
  share_of_total divides by the per-bucket denominator total
- same-alias series disambiguated with a __{splitIndex} suffix (and the
  suffix stripped from the ratio label)
- gauge+sum (increase) series from different tables join on bucket/group;
  grouped histogram series keep their Array "group" column and never
  join with gauge/sum rows
- table and number display shapes merge on group values / a single row
) ENGINE = MergeTree PARTITION BY toDate(TimeUnix) ${OTEL_ORDER_BY}`,
});
await client.command({
query: `CREATE OR REPLACE TABLE ${DATABASE}.${HIST_TABLE} (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have support for Exponential Histogram now, it would be nice if these tests covered that metric type as well! There are existing integration tests, but probably none that cover the multi-series case.

@pulpdrew pulpdrew left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but it would be good to cover Exp. Histogram as well since that's a different query.

@kodiakhq
kodiakhq Bot merged commit 712ddfc into main Aug 11, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automerge review/tier-2 Low risk — AI review + quick human skim

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants