fix(dashboards): Align time series X axis ticks to user timezone#109881
Draft
gggritso wants to merge 12 commits into
Draft
fix(dashboards): Align time series X axis ticks to user timezone#109881gggritso wants to merge 12 commits into
gggritso wants to merge 12 commits into
Conversation
ECharts can only place ticks at browser-local or UTC boundaries. When the user's Sentry timezone setting differs from their browser timezone, ticks appear at non-round times (e.g., "9:00 PM" on every tick instead of midnight). Use ECharts' `customValues` feature to compute tick positions at round boundaries in the user's configured timezone. Adds a `generateTimezoneAlignedTicks` utility that mirrors ECharts' interval selection algorithm but uses moment-timezone to snap ticks to the correct timezone. No data shifting is needed — timestamps stay as real UTC everywhere, so zoom, tooltips, and release bubbles are unaffected. Refs DAIN-594 Co-Authored-By: Claude <noreply@anthropic.com>
Track tick generation duration via Sentry.metrics.distribution to monitor performance in production. Tags include the chosen interval unit and tick count. Refs DAIN-594 Co-Authored-By: Claude <noreply@anthropic.com>
Separate the snapped date computation into its own variable to make the day boundary snapping logic easier to read. Refs DAIN-594 Co-Authored-By: Claude <noreply@anthropic.com>
…ation Add a visual test story with 21 charts covering standard time ranges, DST transitions, and edge cases. The story overrides the user timezone to Asia/Kolkata to simulate a browser/Sentry timezone mismatch, verifying that ticks land on round boundaries. Also removes axisLabel.customValues to work around an ECharts 6.0.0 bug in leveledFormat.
…ensity The X axis label formatter was parsing tick values in browser-local time, but generateTimezoneAlignedTicks places ticks at round boundaries in the user's configured timezone. This caused labels like "10:30 AM" (browser-local) instead of "12:00 AM" (user timezone). Add a timezone parameter to formatXAxisTimestamp so it interprets tick values in the correct timezone via moment-timezone. Also bump splitNumber from 5 to 10 to match ECharts' default tick density, and revert the broken type:'value' axis workaround. Improve code comments explaining the flat tick generation + cascading formatter approach. Co-Authored-By: Claude <noreply@anthropic.com>
…ver stories Change the year-boundary label format from "Jan 1st 2025" to just "2025" for a cleaner axis when crossing year boundaries. Add story test cases for day, month, and year boundary rollover to demonstrate the cascading formatter producing mixed-granularity labels. Bold the chart titles for better readability. Co-Authored-By: Claude <noreply@anthropic.com>
Simplify formatXAxisTimestamp to accept (value, timezone) instead of an options object. Restructure generateTimezoneAlignedTicks with the main function at top and helpers below. Clean up test files with helpers at bottom and array-style parameterized tests. Extract makeRandomWalkTimeSeries to its own file and test cases to a constant in the story. Co-Authored-By: Claude <noreply@anthropic.com>
Remove export from getParser in dates.tsx since it's only used internally. Use `attributes` instead of `tags` in Sentry metrics distribution call to match the MetricOptions type. Co-Authored-By: Claude <noreply@anthropic.com>
This comment was marked as outdated.
This comment was marked as outdated.
Resolved conflict in timeSeriesWidgetVisualization.tsx: combined React imports from both branches (useEffect + useState from master, useMemo from our branch; Fragment removed as it's no longer used).
This comment was marked as outdated.
This comment was marked as outdated.
Contributor
📊 Type Coverage Diff✅ No new type safety issues introduced. Coverage: 93.47% |
…ignature change
- Replace `return undefined` with bare `return` to satisfy unicorn/no-useless-undefined
- Fix default import of ConfigStore to named import (no default export)
- Update HeatMapWidgetVisualization to use the new `timezone: string` signature of formatXAxisTimestamp instead of the old `{ utc: boolean | undefined }` object
Co-Authored-By: Claude <noreply@anthropic.com>
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.
Compute timezone-aware tick positions for time series chart X axes using ECharts'
customValues, so ticks always land on round boundaries in the user's configured timezone.Before:

After:

ECharts can only snap ticks to browser-local or UTC boundaries. When a user's Sentry timezone differs from their browser timezone, ticks appear at non-round times (e.g., "9:30 PM" instead of "12:00 AM"). This replaces the built-in tick placement with a custom algorithm that snaps to round boundaries in the user's timezone, paired with a cascading formatter that produces mixed-granularity labels (e.g., "2025 | Feb | Mar | 2:00 PM").
The custom algorithm uses a flat single-pass approach (pick one interval, snap, walk forward) rather than ECharts' multi-level hierarchy. Mixed-granularity formatting is handled separately by
formatXAxisTimestamp, which inspects each tick and cascades through format levels based on what round boundary it falls on. This produces the same visual result as ECharts' built-in hierarchy.Note: ECharts 6.0.0 has a bug (#21226) where
customValuesticks crash inleveledFormatbecause they lack a.timeproperty. The fix is merged upstream (PR #21352) but not yet released. Local patches tonode_modulesare applied as a workaround — these should be made permanent viapnpm patchor removed once a new ECharts version ships.Tl:DR we are awaiting ECharts 6.1.0!
Closes DAIN-594