Skip to content

Commit 6a351e8

Browse files
authored
Merge branch 'main' into aaron/alphabetize-keys
2 parents c81d77c + 85675fc commit 6a351e8

83 files changed

Lines changed: 4354 additions & 845 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@hyperdx/common-utils': patch
3+
'@hyperdx/app': patch
4+
---
5+
6+
feat: Broadcast adhoc dashboard filter conditions

‎.changeset/alert-side-panel.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@hyperdx/app': minor
3+
---
4+
5+
feat: Edit chart alerts in a side panel docked beside the chart editor, so the preview chart stays in view while the alert is tuned. "Add alert" / "Edit alert" opens the panel; a new alert is kept with "Add alert" and an existing one with "Update alert", while closing the panel discards the changes. The panel fills the editor's visible height and can be resized from its left edge. Save and Cancel move to the chart name row.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'@hyperdx/app': minor
3+
---
4+
5+
feat: add a content font size preference
6+
7+
Small text in the log/trace table was not adjustable without browser zoom, which
8+
also shrinks the surrounding chrome. User preferences now carry a **Content font
9+
size** setting (small / medium / large) that scales the search results table,
10+
data tables, expanded row JSON, and chart axes, legends, and tooltips. Small is
11+
the default and matches the previous sizes, so nothing changes until you opt in.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@hyperdx/app': patch
3+
---
4+
5+
fix: Wrap long values in release marker tooltips instead of overflowing

‎.changeset/stream-filter-values.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@hyperdx/app': patch
3+
'@hyperdx/common-utils': patch
4+
---
5+
6+
perf: stream filter values into the UI as each query finishes instead of
7+
waiting for all of them

