@parca/profile 0.19.75 → 0.19.77

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [0.19.77](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.76...@parca/profile@0.19.77) (2025-11-19)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
10
+ ## [0.19.76](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.75...@parca/profile@0.19.76) (2025-11-19)
11
+
12
+ **Note:** Version bump only for package @parca/profile
13
+
6
14
  ## [0.19.75](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.74...@parca/profile@0.19.75) (2025-11-18)
7
15
 
8
16
  **Note:** Version bump only for package @parca/profile
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/MetricsGraph/UtilizationMetrics/index.tsx"],"names":[],"mappings":"AAkBA,OAAO,EACL,aAAa,EAId,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAC,KAAK,kBAAkB,IAAI,YAAY,EAAC,MAAM,uBAAuB,CAAC;AAI9E,UAAU,WAAW;IACnB,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/C;AAYD,KAAK,KAAK,GAAG,WAAW,GAAG;IACzB,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,eAAe,CAAC,EAAE,CAChB,MAAM,EAAE;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,GAAG,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,KACvE,IAAI,CAAC;IACV,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,KAAK,IAAI,CAAC;CAChF,CAAC;AAyTF,QAAA,MAAM,kBAAkB,GAAI,6KAWzB,KAAK,KAAG,GAAG,CAAC,OAwCd,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/MetricsGraph/UtilizationMetrics/index.tsx"],"names":[],"mappings":"AAkBA,OAAO,EACL,aAAa,EAId,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAC,KAAK,kBAAkB,IAAI,YAAY,EAAC,MAAM,uBAAuB,CAAC;AAI9E,UAAU,WAAW;IACnB,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/C;AAYD,KAAK,KAAK,GAAG,WAAW,GAAG;IACzB,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,eAAe,CAAC,EAAE,CAChB,MAAM,EAAE;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,GAAG,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,KACvE,IAAI,CAAC;IACV,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,KAAK,IAAI,CAAC;CAChF,CAAC;AA4TF,QAAA,MAAM,kBAAkB,GAAI,6KAWzB,KAAK,KAAG,GAAG,CAAC,OAwCd,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -122,7 +122,10 @@ const _getYAxisUnit = (name) => {
122
122
  };
