@parca/profile 0.16.479 → 0.16.481
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 +12 -0
- package/dist/MetricsGraph/MetricsContextMenu/index.d.ts.map +1 -1
- package/dist/MetricsGraph/MetricsContextMenu/index.js +6 -1
- package/dist/MetricsGraph/UtilizationMetrics/index.d.ts +1 -3
- package/dist/MetricsGraph/UtilizationMetrics/index.d.ts.map +1 -1
- package/dist/MetricsGraph/UtilizationMetrics/index.js +16 -13
- package/dist/ProfileSelector/MetricsGraphSection.d.ts.map +1 -1
- package/dist/ProfileSelector/MetricsGraphSection.js +1 -3
- package/package.json +2 -2
- package/src/MetricsGraph/MetricsContextMenu/index.tsx +6 -1
- package/src/MetricsGraph/UtilizationMetrics/index.tsx +17 -16
- package/src/ProfileSelector/MetricsGraphSection.tsx +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
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.16.481](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.480...@parca/profile@0.16.481) (2025-02-26)
|
|
7
|
+
|
|
8
|
+
## 0.23.1 (2025-02-24)
|
|
9
|
+
|
|
10
|
+
**Note:** Version bump only for package @parca/profile
|
|
11
|
+
|
|
12
|
+
## [0.16.480](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.479...@parca/profile@0.16.480) (2025-02-25)
|
|
13
|
+
|
|
14
|
+
## 0.23.1 (2025-02-24)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @parca/profile
|
|
17
|
+
|
|
6
18
|
## [0.16.479](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.478...@parca/profile@0.16.479) (2025-02-25)
|
|
7
19
|
|
|
8
20
|
## 0.23.1 (2025-02-24)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/MetricsGraph/MetricsContextMenu/index.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAC,iBAAiB,EAAC,MAAM,KAAK,CAAC;AAEtC,UAAU,uBAAuB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,CACjB,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,WAAW,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACtC,eAAe,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AASD,QAAA,MAAM,kBAAkB,qFAMrB,uBAAuB,KAAG,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/MetricsGraph/MetricsContextMenu/index.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAC,iBAAiB,EAAC,MAAM,KAAK,CAAC;AAEtC,UAAU,uBAAuB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,CACjB,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,WAAW,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACtC,eAAe,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AASD,QAAA,MAAM,kBAAkB,qFAMrB,uBAAuB,KAAG,GAAG,CAAC,OAmDhC,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -30,6 +30,11 @@ const MetricsContextMenu = ({ menuId, onAddLabelMatcher, highlighted, trackVisib
|
|
|
30
30
|
}));
|
|
31
31
|
labelsToAdd !== undefined && onAddLabelMatcher(labelsToAdd);
|
|
32
32
|
};
|
|
33
|
-
return (_jsxs(Menu, { id: menuId, onVisibilityChange: trackVisibility, theme: isDarkMode ? 'dark' : '', children: [_jsx(Item, { id: "focus-on-single-series", onClick: handleFocusOnSingleSeries, children: _jsxs("div", { className: "flex w-full items-center gap-2", children: [_jsx(Icon, { icon: "ph:star" }), _jsx("div", { children: "Focus only on this series" })] }) }), _jsx(Submenu, { label: _jsxs("div", { className: "flex w-full items-center gap-2", children: [_jsx(Icon, { icon: "material-symbols:add" }), _jsx("div", { children: "Add to query" })] }), children: _jsx("div", { className: "max-h-[300px] overflow-scroll", children: labels?.map((label) => (_jsx(Item, { id: label.name, onClick: () =>
|
|
33
|
+
return (_jsxs(Menu, { id: menuId, onVisibilityChange: trackVisibility, theme: isDarkMode ? 'dark' : '', children: [_jsx(Item, { id: "focus-on-single-series", onClick: handleFocusOnSingleSeries, children: _jsxs("div", { className: "flex w-full items-center gap-2", children: [_jsx(Icon, { icon: "ph:star" }), _jsx("div", { children: "Focus only on this series" })] }) }), _jsx(Submenu, { label: _jsxs("div", { className: "flex w-full items-center gap-2", children: [_jsx(Icon, { icon: "material-symbols:add" }), _jsx("div", { children: "Add to query" })] }), children: _jsx("div", { className: "max-h-[300px] overflow-scroll", children: labels?.map((label) => (_jsx(Item, { id: label.name, onClick: () => {
|
|
34
|
+
onAddLabelMatcher({
|
|
35
|
+
key: label.name,
|
|
36
|
+
value: label.value,
|
|
37
|
+
});
|
|
38
|
+
}, className: "max-w-[400px] overflow-hidden", children: _jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-300", children: `${transformUtilizationLabels(label.name, utilizationMetrics)}="${label.value}"` }) }, label.name))) }) })] }));
|
|
34
39
|
};
|
|
35
40
|
export default MetricsContextMenu;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { DateTimeRange } from '@parca/components';
|
|
2
|
-
import { Matcher } from '@parca/parser';
|
|
3
2
|
import { type UtilizationMetrics as MetricSeries } from '../../ProfileSelector';
|
|
4
3
|
interface CommonProps {
|
|
5
4
|
data: MetricSeries[];
|
|
@@ -11,7 +10,6 @@ interface CommonProps {
|
|
|
11
10
|
value: string;
|
|
12
11
|
}>) => void;
|
|
13
12
|
setTimeRange: (range: DateTimeRange) => void;
|
|
14
|
-
selectedSeriesMatchers?: Matcher[];
|
|
15
13
|
}
|
|
16
14
|
type Props = CommonProps & {
|
|
17
15
|
data: MetricSeries[];
|
|
@@ -25,6 +23,6 @@ type Props = CommonProps & {
|
|
|
25
23
|
setTimeRange: (range: DateTimeRange) => void;
|
|
26
24
|
utilizationMetricsLoading?: boolean;
|
|
27
25
|
};
|
|
28
|
-
declare const UtilizationMetrics: ({ data, addLabelMatcher, setTimeRange, utilizationMetricsLoading,
|
|
26
|
+
declare const UtilizationMetrics: ({ data, addLabelMatcher, setTimeRange, utilizationMetricsLoading, }: Props) => JSX.Element;
|
|
29
27
|
export default UtilizationMetrics;
|
|
30
28
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/MetricsGraph/UtilizationMetrics/index.tsx"],"names":[],"mappings":"AAqBA,OAAO,EAAC,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/MetricsGraph/UtilizationMetrics/index.tsx"],"names":[],"mappings":"AAqBA,OAAO,EAAC,aAAa,EAAqD,MAAM,mBAAmB,CAAC;AAKpG,OAAO,EAAC,KAAK,kBAAkB,IAAI,YAAY,EAAC,MAAM,uBAAuB,CAAC;AAM9E,UAAU,WAAW;IACnB,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,eAAe,EAAE,CACf,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,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC9C;AAQD,KAAK,KAAK,GAAG,WAAW,GAAG;IACzB,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,eAAe,EAAE,CACf,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,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC,CAAC;AAocF,QAAA,MAAM,kBAAkB,wEAKrB,KAAK,KAAG,GAAG,CAAC,OA4Bd,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -17,7 +17,7 @@ import { pointer } from 'd3-selection';
|
|
|
17
17
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
18
18
|
import throttle from 'lodash.throttle';
|
|
19
19
|
import { useContextMenu } from 'react-contexify';
|
|
20
|
-
import { DateTimeRange, MetricsGraphSkeleton, useParcaContext } from '@parca/components';
|
|
20
|
+
import { DateTimeRange, MetricsGraphSkeleton, useParcaContext, useURLState } from '@parca/components';
|
|
21
21
|
import { formatDate, formatForTimespan, getPrecision, valueFormatter } from '@parca/utilities';
|
|
22
22
|
import MetricsSeries from '../../MetricsSeries';
|
|
23
23
|
import MetricsContextMenu from '../MetricsContextMenu';
|
|
@@ -46,7 +46,7 @@ function transformToSeries(data) {
|
|
|
46
46
|
values: series.values.sort((a, b) => a[0] - b[0]),
|
|
47
47
|
}));
|
|
48
48
|
}
|
|
49
|
-
const RawUtilizationMetrics = ({ data, addLabelMatcher, setTimeRange, width, height, margin,
|
|
49
|
+
const RawUtilizationMetrics = ({ data, addLabelMatcher, setTimeRange, width, height, margin, }) => {
|
|
50
50
|
const { timezone } = useParcaContext();
|
|
51
51
|
const graph = useRef(null);
|
|
52
52
|
const [dragging, setDragging] = useState(false);
|
|
@@ -55,6 +55,13 @@ const RawUtilizationMetrics = ({ data, addLabelMatcher, setTimeRange, width, hei
|
|
|
55
55
|
const [pos, setPos] = useState([0, 0]);
|
|
56
56
|
const [isContextMenuOpen, setIsContextMenuOpen] = useState(false);
|
|
57
57
|
const idForContextMenu = useId();
|
|
58
|
+
const [selectedSeries, setSelectedSeries] = useURLState('selectedSeries');
|
|
59
|
+
const parsedSelectedSeries = useMemo(() => {
|
|
60
|
+
if (selectedSeries === undefined) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
return JSON.parse(decodeURIComponent(selectedSeries));
|
|
64
|
+
}, [selectedSeries]);
|
|
58
65
|
const lineStroke = '1px';
|
|
59
66
|
const lineStrokeHover = '2px';
|
|
60
67
|
const lineStrokeSelected = '3px';
|
|
@@ -202,10 +209,8 @@ const RawUtilizationMetrics = ({ data, addLabelMatcher, setTimeRange, width, hei
|
|
|
202
209
|
/* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
|
|
203
210
|
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", children: series.map((s, i) => {
|
|
204
211
|
let isSelected = false;
|
|
205
|
-
if (
|
|
206
|
-
|
|
207
|
-
selectedSeriesMatchers.length === s.metric.length) {
|
|
208
|
-
isSelected = selectedSeriesMatchers.every(m => {
|
|
212
|
+
if (parsedSelectedSeries != null && parsedSelectedSeries.length > 0) {
|
|
213
|
+
isSelected = parsedSelectedSeries.every(m => {
|
|
209
214
|
for (let i = 0; i < s.metric.length; i++) {
|
|
210
215
|
if (s.metric[i].name === m.key && s.metric[i].value === m.value) {
|
|
211
216
|
return true;
|
|
@@ -220,19 +225,17 @@ const RawUtilizationMetrics = ({ data, addLabelMatcher, setTimeRange, width, hei
|
|
|
220
225
|
? lineStrokeHover
|
|
221
226
|
: lineStroke, xScale: xScale, yScale: yScale, onClick: () => {
|
|
222
227
|
if (highlighted != null) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
.map(l => ({
|
|
226
|
-
key: l.name.replace('attributes_resource.', ''),
|
|
228
|
+
setSelectedSeries(JSON.stringify(highlighted.labels.map(l => ({
|
|
229
|
+
key: l.name,
|
|
227
230
|
value: l.value,
|
|
228
|
-
})));
|
|
231
|
+
}))));
|
|
229
232
|
}
|
|
230
233
|
} }) }, i));
|
|
231
234
|
}) })] })] }) })] }));
|
|
232
235
|
};
|
|
233
|
-
const UtilizationMetrics = ({ data, addLabelMatcher, setTimeRange, utilizationMetricsLoading,
|
|
236
|
+
const UtilizationMetrics = ({ data, addLabelMatcher, setTimeRange, utilizationMetricsLoading, }) => {
|
|
234
237
|
const { isDarkMode } = useParcaContext();
|
|
235
238
|
const { width, height, margin, heightStyle } = useMetricsGraphDimensions(false, true);
|
|
236
|
-
return (_jsx(AnimatePresence, { children: _jsx(motion.div, { className: "w-full relative", initial: { display: 'none', opacity: 0 }, animate: { display: 'block', opacity: 1 }, transition: { duration: 0.5 }, children: utilizationMetricsLoading === true ? (_jsx(MetricsGraphSkeleton, { heightStyle: heightStyle, isDarkMode: isDarkMode, isMini: true })) : (_jsx(RawUtilizationMetrics, { data: data, addLabelMatcher: addLabelMatcher, setTimeRange: setTimeRange, width: width, height: height, margin: margin
|
|
239
|
+
return (_jsx(AnimatePresence, { children: _jsx(motion.div, { className: "w-full relative", initial: { display: 'none', opacity: 0 }, animate: { display: 'block', opacity: 1 }, transition: { duration: 0.5 }, children: utilizationMetricsLoading === true ? (_jsx(MetricsGraphSkeleton, { heightStyle: heightStyle, isDarkMode: isDarkMode, isMini: true })) : (_jsx(RawUtilizationMetrics, { data: data, addLabelMatcher: addLabelMatcher, setTimeRange: setTimeRange, width: width, height: height, margin: margin })) }, "utilization-metrics-graph-loaded") }));
|
|
237
240
|
};
|
|
238
241
|
export default UtilizationMetrics;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MetricsGraphSection.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/MetricsGraphSection.tsx"],"names":[],"mappings":"
|
|
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,EAAC,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAEpC,OAAO,EAAyB,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAG5D,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,aAAa,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,KAAK,EAAE,KAAK,CAAC;IACb,qBAAqB,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,kBAAkB,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,kBAAkB,CAAC,EAAE,sBAAsB,EAAE,CAAC;IAC9C,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;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,aAAa,EACb,KAAK,EACL,qBAAqB,EACrB,kBAAkB,EAClB,yBAAyB,GAC1B,EAAE,wBAAwB,GAAG,GAAG,CAAC,OAAO,CAkIxC"}
|
|
@@ -11,7 +11,6 @@ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-run
|
|
|
11
11
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
// See the License for the specific language governing permissions and
|
|
13
13
|
// limitations under the License.
|
|
14
|
-
import { useMemo } from 'react';
|
|
15
14
|
import cx from 'classnames';
|
|
16
15
|
import { Query } from '@parca/parser';
|
|
17
16
|
import { MergedProfileSelection } from '..';
|
|
@@ -76,8 +75,7 @@ export function MetricsGraphSection({ showMetricsGraph, setDisplayHideMetricsGra
|
|
|
76
75
|
const mergeTo = query.profileType().delta ? mergeFrom + durationInMilliseconds : mergeFrom;
|
|
77
76
|
selectProfile(new MergedProfileSelection(mergeFrom, mergeTo, query));
|
|
78
77
|
};
|
|
79
|
-
const selectedMatchers = useMemo(() => Query.parse(querySelection.expression).matchers, [querySelection.expression]);
|
|
80
78
|
return (_jsxs("div", { className: cx('relative', { 'py-4': !showMetricsGraph }), children: [setDisplayHideMetricsGraphButton != null ? (_jsxs("button", { onClick: () => setDisplayHideMetricsGraphButton(!showMetricsGraph), className: cx('hidden px-3 py-1 text-sm font-medium text-gray-700 dark:text-gray-200 bg-gray-100 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:bg-gray-900', showMetricsGraph && 'absolute right-0 bottom-3 !flex', !showMetricsGraph && 'relative !flex ml-auto'), children: [showMetricsGraph ? 'Hide' : 'Show', " Metrics Graph"] })) : null, showMetricsGraph && (_jsx(_Fragment, { children: _jsx("div", { style: { height: heightStyle }, children: querySelection.expression !== '' &&
|
|
81
79
|
querySelection.from !== undefined &&
|
|
82
|
-
querySelection.to !== undefined ? (_jsx(_Fragment, { children: utilizationMetrics !== undefined ? (_jsx(UtilizationMetricsGraph, { data: utilizationMetrics, addLabelMatcher: addLabelMatcher, setTimeRange: handleTimeRangeChange, utilizationMetricsLoading: utilizationMetricsLoading
|
|
80
|
+
querySelection.to !== undefined ? (_jsx(_Fragment, { children: utilizationMetrics !== undefined ? (_jsx(UtilizationMetricsGraph, { data: utilizationMetrics, addLabelMatcher: addLabelMatcher, setTimeRange: handleTimeRangeChange, utilizationMetricsLoading: utilizationMetricsLoading })) : (_jsx(_Fragment, { children: _jsx(ProfileMetricsGraph, { queryClient: queryClient, queryExpression: querySelection.expression, from: querySelection.from, to: querySelection.to, profile: profileSelection, comparing: comparing, sumBy: querySelection.sumBy ?? sumBy ?? [], sumByLoading: defaultSumByLoading, setTimeRange: handleTimeRangeChange, addLabelMatcher: addLabelMatcher, onPointClick: handlePointClick }) })) })) : (profileSelection === null && (_jsx("div", { className: "p-2", children: _jsx(ProfileMetricsEmptyState, { message: "Please select a profile type and click 'Search' to begin." }) }))) }) }))] }));
|
|
83
81
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.481",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@headlessui/react": "^1.7.19",
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
"access": "public",
|
|
76
76
|
"registry": "https://registry.npmjs.org/"
|
|
77
77
|
},
|
|
78
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "47999057686395133ae1ae775334b4b3dd670964"
|
|
79
79
|
}
|
|
@@ -76,7 +76,12 @@ const MetricsContextMenu = ({
|
|
|
76
76
|
<Item
|
|
77
77
|
key={label.name}
|
|
78
78
|
id={label.name}
|
|
79
|
-
onClick={() =>
|
|
79
|
+
onClick={() => {
|
|
80
|
+
onAddLabelMatcher({
|
|
81
|
+
key: label.name,
|
|
82
|
+
value: label.value,
|
|
83
|
+
});
|
|
84
|
+
}}
|
|
80
85
|
className="max-w-[400px] overflow-hidden"
|
|
81
86
|
>
|
|
82
87
|
<div className="mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-300">
|
|
@@ -19,7 +19,7 @@ import {AnimatePresence, motion} from 'framer-motion';
|
|
|
19
19
|
import throttle from 'lodash.throttle';
|
|
20
20
|
import {useContextMenu} from 'react-contexify';
|
|
21
21
|
|
|
22
|
-
import {DateTimeRange, MetricsGraphSkeleton, useParcaContext} from '@parca/components';
|
|
22
|
+
import {DateTimeRange, MetricsGraphSkeleton, useParcaContext, useURLState} from '@parca/components';
|
|
23
23
|
import {Matcher} from '@parca/parser';
|
|
24
24
|
import {formatDate, formatForTimespan, getPrecision, valueFormatter} from '@parca/utilities';
|
|
25
25
|
|
|
@@ -36,7 +36,6 @@ interface CommonProps {
|
|
|
36
36
|
labels: {key: string; value: string} | Array<{key: string; value: string}>
|
|
37
37
|
) => void;
|
|
38
38
|
setTimeRange: (range: DateTimeRange) => void;
|
|
39
|
-
selectedSeriesMatchers?: Matcher[];
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
type RawUtilizationMetricsProps = CommonProps & {
|
|
@@ -91,7 +90,6 @@ const RawUtilizationMetrics = ({
|
|
|
91
90
|
width,
|
|
92
91
|
height,
|
|
93
92
|
margin,
|
|
94
|
-
selectedSeriesMatchers,
|
|
95
93
|
}: RawUtilizationMetricsProps): JSX.Element => {
|
|
96
94
|
const {timezone} = useParcaContext();
|
|
97
95
|
const graph = useRef(null);
|
|
@@ -101,6 +99,15 @@ const RawUtilizationMetrics = ({
|
|
|
101
99
|
const [pos, setPos] = useState([0, 0]);
|
|
102
100
|
const [isContextMenuOpen, setIsContextMenuOpen] = useState<boolean>(false);
|
|
103
101
|
const idForContextMenu = useId();
|
|
102
|
+
const [selectedSeries, setSelectedSeries] = useURLState<string>('selectedSeries');
|
|
103
|
+
|
|
104
|
+
const parsedSelectedSeries: Matcher[] = useMemo(() => {
|
|
105
|
+
if (selectedSeries === undefined) {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return JSON.parse(decodeURIComponent(selectedSeries));
|
|
110
|
+
}, [selectedSeries]);
|
|
104
111
|
|
|
105
112
|
const lineStroke = '1px';
|
|
106
113
|
const lineStrokeHover = '2px';
|
|
@@ -446,12 +453,8 @@ const RawUtilizationMetrics = ({
|
|
|
446
453
|
<g className="lines fill-transparent">
|
|
447
454
|
{series.map((s, i) => {
|
|
448
455
|
let isSelected = false;
|
|
449
|
-
if (
|
|
450
|
-
|
|
451
|
-
selectedSeriesMatchers.length > 0 &&
|
|
452
|
-
selectedSeriesMatchers.length === s.metric.length
|
|
453
|
-
) {
|
|
454
|
-
isSelected = selectedSeriesMatchers.every(m => {
|
|
456
|
+
if (parsedSelectedSeries != null && parsedSelectedSeries.length > 0) {
|
|
457
|
+
isSelected = parsedSelectedSeries.every(m => {
|
|
455
458
|
for (let i = 0; i < s.metric.length; i++) {
|
|
456
459
|
if (s.metric[i].name === m.key && s.metric[i].value === m.value) {
|
|
457
460
|
return true;
|
|
@@ -478,13 +481,13 @@ const RawUtilizationMetrics = ({
|
|
|
478
481
|
yScale={yScale}
|
|
479
482
|
onClick={() => {
|
|
480
483
|
if (highlighted != null) {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
.
|
|
484
|
-
|
|
485
|
-
key: l.name.replace('attributes_resource.', ''),
|
|
484
|
+
setSelectedSeries(
|
|
485
|
+
JSON.stringify(
|
|
486
|
+
highlighted.labels.map(l => ({
|
|
487
|
+
key: l.name,
|
|
486
488
|
value: l.value,
|
|
487
489
|
}))
|
|
490
|
+
)
|
|
488
491
|
);
|
|
489
492
|
}
|
|
490
493
|
}}
|
|
@@ -505,7 +508,6 @@ const UtilizationMetrics = ({
|
|
|
505
508
|
addLabelMatcher,
|
|
506
509
|
setTimeRange,
|
|
507
510
|
utilizationMetricsLoading,
|
|
508
|
-
selectedSeriesMatchers,
|
|
509
511
|
}: Props): JSX.Element => {
|
|
510
512
|
const {isDarkMode} = useParcaContext();
|
|
511
513
|
const {width, height, margin, heightStyle} = useMetricsGraphDimensions(false, true);
|
|
@@ -529,7 +531,6 @@ const UtilizationMetrics = ({
|
|
|
529
531
|
width={width}
|
|
530
532
|
height={height}
|
|
531
533
|
margin={margin}
|
|
532
|
-
selectedSeriesMatchers={selectedSeriesMatchers}
|
|
533
534
|
/>
|
|
534
535
|
)}
|
|
535
536
|
</motion.div>
|
|
@@ -11,8 +11,6 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import {useMemo} from 'react';
|
|
15
|
-
|
|
16
14
|
import cx from 'classnames';
|
|
17
15
|
|
|
18
16
|
import {Label, QueryServiceClient} from '@parca/client';
|
|
@@ -135,11 +133,6 @@ export function MetricsGraphSection({
|
|
|
135
133
|
selectProfile(new MergedProfileSelection(mergeFrom, mergeTo, query));
|
|
136
134
|
};
|
|
137
135
|
|
|
138
|
-
const selectedMatchers = useMemo(
|
|
139
|
-
() => Query.parse(querySelection.expression).matchers,
|
|
140
|
-
[querySelection.expression]
|
|
141
|
-
);
|
|
142
|
-
|
|
143
136
|
return (
|
|
144
137
|
<div className={cx('relative', {'py-4': !showMetricsGraph})}>
|
|
145
138
|
{setDisplayHideMetricsGraphButton != null ? (
|
|
@@ -167,7 +160,6 @@ export function MetricsGraphSection({
|
|
|
167
160
|
addLabelMatcher={addLabelMatcher}
|
|
168
161
|
setTimeRange={handleTimeRangeChange}
|
|
169
162
|
utilizationMetricsLoading={utilizationMetricsLoading}
|
|
170
|
-
selectedSeriesMatchers={selectedMatchers}
|
|
171
163
|
/>
|
|
172
164
|
) : (
|
|
173
165
|
<>
|