‎packages/app/pages/_app.tsx‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { NextApiConfigResponseData } from '@/types';
3333
import { ConfirmProvider } from '@/useConfirm';
3434
import {
3535
SystemColorSchemeScript,
36+
useContentFontSize,
3637
useResolvedColorScheme,
3738
useUserPreferences,
3839
} from '@/useUserPreferences';
@@ -98,6 +99,8 @@ function AppContent({
9899
const { userPreferences } = useUserPreferences();
99100
const resolvedColorScheme = useResolvedColorScheme();
100101
const { themeName } = useAppTheme();
102+
const { base: contentFontSize, compact: compactContentFontSize } =
103+
useContentFontSize();
101104

102105
// ClickStack theme always uses Inter font - user preference is ignored
103106
// HyperDX theme allows user to select font preference
@@ -115,6 +118,21 @@ function AppContent({
115118
}
116119
}, [effectiveFont]);
117120

121+
useEffect(() => {
122+
// Single write point for the content font size preference; tables and
123+
// chart CSS read these vars (see styles/app.scss for the defaults).
124+
if (typeof document !== 'undefined') {
125+
document.documentElement.style.setProperty(
126+
'--hdx-content-font-size',
127+
`${contentFontSize}px`,
128+
);
129+
document.documentElement.style.setProperty(
130+
'--hdx-content-font-size-compact',
131+
`${compactContentFontSize}px`,
132+
);
133+
}
134+
}, [contentFontSize, compactContentFontSize]);
135+
118136
const getLayout = Component.getLayout ?? (page => page);
119137

120138
return (

‎packages/app/src/DBDashboardPage.tsx‎

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ import {
3535
isTimeSeriesDisplayType,
3636
} from '@hyperdx/common-utils/dist/core/utils';
3737
import { getBlockingRequiredFilterNames } from '@hyperdx/common-utils/dist/dashboardFilterValues';
38+
import {
39+
getPromqlFilters,
40+
getSqlFilters,
41+
} from '@hyperdx/common-utils/dist/filters';
3842
import {
3943
displayTypeRequiresSource,
4044
isBuilderChartConfig,
@@ -51,12 +55,12 @@ import {
5155
import { isMissingFiltersMacro } from '@hyperdx/common-utils/dist/macros';
5256
import {
5357
AlertState,
58+
BroadcastFilter,
5459
ChartConfigWithDateRange,
5560
ChartVariable,
5661
DashboardContainer as DashboardContainerSchema,
5762
DashboardFilter,
5863
DisplayType,
59-
Filter,
6064
getSampleWeightExpression,
6165
isLogSource,
6266
isTraceSource,
@@ -467,7 +471,7 @@ const Tile = ({
467471
onSettled?: () => void;
468472
granularity: SQLInterval | undefined;
469473
onTimeRangeSelect: (start: Date, end: Date) => void;
470-
filters?: Filter[];
474+
filters?: BroadcastFilter[];
471475
variables?: ChartVariable[];
472476
/** The dashboard's required filters that have nothing selected. */
473477
unsatisfiedRequiredFilters?: DashboardFilter[];
@@ -650,6 +654,15 @@ const Tile = ({
650654
missingRequiredFilterNames.length > 0 &&
651655
displayTypeRequiresSource(chart.config.displayType);
652656

657+
const sqlFilters = useMemo(
658+
() => (filters ? getSqlFilters(filters) : undefined),
659+
[filters],
660+
);
661+
const promqlFilters = useMemo(
662+
() => (filters ? getPromqlFilters(filters) : undefined),
663+
[filters],
664+
);
665+
653666
useEffect(() => {
654667
if (isPromqlSavedChartConfig(chart.config)) {
655668
if (source != null) {
@@ -660,6 +673,7 @@ const Tile = ({
660673
dateRange,
661674
granularity,
662675
variables: tileVariables,
676+
filters: promqlFilters,
663677
});
664678
}
665679
return;
@@ -672,7 +686,7 @@ const Tile = ({
672686
...chart.config,
673687
dateRange,
674688
granularity,
675-
filters,
689+
filters: sqlFilters,
676690
variables: tileVariables,
677691
});
678692
} else if (source != null) {
@@ -691,7 +705,7 @@ const Tile = ({
691705
sampleWeightExpression: getSampleWeightExpression(source),
692706
dateRange,
693707
granularity,
694-
filters,
708+
filters: sqlFilters,
695709
variables: tileVariables,
696710
});
697711
}
@@ -732,13 +746,21 @@ const Tile = ({
732746
? source.bodyExpression
733747
: undefined,
734748
sampleWeightExpression: getSampleWeightExpression(source),
735-
filters,
749+
filters: sqlFilters,
736750
variables: tileVariables,
737751
metricTables: isMetricSource ? source.metricTables : undefined,
738752
});
739753
}
740754
}
741-
}, [source, chart, dateRange, granularity, filters, tileVariables]);
755+
}, [
756+
source,
757+
chart,
758+
dateRange,
759+
granularity,
760+
sqlFilters,
761+
promqlFilters,
762+
tileVariables,
763+
]);
742764

743765
const [hovered, setHovered] = useState(false);
744766

@@ -809,7 +831,7 @@ const Tile = ({
809831
where: builderConfig?.where,
810832
whereLanguage: builderConfig?.whereLanguage,
811833
select: builderConfig?.select,
812-
filters,
834+
filters: sqlFilters,
813835
},
814836
);
815837

@@ -819,10 +841,10 @@ const Tile = ({
819841
);
820842

821843
const filterWarning = useMemo(() => {
822-
const doFiltersExist = !!filters?.filter(
844+
const doFiltersExist = !!sqlFilters?.filter(
823845
f => (f.type === 'lucene' || f.type === 'sql') && f.condition.trim(),
824846
)?.length;
825-
const doLuceneFiltersExist = !!filters?.filter(
847+
const doLuceneFiltersExist = !!sqlFilters?.filter(
826848
f => f.type === 'lucene' && f.condition.trim(),
827849
)?.length;
828850

@@ -858,7 +880,7 @@ const Tile = ({
858880
<IconZoomExclamation size={16} color="var(--color-text-danger)" />
859881
</Tooltip>
860882
);
861-
}, [filters, queriedConfig, source]);
883+
}, [sqlFilters, queriedConfig, source]);
862884

863885
const replaySearchUrl = useMemo(() => {
864886
return buildDashboardReplaySearchUrl({
@@ -1548,7 +1570,7 @@ const EditTileModal = ({
15481570
isSaving?: boolean;
15491571
onSave: (chart: Tile) => void;
15501572
variables?: ChartVariable[];
1551-
getDashboardFilters: (sourceId: string | undefined) => Filter[];
1573+
getDashboardFilters: (sourceId: string | undefined) => BroadcastFilter[];
15521574
unsatisfiedRequiredFilters?: DashboardFilter[];
15531575
}) => {
15541576
const contextZIndex = useZIndex();
@@ -2304,7 +2326,7 @@ function DBDashboardPage({
23042326
// `sourceId`. Shared with the tile editor so its preview queries what the
23052327
// tile does.
23062328
const getTileFilters = useCallback(
2307-
(sourceId: string | undefined): Filter[] => [
2329+
(sourceId: string | undefined): BroadcastFilter[] => [
23082330
{
23092331
type: whereLanguage === 'sql' ? 'sql' : 'lucene',
23102332
condition: where,

‎packages/app/src/HDXMultiSeriesTableChart.module.scss‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
// .rowButtons pattern from LogTable.module.scss (lines 156-172),
55
// scoped down to a single icon. See HDX-4405.
66

7+
.tableWrapper {
8+
font-size: var(--hdx-content-font-size);
9+
}
10+
711
.tableHeader {
812
// Always-on 1px separator between the sticky header and the rows. An
913
// inset box-shadow rather than a border because the table sets

‎packages/app/src/HDXMultiSeriesTableChart.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ export const Table = ({
408408

409409
return (
410410
<div
411-
className={cx('overflow-auto h-100 fs-8', className)}
411+
className={cx('overflow-auto h-100', styles.tableWrapper, className)}
412412
ref={tableContainerRef}
413413
>
414414
<table

‎packages/app/src/HDXMultiSeriesTimeChart.tsx‎

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import {
6969
toStartOfInterval,
7070
} from './ChartUtils';
7171
import { useFormatTime } from './useFormatTime';
72+
import { useContentFontSize } from './useUserPreferences';
7273

7374
import styles from '@styles/HDXLineChart.module.scss';
7475

@@ -777,7 +778,12 @@ export function collectMemoChartGradientHexes(
777778
// (NumberFormat.tsx), but 2 already distinguishes values >= 0.005 from 0.
778779
const MAX_AXIS_MANTISSA = 2;
779780

780-
/** Base width ceiling for a bare signed number - see MAX_AXIS_MANTISSA's comment. */
781+
/**
782+
* Base width ceiling for a bare signed number - see MAX_AXIS_MANTISSA's
783+
* comment. A character budget rather than a pixel one, which is why
784+
* Y_AXIS_WIDTH scales with the content font size preference: the gutter has to
785+
* grow with the tick font for this to keep holding at every setting.
786+
*/
781787
const AXIS_CHAR_BUDGET = 5;
782788

783789
// Flat, not suffix-length-scaled - IBM Plex Mono is monospace, so a longer
@@ -1351,6 +1357,12 @@ export const MemoChart = memo(function MemoChart({
13511357
const _id = useId();
13521358
const id = _id.replace(/:/g, '');
13531359

1360+
// The y-axis width budget is expressed in characters (see MAX_AXIS_MANTISSA),
1361+
// so it has to grow with the tick font or the widest labels clip.
1362+
const { compact: axisTickFontSize, scale: contentFontScale } =
1363+
useContentFontSize();
1364+
const yAxisWidth = Math.round(Y_AXIS_WIDTH * contentFontScale);
1365+
13541366
// recharts sync group, scoped via context (see chartSync).
13551367
const syncId = useChartSyncId();
13561368

@@ -1585,14 +1597,14 @@ export const MemoChart = memo(function MemoChart({
15851597
if (graphResults.length !== 1) return undefined;
15861598
const drawableWidth = Math.max(
15871599
0,
1588-
containerWidth - Y_AXIS_WIDTH - SINGLE_POINT_BAR_RIGHT_PADDING,
1600+
containerWidth - yAxisWidth - SINGLE_POINT_BAR_RIGHT_PADDING,
15891601
);
15901602
if (drawableWidth <= 0) return undefined;
15911603
return Math.max(
15921604
1,
15931605
Math.floor(drawableWidth * SINGLE_POINT_BAR_WIDTH_RATIO),
15941606
);
1595-
}, [displayType, graphResults.length, containerWidth]);
1607+
}, [displayType, graphResults.length, containerWidth, yAxisWidth]);
15961608

15971609
const formatTime = useFormatTime();
15981610
const xTickFormatter = useCallback(
@@ -1932,9 +1944,9 @@ export const MemoChart = memo(function MemoChart({
19321944
}
19331945
return layoutAnnotations(coloredAnnotations, {
19341946
domain: xAxisDomain,
1935-
plotWidth: Math.max(0, containerWidth - Y_AXIS_WIDTH),
1947+
plotWidth: Math.max(0, containerWidth - yAxisWidth),
19361948
});
1937-
}, [coloredAnnotations, xAxisDomain, containerWidth]);
1949+
}, [coloredAnnotations, xAxisDomain, containerWidth, yAxisWidth]);
19381950

19391951
const [hoveredAnnotation, setHoveredAnnotation] =
19401952
useState<HoveredAnnotation | null>(null);
@@ -1948,9 +1960,9 @@ export const MemoChart = memo(function MemoChart({
19481960
// Drawable width, so markers too close together share one label. Zero on
19491961
// the first paint (before ResponsiveContainer measures), which the
19501962
// renderer treats as "label everything".
1951-
plotWidth: Math.max(0, containerWidth - Y_AXIS_WIDTH),
1963+
plotWidth: Math.max(0, containerWidth - yAxisWidth),
19521964
});
1953-
}, [coloredAnnotations, xAxisDomain, containerWidth]);
1965+
}, [coloredAnnotations, xAxisDomain, containerWidth, yAxisWidth]);
19541966

19551967
return (
19561968
<div
@@ -2063,13 +2075,19 @@ export const MemoChart = memo(function MemoChart({
20632075
type="number"
20642076
tickFormatter={xTickFormatter}
20652077
minTickGap={100}
2066-
tick={{ fontSize: 11, fontFamily: 'IBM Plex Mono, monospace' }}
2078+
tick={{
2079+
fontSize: axisTickFontSize,
2080+
fontFamily: 'IBM Plex Mono, monospace',
2081+
}}
20672082
/>
20682083
<YAxis
2069-
width={Y_AXIS_WIDTH}
2084+
width={yAxisWidth}
20702085
minTickGap={25}
20712086
tickFormatter={yAxisTickFormatter}
2072-
tick={{ fontSize: 11, fontFamily: 'IBM Plex Mono, monospace' }}
2087+
tick={{
2088+
fontSize: axisTickFontSize,
2089+
fontFamily: 'IBM Plex Mono, monospace',
2090+
}}
20732091
domain={yAxisDomain}
20742092
ticks={yAxisTicks}
20752093
/>

0 commit comments

Comments
 (0)