@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 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,OA8ChC,CAAC;AAEF,eAAe,kBAAkB,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: () => onAddLabelMatcher({ key: label.name, value: label.value }), 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))) }) })] }));
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, selectedSeriesMatchers, }: Props) => JSX.Element;
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,EAAwC,MAAM,mBAAmB,CAAC;AACvF,OAAO,EAAC,OAAO,EAAC,MAAM,eAAe,CAAC;AAItC,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;IAC7C,sBAAsB,CAAC,EAAE,OAAO,EAAE,CAAC;CACpC;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;AAgcF,QAAA,MAAM,kBAAkB,gGAMrB,KAAK,KAAG,GAAG,CAAC,OA6Bd,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
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, selectedSeriesMatchers, }) => {
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 (selectedSeriesMatchers != null &&
206
- selectedSeriesMatchers.length > 0 &&
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
- addLabelMatcher(highlighted.labels
224
- .filter(l => l.name.startsWith('attributes_resource.'))
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, selectedSeriesMatchers, }) => {
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, selectedSeriesMatchers: selectedSeriesMatchers })) }, "utilization-metrics-graph-loaded") }));
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":"AAiBA,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,CAwIxC"}
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, selectedSeriesMatchers: selectedMatchers })) : (_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." }) }))) }) }))] }));
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.479",
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": "11658aa6fcf7455df7adb7d45ca68e8235566d5d"
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={() => onAddLabelMatcher({key: label.name, value: label.value})}
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
- selectedSeriesMatchers != null &&
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
- addLabelMatcher(
482
- highlighted.labels
483
- .filter(l => l.name.startsWith('attributes_resource.'))
484
- .map(l => ({
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
  <>