123
123
  const RawUtilizationMetrics = ({ data, originalData, setTimeRange, width, height, margin, humanReadableName, from, to, yAxisUnit, contextMenuItems, onSeriesClick, }) => {
124
124
  const { timezone } = useParcaContext();
125
- return (_jsx(MetricsGraph, { data: data, from: from, to: to, setTimeRange: setTimeRange, onSampleClick: closestPoint => {
125
+ return (_jsx(MetricsGraph, { data: data.map((val, idx) => ({
126
+ ...val,
127
+ highlighted: originalData?.[idx]?.isSelected ?? false,
128
+ })), from: from, to: to, setTimeRange: setTimeRange, onSampleClick: closestPoint => {
126
129
  if (onSeriesClick != null) {
127
130
  onSeriesClick(closestPoint.seriesIndex);
128
131
  }
@@ -29,6 +29,7 @@ export interface HighlightedSeries {
29
29
  export interface Series {
30
30
  id: string;
31
31
  values: Array<[number, number]>;
32
+ highlighted?: boolean;
32
33
  }
33
34
  declare const MetricsGraph: ({ data, from, to, onSampleClick, setTimeRange, yAxisLabel, yAxisUnit, width, height, margin, selectedPoint, contextMenuItems, renderTooltipContent, }: Props) => JSX.Element;
34
35
  export default MetricsGraph;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/MetricsGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAgE,MAAM,OAAO,CAAC;AAOrF,OAAO,EAAC,aAAa,EAAkB,MAAM,mBAAmB,CAAC;AAMjE,OAA2B,EACzB,eAAe,EACf,wBAAwB,EACxB,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAI9B,UAAU,KAAK;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,CAAC,YAAY,EAAE,WAAW,KAAK,IAAI,CAAC;IACnD,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,gBAAgB,CAAC,EAAE,wBAAwB,EAAE,CAAC;IAC9C,oBAAoB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;CACrF;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACjC;AAED,QAAA,MAAM,YAAY,GAAI,uJAcnB,KAAK,KAAG,GAAG,CAAC,OA+Bd,CAAC;AAEF,eAAe,YAAY,CAAC;AAC5B,YAAY,EAAC,wBAAwB,EAAE,eAAe,EAAE,kBAAkB,EAAC,CAAC;AAE5E,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,KAAG,MAAM,GAAG,IAKnD,CAAC;AAKF,eAAO,MAAM,eAAe,GAAI,uJAc7B,KAAK,KAAG,GAAG,CAAC,OA6ad,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/MetricsGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAgE,MAAM,OAAO,CAAC;AAOrF,OAAO,EAAC,aAAa,EAAkB,MAAM,mBAAmB,CAAC;AAMjE,OAA2B,EACzB,eAAe,EACf,wBAAwB,EACxB,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAI9B,UAAU,KAAK;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,CAAC,YAAY,EAAE,WAAW,KAAK,IAAI,CAAC;IACnD,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,gBAAgB,CAAC,EAAE,wBAAwB,EAAE,CAAC;IAC9C,oBAAoB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;CACrF;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAChC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,QAAA,MAAM,YAAY,GAAI,uJAcnB,KAAK,KAAG,GAAG,CAAC,OA+Bd,CAAC;AAEF,eAAe,YAAY,CAAC;AAC5B,YAAY,EAAC,wBAAwB,EAAE,eAAe,EAAE,kBAAkB,EAAC,CAAC;AAE5E,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,KAAG,MAAM,GAAG,IAKnD,CAAC;AAKF,eAAO,MAAM,eAAe,GAAI,uJAc7B,KAAK,KAAG,GAAG,CAAC,OAibd,CAAC"}
@@ -85,7 +85,10 @@ export const RawMetricsGraph = ({ data, from, to, onSampleClick, setTimeRange, y
85
85
  }, [series]);
86
86
  const l = d3.line(d => xScale(d[0]), d => yScale(d[1]));
87
87
  const closestPoint = useMemo(() => {
88
- // Return the closest point as the highlighted point
88
+ // Guard against empty series
89
+ if (series.length === 0) {
90
+ return null;
91
+ }
89
92
  const closestPointPerSeries = series.map(function (s) {
90
93
  const distances = s.values.map(d => {
91
94
  const x = xScale(d[0]) + margin / 2; // d[0] is timestamp_ms
@@ -219,7 +222,8 @@ export const RawMetricsGraph = ({ data, from, to, onSampleClick, setTimeRange, y
219
222
  transform: `translate(0, ${yScale(d)})`, children: [_jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x2: -6 }), _jsx("text", { fill: "currentColor", x: -9, dy: '0.32em', children: valueFormatter(d, yAxisUnit, decimals) })] }, `tick-${i}`), _jsx("g", { children: _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(from), x2: xScale(to), y1: yScale(d), y2: yScale(d) }) }, `grid-${i}`)] }, `${i.toString()}-${d.toString()}`));
220
223
  }), _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: 0, x2: 0, y1: 0, y2: height - margin }), _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(to), x2: xScale(to), y1: 0, y2: height - margin }), _jsx("g", { transform: `translate(${-margin}, ${(height - margin) / 2}) rotate(270)`, children: _jsx("text", { fill: "currentColor", dy: "-0.7em", className: "text-sm capitalize", textAnchor: "middle", children: yAxisLabel }) })] }), _jsxs("g", { className: "x axis", fill: "none", fontSize: "10", textAnchor: "middle", transform: `translate(0,${height - margin})`, children: [xScale.ticks(5).map((d, i) => (_jsxs(Fragment, { children: [_jsxs("g", { className: "tick",
221
224
  /* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
222
- transform: `translate(${xScale(d)}, 0)`, children: [_jsx("line", { y2: 6, className: "stroke-gray-300 dark:stroke-gray-500" }), _jsx("text", { fill: "currentColor", dy: ".71em", y: 9, children: formatDate(d, formatForTimespan(from, to), timezone) })] }, `tick-${i}`), _jsx("g", { children: _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(d), x2: xScale(d), y1: 0, y2: -height + margin }) }, `grid-${i}`)] }, `${i.toString()}-${d.toString()}`))), _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: 0, x2: graphWidth, y1: 0, y2: 0 }), _jsx("g", { transform: `translate(${(width - 2.5 * margin) / 2}, ${margin / 2})`, children: _jsx("text", { fill: "currentColor", dy: ".71em", y: 5, className: "text-sm", children: "Time" }) })] }), _jsx("g", { className: "lines fill-transparent", transform: graphTransform, width: graphWidth - 100, children: series.map((s, i) => (_jsx("g", { className: "line", children: _jsx(MetricsSeries, { data: s, line: l, color: color(s.id), strokeWidth: hovering && highlighted != null && i === highlighted.seriesIndex
225
+ transform: `translate(${xScale(d)}, 0)`, children: [_jsx("line", { y2: 6, className: "stroke-gray-300 dark:stroke-gray-500" }), _jsx("text", { fill: "currentColor", dy: ".71em", y: 9, children: formatDate(d, formatForTimespan(from, to), timezone) })] }, `tick-${i}`), _jsx("g", { children: _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(d), x2: xScale(d), y1: 0, y2: -height + margin }) }, `grid-${i}`)] }, `${i.toString()}-${d.toString()}`))), _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: 0, x2: graphWidth, y1: 0, y2: 0 }), _jsx("g", { transform: `translate(${(width - 2.5 * margin) / 2}, ${margin / 2})`, children: _jsx("text", { fill: "currentColor", dy: ".71em", y: 5, className: "text-sm", children: "Time" }) })] }), _jsx("g", { className: "lines fill-transparent", transform: graphTransform, width: graphWidth - 100, children: series.map((s, i) => (_jsx("g", { className: "line", children: _jsx(MetricsSeries, { data: s, line: l, color: color(s.id), strokeWidth: (hovering && highlighted != null && i === highlighted.seriesIndex) ||
226
+ s.highlighted === true
223
227
  ? lineStrokeHover
224
228
  : lineStroke, xScale: xScale, yScale: yScale }) }, s.id))) }), hovering && highlighted != null && (_jsx("g", { className: "circle-group", ref: metricPointRef, style: { fill: color(series[highlighted.seriesIndex]?.id ?? '0') }, transform: graphTransform, children: _jsx(MetricsCircle, { cx: highlighted.x, cy: highlighted.y }) })), selected != null && (_jsx("g", { className: "circle-group", style: selected?.seriesIndex != null
225
229
  ? { fill: color(series[selected.seriesIndex]?.id ?? '0') }
@@ -1 +1 @@
1
- {"version":3,"file":"MetricsGraphSection.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/MetricsGraphSection.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAQ,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACxD,OAAO,EAAC,aAAa,EAAmB,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAEpC,OAAO,EAAC,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAKpC,OAAO,EAAC,cAAc,EAAE,KAAK,kBAAkB,IAAI,sBAAsB,EAAC,MAAM,SAAS,CAAC;AAE1F,UAAU,wBAAwB;IAChC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gCAAgC,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACvB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,kBAAkB,CAAC;IAChC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qBAAqB,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACtD,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAChF,KAAK,EAAE,KAAK,CAAC;IACb,qBAAqB,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3E,kBAAkB,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,kBAAkB,CAAC,EAAE,KAAK,CAAC;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,iBAAiB,EAAE,MAAM,CAAC;QAC1B,IAAI,EAAE,sBAAsB,EAAE,CAAC;KAChC,CAAC,CAAC;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,yBAAyB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3D;AAED,wBAAgB,mBAAmB,CAAC,EAClC,gBAAgB,EAChB,gCAAgC,EAChC,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,KAAK,EACL,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,WAAW,EACX,mBAAmB,EACnB,KAAK,EACL,qBAAqB,EACrB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,GAC1B,EAAE,wBAAwB,GAAG,GAAG,CAAC,OAAO,CA8MxC"}
1
+ {"version":3,"file":"MetricsGraphSection.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/MetricsGraphSection.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAQ,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACxD,OAAO,EAAC,aAAa,EAAmB,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAEpC,OAAO,EAAC,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAKpC,OAAO,EAAC,cAAc,EAAE,KAAK,kBAAkB,IAAI,sBAAsB,EAAC,MAAM,SAAS,CAAC;AAE1F,UAAU,wBAAwB;IAChC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gCAAgC,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACvB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,kBAAkB,CAAC;IAChC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qBAAqB,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACtD,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAChF,KAAK,EAAE,KAAK,CAAC;IACb,qBAAqB,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3E,kBAAkB,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,kBAAkB,CAAC,EAAE,KAAK,CAAC;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,iBAAiB,EAAE,MAAM,CAAC;QAC1B,IAAI,EAAE,sBAAsB,EAAE,CAAC;KAChC,CAAC,CAAC;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,yBAAyB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3D;AAED,wBAAgB,mBAAmB,CAAC,EAClC,gBAAgB,EAChB,gCAAgC,EAChC,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,KAAK,EACL,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,WAAW,EACX,mBAAmB,EACnB,KAAK,EACL,qBAAqB,EACrB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,GAC1B,EAAE,wBAAwB,GAAG,GAAG,CAAC,OAAO,CA4MxC"}
@@ -91,12 +91,12 @@ export function MetricsGraphSection({ showMetricsGraph, setDisplayHideMetricsGra
91
91
  return (_jsxs("div", { children: [utilizationMetrics.map(({ name, humanReadableName, data }) => {
92
92
  if (name !== 'gpu_pcie_throughput_transmit_bytes' &&
93
93
  name !== 'gpu_pcie_throughput_receive_bytes') {
94
- return (_jsx(_Fragment, { children: _jsx(UtilizationMetricsGraph, { data: data, setTimeRange: handleTimeRangeChange, utilizationMetricsLoading: utilizationMetricsLoading, humanReadableName: humanReadableName, from: querySelection.from, to: querySelection.to, yAxisUnit: "percentage", addLabelMatcher: addLabelMatcher, onSeriesClick: seriesIndex => {
95
- // For generic UtilizationMetrics, just pass the series index
96
- if (onUtilizationSeriesSelect != null) {
97
- onUtilizationSeriesSelect(seriesIndex);
98
- }
99
- } }, name) }));
94
+ return (_jsx(UtilizationMetricsGraph, { data: data, setTimeRange: handleTimeRangeChange, utilizationMetricsLoading: utilizationMetricsLoading, humanReadableName: humanReadableName, from: querySelection.from, to: querySelection.to, yAxisUnit: "percentage", addLabelMatcher: addLabelMatcher, onSeriesClick: seriesIndex => {
95
+ // For generic UtilizationMetrics, just pass the series index
96
+ if (onUtilizationSeriesSelect != null) {
97
+ onUtilizationSeriesSelect(seriesIndex);
98
+ }
99
+ } }, name));
100
100
  }
101
101
  return null;
102
102
  }), throughputMetrics.length > 0 && (_jsx(AreaChart, { transmitData: throughputMetrics.find(metric => metric.name === 'gpu_pcie_throughput_transmit_bytes')
@@ -53,6 +53,7 @@ interface ProfileSelectorProps extends ProfileSelectorFeatures {
53
53
  utilizationMetricsLoading?: boolean;
54
54
  utilizationLabels?: UtilizationLabels;
55
55
  onUtilizationSeriesSelect?: (seriesIndex: number) => void;
56
+ onSearchHook?: () => void;
56
57
  }
57
58
  export interface IProfileTypesResult {
58
59
  loading: boolean;
@@ -60,6 +61,6 @@ export interface IProfileTypesResult {
60
61
  error?: RpcError;
61
62
  }
62
63
  export declare const useProfileTypes: (client: QueryServiceClient, start?: number, end?: number) => IProfileTypesResult;
63
- declare const ProfileSelector: ({ queryClient, closeProfile, enforcedProfileName, comparing, navigateTo, showMetricsGraph, showSumBySelector, showProfileTypeSelector, disableExplorativeQuerying, setDisplayHideMetricsGraphButton, suffix, utilizationMetrics, utilizationMetricsLoading, utilizationLabels, onUtilizationSeriesSelect, }: ProfileSelectorProps) => JSX.Element;
64
+ declare const ProfileSelector: ({ queryClient, closeProfile, enforcedProfileName, comparing, navigateTo, showMetricsGraph, showSumBySelector, showProfileTypeSelector, disableExplorativeQuerying, setDisplayHideMetricsGraphButton, suffix, utilizationMetrics, utilizationMetricsLoading, utilizationLabels, onUtilizationSeriesSelect, onSearchHook, }: ProfileSelectorProps) => JSX.Element;
64
65
  export default ProfileSelector;
65
66
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,QAAQ,EAAE,cAAc,EAAoD,MAAM,OAAO,CAAC;AAElG,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAElD,OAAO,EAAsB,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAW5F,OAAO,EAAyB,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAW/E,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,uBAAuB;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE;QACR,MAAM,EAAE,KAAK,CAAC;YACZ,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,EAAE,MAAM,CAAC;SACf,CAAC,CAAC;KACJ,CAAC;IACF,OAAO,EAAE,KAAK,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,iBAAiB;IAChC,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,2BAA2B,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACjE,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,4BAA4B,CAAC,EAAE,OAAO,CAAC;CACxC;AAED,UAAU,oBAAqB,SAAQ,uBAAuB;IAC5D,WAAW,EAAE,kBAAkB,CAAC;IAChC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,gCAAgC,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,kBAAkB,CAAC,EAAE,KAAK,CAAC;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,iBAAiB,EAAE,MAAM,CAAC;QAC1B,IAAI,EAAE,kBAAkB,EAAE,CAAC;KAC5B,CAAC,CAAC;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,yBAAyB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3D;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,GAC1B,QAAQ,kBAAkB,EAC1B,QAAQ,MAAM,EACd,MAAM,MAAM,KACX,mBAsBF,CAAC;AAEF,QAAA,MAAM,eAAe,GAAI,6SAgBtB,oBAAoB,KAAG,GAAG,CAAC,OAwN7B,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,QAAQ,EAAE,cAAc,EAAoD,MAAM,OAAO,CAAC;AAElG,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAElD,OAAO,EAAsB,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAY5F,OAAO,EAAyB,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAW/E,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,uBAAuB;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE;QACR,MAAM,EAAE,KAAK,CAAC;YACZ,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,EAAE,MAAM,CAAC;SACf,CAAC,CAAC;KACJ,CAAC;IACF,OAAO,EAAE,KAAK,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,iBAAiB;IAChC,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,2BAA2B,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACjE,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,4BAA4B,CAAC,EAAE,OAAO,CAAC;CACxC;AAED,UAAU,oBAAqB,SAAQ,uBAAuB;IAC5D,WAAW,EAAE,kBAAkB,CAAC;IAChC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,gCAAgC,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,kBAAkB,CAAC,EAAE,KAAK,CAAC;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,iBAAiB,EAAE,MAAM,CAAC;QAC1B,IAAI,EAAE,kBAAkB,EAAE,CAAC;KAC5B,CAAC,CAAC;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,yBAAyB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,GAC1B,QAAQ,kBAAkB,EAC1B,QAAQ,MAAM,EACd,MAAM,MAAM,KACX,mBAsBF,CAAC;AAEF,QAAA,MAAM,eAAe,GAAI,2TAiBtB,oBAAoB,KAAG,GAAG,CAAC,OA8N7B,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -12,7 +12,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
15
- import { DateTimeRange, IconButton, useGrpcMetadata, useParcaContext, useURLState, } from '@parca/components';
15
+ import { DateTimeRange, IconButton, useGrpcMetadata, useParcaContext, useURLState, useURLStateBatch, } from '@parca/components';
16
16
  import { CloseIcon } from '@parca/icons';
17
17
  import { Query } from '@parca/parser';
18
18
  import { TEST_IDS, testId } from '@parca/test-utils';
@@ -45,10 +45,11 @@ export const useProfileTypes = (client, start, end) => {
45
45
  });
46
46
  return { loading: isLoading, data, error: error };
47
47
  };
48
- const ProfileSelector = ({ queryClient, closeProfile, enforcedProfileName, comparing, navigateTo, showMetricsGraph = true, showSumBySelector = true, showProfileTypeSelector = true, disableExplorativeQuerying = false, setDisplayHideMetricsGraphButton, suffix, utilizationMetrics, utilizationMetricsLoading, utilizationLabels, onUtilizationSeriesSelect, }) => {
48
+ const ProfileSelector = ({ queryClient, closeProfile, enforcedProfileName, comparing, navigateTo, showMetricsGraph = true, showSumBySelector = true, showProfileTypeSelector = true, disableExplorativeQuerying = false, setDisplayHideMetricsGraphButton, suffix, utilizationMetrics, utilizationMetricsLoading, utilizationLabels, onUtilizationSeriesSelect, onSearchHook, }) => {
49
49
  const { heightStyle } = useMetricsGraphDimensions(comparing, utilizationMetrics != null);
50
50
  const { viewComponent } = useParcaContext();
51
51
  const [queryBrowserMode, setQueryBrowserMode] = useURLState('query_browser_mode');
52
+ const batchUpdates = useURLStateBatch();
52
53
  // Use the new useQueryState hook - reads directly from URL params
53
54
  const { querySelection, draftSelection, setDraftExpression, setDraftTimeRange, setDraftSumBy, setDraftProfileName, setDraftMatchers, commitDraft, profileSelection, setProfileSelection, sumByLoading, } = useQueryState({ suffix });
54
55
  // Use draft state for local state instead of committed state
@@ -88,23 +89,28 @@ const ProfileSelector = ({ queryClient, closeProfile, enforcedProfileName, compa
88
89
  const query = enforcedProfileName !== '' ? enforcedProfileNameQuery() : Query.parse(queryExpressionString);
89
90
  const selectedProfileName = query.profileName();
90
91
  const setQueryExpression = (updateTs = false) => {
91
- // When updateTs is true, re-evaluate the time range to current values
92
- if (updateTs) {
93
- // Force re-evaluation of time range (important for relative ranges like "last 15 minutes")
94
- const currentFrom = timeRangeSelection.getFromMs(true);
95
- const currentTo = timeRangeSelection.getToMs(true);
96
- const currentRangeKey = timeRangeSelection.getRangeKey();
97
- // Commit with refreshed time range
98
- commitDraft({
99
- from: currentFrom,
100
- to: currentTo,
101
- timeSelection: currentRangeKey,
102
- });
103
- }
104
- else {
105
- // Commit the draft with existing values
106
- commitDraft();
107
- }
92
+ batchUpdates(() => {
93
+ if (onSearchHook != null) {
94
+ onSearchHook();
95
+ }
96
+ // When updateTs is true, re-evaluate the time range to current values
97
+ if (updateTs) {
98
+ // Force re-evaluation of time range (important for relative ranges like "last 15 minutes")
99
+ const currentFrom = timeRangeSelection.getFromMs(true);
100
+ const currentTo = timeRangeSelection.getToMs(true);
101
+ const currentRangeKey = timeRangeSelection.getRangeKey();
102
+ // Commit with refreshed time range
103
+ commitDraft({
104
+ from: currentFrom,
105
+ to: currentTo,
106
+ timeSelection: currentRangeKey,
107
+ });
108
+ }
109
+ else {
110
+ // Commit the draft with existing values
111
+ commitDraft();
112
+ }
113
+ });
108
114
  };
109
115
  const setMatchersString = (matchers) => {
110
116
  // Update draft state only
@@ -1 +1 @@
1
- {"version":3,"file":"useQueryState.d.ts","sourceRoot":"","sources":["../../src/hooks/useQueryState.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAEpC,OAAO,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAC,gBAAgB,EAA8B,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAG7F,UAAU,oBAAoB;IAC5B,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,mBAAmB;IAE3B,cAAc,EAAE,cAAc,CAAC;IAG/B,cAAc,EAAE,cAAc,CAAC;IAG/B,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnE,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7E,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,KAAK,IAAI,CAAC;IACrD,mBAAmB,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,gBAAgB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAG7C,WAAW,EAAE,CAAC,kBAAkB,CAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAC,KAAK,IAAI,CAAC;IAG9F,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAG1C,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IAGpC,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAGhF,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,eAAO,MAAM,aAAa,GAAI,UAAS,oBAAyB,KAAG,mBAgWlE,CAAC"}
1
+ {"version":3,"file":"useQueryState.d.ts","sourceRoot":"","sources":["../../src/hooks/useQueryState.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAEpC,OAAO,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAC,gBAAgB,EAA8B,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAI7F,UAAU,oBAAoB;IAC5B,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,mBAAmB;IAE3B,cAAc,EAAE,cAAc,CAAC;IAG/B,cAAc,EAAE,cAAc,CAAC;IAG/B,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnE,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7E,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,KAAK,IAAI,CAAC;IACrD,mBAAmB,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,gBAAgB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAG7C,WAAW,EAAE,CAAC,kBAAkB,CAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAC,KAAK,IAAI,CAAC;IAG9F,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAG1C,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IAGpC,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAGhF,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,eAAO,MAAM,aAAa,GAAI,UAAS,oBAAyB,KAAG,mBAmWlE,CAAC"}
@@ -14,12 +14,14 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
14
14
  import { DateTimeRange, useParcaContext, useURLState, useURLStateBatch } from '@parca/components';
15
15
  import { Query } from '@parca/parser';
16
16
  import { ProfileSelectionFromParams } from '../ProfileSource';
17
+ import { useResetFlameGraphState } from '../ProfileView/hooks/useResetFlameGraphState';
17
18
  import { sumByToParam, useSumBy, useSumByFromParams } from '../useSumBy';
18
19
  export const useQueryState = (options = {}) => {
19
20
  const { queryServiceClient: queryClient } = useParcaContext();
20
21
  const { suffix = '', defaultExpression = '', defaultTimeSelection = 'relative:minute|15', // Default to 15 minutes relative
21
22
  defaultFrom, defaultTo, comparing = false, } = options;
22
23
  const batchUpdates = useURLStateBatch();
24
+ const resetFlameGraphState = useResetFlameGraphState();
23
25
  // URL state hooks with appropriate suffixes
24
26
  const [expression, setExpressionState] = useURLState(`expression${suffix}`, {
25
27
  defaultValue: defaultExpression,
@@ -114,12 +116,13 @@ export const useQueryState = (options = {}) => {
114
116
  const draftMergeTo = isDelta
115
117
  ? (BigInt(draftTimeRange.getToMs()) * 1000000n).toString()
116
118
  : undefined;
119
+ const finalSumBy = draftSumBy ?? computedSumByFromURL;
117
120
  return {
118
121
  expression: draftExpression ?? defaultExpression,
119
122
  from: draftTimeRange.getFromMs(),
120
123
  to: draftTimeRange.getToMs(),
121
124
  timeSelection: draftTimeRange.getRangeKey(),
122
- sumBy: draftSumBy ?? computedSumByFromURL, // Use draft if set, otherwise fallback to computed
125
+ sumBy: finalSumBy, // Use draft if set, otherwise fallback to computed
123
126
  ...(draftMergeFrom !== undefined &&
124
127
  draftMergeFrom !== '' &&
125
128
  draftMergeTo !== undefined &&
@@ -203,6 +206,7 @@ export const useQueryState = (options = {}) => {
203
206
  // Clear ProfileSelection for non-delta profiles
204
207
  setSelectionParam(undefined);
205
208
  }
209
+ resetFlameGraphState();
206
210
  });
207
211
  }, [
208
212
  batchUpdates,
@@ -222,6 +226,7 @@ export const useQueryState = (options = {}) => {
222
226
  setMergeFromState,
223
227
  setMergeToState,
224
228
  setSelectionParam,
229
+ resetFlameGraphState,
225
230
  ]);
226
231
  // Draft setters (update local state only, or commit directly if specified)
227
232
  const setDraftExpressionCallback = useCallback((newExpression, commit = false) => {
package/dist/useSumBy.js CHANGED
@@ -88,7 +88,7 @@ const getSumByFromParam = (param) => {
88
88
  return undefined;
89
89
  }
90
90
  if (param === '__none__') {
91
- return [];
91
+ return DEFAULT_EMPTY_SUM_BY;
92
92
  }
93
93
  if (typeof param === 'string') {
94
94
  // Handle comma-separated strings (e.g., "comm,node" -> ["comm", "node"])
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.19.75",
3
+ "version": "0.19.77",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@floating-ui/react": "^0.27.12",
7
7
  "@headlessui/react": "^1.7.19",
8
8
  "@iconify/react": "^4.0.0",
9
9
  "@parca/client": "0.17.8",
10
- "@parca/components": "0.16.381",
10
+ "@parca/components": "0.16.382",
11
11
  "@parca/dynamicsize": "0.16.67",
12
12
  "@parca/hooks": "0.0.108",
13
13
  "@parca/icons": "0.16.74",
@@ -79,5 +79,5 @@
79
79
  "access": "public",
80
80
  "registry": "https://registry.npmjs.org/"
81
81
  },
82
- "gitHead": "bedae1353c29f9903653fd4a063be5c98a563f32"
82
+ "gitHead": "c09ced4875b54404d8d2f7738137ad8c2d7774f2"
83
83
  }
@@ -201,7 +201,10 @@ const RawUtilizationMetrics = ({
201
201
 
202
202
  return (
203
203
  <MetricsGraph
204
- data={data}
204
+ data={data.map((val, idx) => ({
205
+ ...val,
206
+ highlighted: originalData?.[idx]?.isSelected ?? false,
207
+ }))}
205
208
  from={from}
206
209
  to={to}
207
210
  setTimeRange={setTimeRange}
@@ -63,6 +63,7 @@ export interface HighlightedSeries {
63
63
  export interface Series {
64
64
  id: string; // opaque string used to determine line color
65
65
  values: Array<[number, number]>; // [timestamp_ms, value]
66
+ highlighted?: boolean;
66
67
  }
67
68
 
68
69
  const MetricsGraph = ({
@@ -200,7 +201,10 @@ export const RawMetricsGraph = ({
200
201
  );
201
202
 
202
203
  const closestPoint = useMemo(() => {
203
- // Return the closest point as the highlighted point
204
+ // Guard against empty series
205
+ if (series.length === 0) {
206
+ return null;
207
+ }
204
208
 
205
209
  const closestPointPerSeries = series.map(function (s) {
206
210
  const distances = s.values.map(d => {
@@ -530,7 +534,8 @@ export const RawMetricsGraph = ({
530
534
  line={l}
531
535
  color={color(s.id)}
532
536
  strokeWidth={
533
- hovering && highlighted != null && i === highlighted.seriesIndex
537
+ (hovering && highlighted != null && i === highlighted.seriesIndex) ||
538
+ s.highlighted === true
534
539
  ? lineStrokeHover
535
540
  : lineStroke
536
541
  }
@@ -174,25 +174,23 @@ export function MetricsGraphSection({
174
174
  name !== 'gpu_pcie_throughput_receive_bytes'
175
175
  ) {
176
176
  return (
177
- <>
178
- <UtilizationMetricsGraph
179
- key={name}
180
- data={data}
181
- setTimeRange={handleTimeRangeChange}
182
- utilizationMetricsLoading={utilizationMetricsLoading}
183
- humanReadableName={humanReadableName}
184
- from={querySelection.from}
185
- to={querySelection.to}
186
- yAxisUnit="percentage"
187
- addLabelMatcher={addLabelMatcher}
188
- onSeriesClick={seriesIndex => {
189
- // For generic UtilizationMetrics, just pass the series index
190
- if (onUtilizationSeriesSelect != null) {
191
- onUtilizationSeriesSelect(seriesIndex);
192
- }
193
- }}
194
- />
195
- </>
177
+ <UtilizationMetricsGraph
178
+ key={name}
179
+ data={data}
180
+ setTimeRange={handleTimeRangeChange}
181
+ utilizationMetricsLoading={utilizationMetricsLoading}
182
+ humanReadableName={humanReadableName}
183
+ from={querySelection.from}
184
+ to={querySelection.to}
185
+ yAxisUnit="percentage"
186
+ addLabelMatcher={addLabelMatcher}
187
+ onSeriesClick={seriesIndex => {
188
+ // For generic UtilizationMetrics, just pass the series index
189
+ if (onUtilizationSeriesSelect != null) {
190
+ onUtilizationSeriesSelect(seriesIndex);
191
+ }
192
+ }}
193
+ />
196
194
  );
197
195
  }
198
196
  return null;
@@ -22,6 +22,7 @@ import {
22
22
  useGrpcMetadata,
23
23
  useParcaContext,
24
24
  useURLState,
25
+ useURLStateBatch,
25
26
  } from '@parca/components';
26
27
  import {CloseIcon} from '@parca/icons';
27
28
  import {Query} from '@parca/parser';
@@ -92,6 +93,7 @@ interface ProfileSelectorProps extends ProfileSelectorFeatures {
92
93
  utilizationMetricsLoading?: boolean;
93
94
  utilizationLabels?: UtilizationLabels;
94
95
  onUtilizationSeriesSelect?: (seriesIndex: number) => void;
96
+ onSearchHook?: () => void;
95
97
  }
96
98
 
97
99
  export interface IProfileTypesResult {
@@ -144,10 +146,12 @@ const ProfileSelector = ({
144
146
  utilizationMetricsLoading,
145
147
  utilizationLabels,
146
148
  onUtilizationSeriesSelect,
149
+ onSearchHook,
147
150
  }: ProfileSelectorProps): JSX.Element => {
148
151
  const {heightStyle} = useMetricsGraphDimensions(comparing, utilizationMetrics != null);
149
152
  const {viewComponent} = useParcaContext();
150
153
  const [queryBrowserMode, setQueryBrowserMode] = useURLState('query_browser_mode');
154
+ const batchUpdates = useURLStateBatch();
151
155
 
152
156
  // Use the new useQueryState hook - reads directly from URL params
153
157
  const {
@@ -227,22 +231,27 @@ const ProfileSelector = ({
227
231
  const selectedProfileName = query.profileName();
228
232
 
229
233
  const setQueryExpression = (updateTs = false): void => {
230
- // When updateTs is true, re-evaluate the time range to current values
231
- if (updateTs) {
232
- // Force re-evaluation of time range (important for relative ranges like "last 15 minutes")
233
- const currentFrom = timeRangeSelection.getFromMs(true);
234
- const currentTo = timeRangeSelection.getToMs(true);
235
- const currentRangeKey = timeRangeSelection.getRangeKey();
236
- // Commit with refreshed time range
237
- commitDraft({
238
- from: currentFrom,
239
- to: currentTo,
240
- timeSelection: currentRangeKey,
241
- });
242
- } else {
243
- // Commit the draft with existing values
244
- commitDraft();
245
- }
234
+ batchUpdates(() => {
235
+ if (onSearchHook != null) {
236
+ onSearchHook();
237
+ }
238
+ // When updateTs is true, re-evaluate the time range to current values
239
+ if (updateTs) {
240
+ // Force re-evaluation of time range (important for relative ranges like "last 15 minutes")
241
+ const currentFrom = timeRangeSelection.getFromMs(true);
242
+ const currentTo = timeRangeSelection.getToMs(true);
243
+ const currentRangeKey = timeRangeSelection.getRangeKey();
244
+ // Commit with refreshed time range
245
+ commitDraft({
246
+ from: currentFrom,
247
+ to: currentTo,
248
+ timeSelection: currentRangeKey,
249
+ });
250
+ } else {
251
+ // Commit the draft with existing values
252
+ commitDraft();
253
+ }
254
+ });
246
255
  };
247
256
 
248
257
  const setMatchersString = (matchers: string): void => {
@@ -18,6 +18,7 @@ import {Query} from '@parca/parser';
18
18
 
19
19
  import {QuerySelection} from '../ProfileSelector';
20
20
  import {ProfileSelection, ProfileSelectionFromParams, ProfileSource} from '../ProfileSource';
21
+ import {useResetFlameGraphState} from '../ProfileView/hooks/useResetFlameGraphState';
21
22
  import {sumByToParam, useSumBy, useSumByFromParams} from '../useSumBy';
22
23
 
23
24
  interface UseQueryStateOptions {
@@ -71,6 +72,7 @@ export const useQueryState = (options: UseQueryStateOptions = {}): UseQueryState
71
72
  } = options;
72
73
 
73
74
  const batchUpdates = useURLStateBatch();
75
+ const resetFlameGraphState = useResetFlameGraphState();
74
76
 
75
77
  // URL state hooks with appropriate suffixes
76
78
  const [expression, setExpressionState] = useURLState<string>(`expression${suffix}`, {
@@ -150,7 +152,6 @@ export const useQueryState = (options: UseQueryStateOptions = {}): UseQueryState
150
152
  draftTo !== '' ? parseInt(draftTo) : defaultTo
151
153
  );
152
154
  }, [draftTimeSelection, draftFrom, draftTo, defaultTimeSelection, defaultFrom, defaultTo]);
153
-
154
155
  // Use combined sumBy hook for fetching labels and computing defaults (based on committed state)
155
156
  const {sumBy: computedSumByFromURL, isLoading: sumBySelectionLoading} = useSumBy(
156
157
  queryClient,
@@ -201,12 +202,13 @@ export const useQueryState = (options: UseQueryStateOptions = {}): UseQueryState
201
202
  ? (BigInt(draftTimeRange.getToMs()) * 1_000_000n).toString()
202
203
  : undefined;
203
204
 
205
+ const finalSumBy = draftSumBy ?? computedSumByFromURL;
204
206
  return {
205
207
  expression: draftExpression ?? defaultExpression,
206
208
  from: draftTimeRange.getFromMs(),
207
209
  to: draftTimeRange.getToMs(),
208
210
  timeSelection: draftTimeRange.getRangeKey(),
209
- sumBy: draftSumBy ?? computedSumByFromURL, // Use draft if set, otherwise fallback to computed
211
+ sumBy: finalSumBy, // Use draft if set, otherwise fallback to computed
210
212
  ...(draftMergeFrom !== undefined &&
211
213
  draftMergeFrom !== '' &&
212
214
  draftMergeTo !== undefined &&
@@ -304,6 +306,7 @@ export const useQueryState = (options: UseQueryStateOptions = {}): UseQueryState
304
306
  // Clear ProfileSelection for non-delta profiles
305
307
  setSelectionParam(undefined);
306
308
  }
309
+ resetFlameGraphState();
307
310
  });
308
311
  },
309
312
  [
@@ -324,6 +327,7 @@ export const useQueryState = (options: UseQueryStateOptions = {}): UseQueryState
324
327
  setMergeFromState,
325
328
  setMergeToState,
326
329
  setSelectionParam,
330
+ resetFlameGraphState,
327
331
  ]
328
332
  );
329
333
 
package/src/useSumBy.ts CHANGED
@@ -145,7 +145,7 @@ const getSumByFromParam = (param: string | string[] | undefined): string[] | und
145
145
  }
146
146
 
147
147
  if (param === '__none__') {
148
- return [];
148
+ return DEFAULT_EMPTY_SUM_BY;
149
149
  }
150
150
 
151
151
  if (typeof param === 'string') {