@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 +8 -0
- package/dist/MetricsGraph/UtilizationMetrics/index.d.ts.map +1 -1
- package/dist/MetricsGraph/UtilizationMetrics/index.js +4 -1
- package/dist/MetricsGraph/index.d.ts +1 -0
- package/dist/MetricsGraph/index.d.ts.map +1 -1
- package/dist/MetricsGraph/index.js +6 -2
- package/dist/ProfileSelector/MetricsGraphSection.d.ts.map +1 -1
- package/dist/ProfileSelector/MetricsGraphSection.js +6 -6
- package/dist/ProfileSelector/index.d.ts +2 -1
- package/dist/ProfileSelector/index.d.ts.map +1 -1
- package/dist/ProfileSelector/index.js +25 -19
- package/dist/hooks/useQueryState.d.ts.map +1 -1
- package/dist/hooks/useQueryState.js +6 -1
- package/dist/useSumBy.js +1 -1
- package/package.json +3 -3
- package/src/MetricsGraph/UtilizationMetrics/index.tsx +4 -1
- package/src/MetricsGraph/index.tsx +7 -2
- package/src/ProfileSelector/MetricsGraphSection.tsx +17 -19
- package/src/ProfileSelector/index.tsx +25 -16
- package/src/hooks/useQueryState.ts +6 -2
- package/src/useSumBy.ts +1 -1
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;
|
|
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,
|
|
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;
|
|
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
|
-
//
|
|
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,
|
|
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(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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;
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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;
|
|
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:
|
|
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
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.19.
|
|
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.
|
|
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": "
|
|
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
|
-
//
|
|
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
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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:
|
|
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
|
|