Skip to content

feat: always-on attribute distribution mode#1855

Draft
alex-fedotyev wants to merge 3 commits intomainfrom
event-deltas/always-on-distribution
Draft

feat: always-on attribute distribution mode#1855
alex-fedotyev wants to merge 3 commits intomainfrom
event-deltas/always-on-distribution

Conversation

@alex-fedotyev
Copy link
Contributor

Summary

  • Show attribute value distribution charts in Event Deltas immediately on load, without requiring a heatmap selection first
  • Users see blue "All spans" distribution bars right away; selecting an area on the heatmap switches to red/green comparison mode (selection vs background)
  • Add legend UI that shows current mode and hints at interaction

Changes

  • deltaChartUtils.ts: Add ALL_SPANS_COLOR constant (Mantine blue-6 CSS variable)
  • DBDeltaChart.tsx: Accept nullable xMin/xMax/yMin/yMax props; derive hasSelection boolean; gate outlier/inlier queries with enabled: hasSelection; add allSpansData query for distribution mode; add legend UI showing current mode; pass hasSelection to PropertyComparisonChart
  • PropertyComparisonChart.tsx: Accept optional hasSelection prop (default true); show single blue bar labeled "All spans" in distribution mode; hide inlier (background) bar when no selection
  • DBSearchHeatmapChart.tsx: Always render DBDeltaChart (remove null-check conditional and placeholder text); remove unused Center/Text imports

Test plan

  • Existing deltaChart unit tests pass (51 tests across 3 suites)
  • ESLint passes on all changed files
  • Manual: Open Event Deltas tab -- attribute distribution charts should appear immediately with blue bars
  • Manual: Select an area on the heatmap -- charts should switch to red/green comparison mode with legend update
  • Manual: Clear selection -- should revert to blue distribution mode

Closes #1824

🤖 Generated with Claude Code

Show attribute value distribution charts immediately when viewing Event
Deltas, without requiring a heatmap selection first. Users see attribute
distributions right away, then can select an area to enable comparison
mode (selection vs background).

Changes:
- DBDeltaChart: Accept nullable xMin/xMax/yMin/yMax props; gate
  outlier/inlier queries with enabled:hasSelection; add allSpansData
  query when no selection; add legend UI showing mode
- PropertyComparisonChart: Accept hasSelection prop; show blue bars
  (ALL_SPANS_COLOR) in distribution mode, hide inlier bar
- DBSearchHeatmapChart: Always render DBDeltaChart (remove conditional
  and placeholder text)
- deltaChartUtils: Add ALL_SPANS_COLOR constant

Closes #1824

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Mar 5, 2026

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

Project Deployment Actions Updated (UTC)
hyperdx-oss Ready Ready Preview, Comment Mar 5, 2026 10:05pm

Request Review

@changeset-bot
Copy link

changeset-bot bot commented Mar 5, 2026

🦋 Changeset detected

Latest commit: 971950f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@hyperdx/app Patch
@hyperdx/api Patch
@hyperdx/otel-collector Patch

Not sure what this means? Click here to learn what changesets are.

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

@github-actions
Copy link
Contributor

github-actions bot commented Mar 5, 2026

Claude finished @alex-fedotyev's task in 30s —— View job


PR Review

✅ No critical issues found.

The implementation is clean and well-structured. A few minor observations:

  • DBDeltaChart.tsx:373useEffect resets page on xMin/xMax/yMin/yMax changes, but these now default to 0 when null. This means the effect dependencies won't change when transitioning from null to null (no selection), which is fine. However, page won't reset when toggling from selection mode back to no-selection mode if the coords happen to stay the same — edge case, probably acceptable.
  • DBDeltaChart.tsx:256error is outlierError ?? allSpansError. Since outlierError is only populated when hasSelection is true (query disabled otherwise), this correctly surfaces the right error in each mode.
  • PropertyComparisonChart.tsx:172 — The outlierCount dataKey is reused for "All spans" mode. This works because allSpansData is mapped as the "outlier" in DBDeltaChart, but it's a subtle coupling. Worth a comment, though not a blocker.
  • The allSpansData query at DBDeltaChart.tsx:242 fetches all spans with select: '*' and no time/value range filter — this is intentional and consistent with the "show everything" distribution mode.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 5, 2026

E2E Test Results

All tests passed • 87 passed • 3 skipped • 907s

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

Tests ran across 4 shards in parallel.

View full report →

@github-actions
Copy link
Contributor

github-actions bot commented Mar 5, 2026

Claude finished @alex-fedotyev's task in 26s —— View job


PR Review

✅ No critical issues found.

The implementation is clean. A couple of minor observations:

  • DBDeltaChart.tsx:373useEffect resets page on xMin/xMax/yMin/yMax changes, but these default to 0 when null. The effect will fire on transition from null → selection (correct), but won't fire when transitioning from selection → null if the last-used coords were also 0 (extremely unlikely edge case, acceptable).
  • PropertyComparisonChart.tsx:171outlierCount dataKey is reused for the "All spans" bar. This works because allSpansData is mapped as the "outlier" in DBDeltaChart, but the coupling is subtle. A brief comment noting this intent would help future maintainers.
  • DBDeltaChart.tsx:242allSpansData query uses select: '*' with no range filter; this is intentional (show full distribution) and consistent with the PR description, but note it fetches up to SAMPLE_SIZE rows on every tab load, so performance at large data volumes is bounded by that limit. No action needed.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 5, 2026

Claude encountered an error —— View job


I'll analyze this and get back to you.

alex-fedotyev pushed a commit that referenced this pull request Mar 5, 2026
Two fixes from code review:

1. computeComparisonScore empty-group fallback: when one group has no
   data, normalize the present group's values to percentages [0,100]
   instead of using raw counts. This prevents single-value fields with
   high raw counts from inflating their score relative to multi-value
   fields. Fixes scale inconsistency with distribution mode in #1855.

2. Wire semanticBoost into DBDeltaChart sort as a tiebreaker (0.1
   weight, only when baseScore > 0). Previously exported and tested
   but never called.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@alex-fedotyev
Copy link
Contributor Author

Code Review

✅ No critical issues found. Clean implementation of always-on distribution mode.

  • ⚠️ allSpansData query has no with (CTE) clauses — the outlier/inlier queries use buildWithClauses() for the PartIds CTE, but allSpansData just uses { ...config, select: '*' } without any CTE. This is correct (no range filter needed), but if the base config has existing with clauses from the parent, they might leak through. The ...config spread includes config.with which was explicitly set to undefined by DBSearchHeatmapChart — verify this is always the case.

  • ⚠️ useQueriedChartConfig enabled option — confirm this hook respects the { enabled: false } option to skip the query. The diff adds it but the hook signature isn't shown. If it doesn't support this option, the outlier/inlier queries will still fire when there's no selection (with xMin=0, xMax=0 etc.), potentially returning incorrect data.

  • ℹ️ No date-range reset effect — the reference implementation had a useEffect that clears selection when the date range changes. This PR doesn't include it, meaning a stale selection could persist across time range changes. Not a blocker for the initial PR but worth adding as a follow-up.

  • ℹ️ Loading state shows even when isLoading is true but data exists from a previous queryisLoading && visibleOnPage.length === 0 && hiddenOnPage.length === 0 guards against this for the placeholder, but the legend shows "Loading…" via isLoading alone. Minor UX consideration.

Overall: well-structured change with clean separation of concerns. The hasSelection derivation pattern is solid and the conditional query enabling is the right approach.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Event Deltas: Always-on attribute distribution mode (no selection required)

1 participant