@parca/profile 0.16.480 → 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,12 @@
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
+
6
12
  ## [0.16.480](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.479...@parca/profile@0.16.480) (2025-02-25)
7
13
 
8
14
  ## 0.23.1 (2025-02-24)
@@ -32,7 +32,7 @@ const MetricsContextMenu = ({ menuId, onAddLabelMatcher, highlighted, trackVisib
32
32
  };
33
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
34
  onAddLabelMatcher({
35
- key: transformUtilizationLabels(label.name, utilizationMetrics),
35
+ key: label.name,
36
36
  value: label.value,
37
37
  });
38
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))) }) })] }));
@@ -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;AAicF,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,13 +209,10 @@ 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 && selectedSeriesMatchers.length > 0) {
206
- isSelected = selectedSeriesMatchers.every(m => {
212
+ if (parsedSelectedSeries != null && parsedSelectedSeries.length > 0) {
213
+ isSelected = parsedSelectedSeries.every(m => {
207
214
  for (let i = 0; i < s.metric.length; i++) {
208
- if (s.metric[i].name
209
- .replace('attributes_resource.', '')
210
- .replace('attributes.', '') === m.key &&
211
- s.metric[i].value === m.value) {
215
+ if (s.metric[i].name === m.key && s.metric[i].value === m.value) {
212
216
  return true;
213
217
  }
214
218
  }
@@ -221,19 +225,17 @@ const RawUtilizationMetrics = ({ data, addLabelMatcher, setTimeRange, width, hei
221
225
  ? lineStrokeHover
222
226
  : lineStroke, xScale: xScale, yScale: yScale, onClick: () => {
223
227
  if (highlighted != null) {
224
- addLabelMatcher(highlighted.labels
225
- .filter(l => l.name.startsWith('attributes_resource.'))
226
- .map(l => ({
227
- key: l.name.replace('attributes_resource.', ''),
228
+ setSelectedSeries(JSON.stringify(highlighted.labels.map(l => ({
229
+ key: l.name,
228
230
  value: l.value,
229
- })));
231
+ }))));
230
232
  }
231
233
  } }) }, i));
232
234
  }) })] })] }) })] }));
233
235
  };
234
- const UtilizationMetrics = ({ data, addLabelMatcher, setTimeRange, utilizationMetricsLoading, selectedSeriesMatchers, }) => {
236
+ const UtilizationMetrics = ({ data, addLabelMatcher, setTimeRange, utilizationMetricsLoading, }) => {
235
237
  const { isDarkMode } = useParcaContext();
236
238
  const { width, height, margin, heightStyle } = useMetricsGraphDimensions(false, true);
237
- 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") }));
238
240
  };
239
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.480",
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": "3866c635c33d8d37e52e41fbaf62e81da153c88e"
78
+ "gitHead": "47999057686395133ae1ae775334b4b3dd670964"
79
79
  }
@@ -78,7 +78,7 @@ const MetricsContextMenu = ({
78
78
  id={label.name}
79
79
  onClick={() => {
80
80
  onAddLabelMatcher({
81
- key: transformUtilizationLabels(label.name, utilizationMetrics),
81
+ key: label.name,
82
82
  value: label.value,
83
83
  });
84
84
  }}
@@ -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,15 +453,10 @@ const RawUtilizationMetrics = ({
446
453
  <g className="lines fill-transparent">
447
454
  {series.map((s, i) => {
448
455
  let isSelected = false;
449
- if (selectedSeriesMatchers != null && selectedSeriesMatchers.length > 0) {
450
- isSelected = selectedSeriesMatchers.every(m => {
456
+ if (parsedSelectedSeries != null && parsedSelectedSeries.length > 0) {
457
+ isSelected = parsedSelectedSeries.every(m => {
451
458
  for (let i = 0; i < s.metric.length; i++) {
452
- if (
453
- s.metric[i].name
454
- .replace('attributes_resource.', '')
455
- .replace('attributes.', '') === m.key &&
456
- s.metric[i].value === m.value
457
- ) {
459
+ if (s.metric[i].name === m.key && s.metric[i].value === m.value) {
458
460
  return true;
459
461
  }
460
462
  }
@@ -479,13 +481,13 @@ const RawUtilizationMetrics = ({
479
481
  yScale={yScale}
480
482
  onClick={() => {
481
483
  if (highlighted != null) {
482
- addLabelMatcher(
483
- highlighted.labels
484
- .filter(l => l.name.startsWith('attributes_resource.'))
485
- .map(l => ({
486
- key: l.name.replace('attributes_resource.', ''),
484
+ setSelectedSeries(
485
+ JSON.stringify(
486
+ highlighted.labels.map(l => ({
487
+ key: l.name,
487
488
  value: l.value,
488
489
  }))
490
+ )
489
491
  );
490
492
  }
491
493
  }}
@@ -506,7 +508,6 @@ const UtilizationMetrics = ({
506
508
  addLabelMatcher,
507
509
  setTimeRange,
508
510
  utilizationMetricsLoading,
509
- selectedSeriesMatchers,
510
511
  }: Props): JSX.Element => {
511
512
  const {isDarkMode} = useParcaContext();
512
513
  const {width, height, margin, heightStyle} = useMetricsGraphDimensions(false, true);
@@ -530,7 +531,6 @@ const UtilizationMetrics = ({
530
531
  width={width}
531
532
  height={height}
532
533
  margin={margin}
533
- selectedSeriesMatchers={selectedSeriesMatchers}
534
534
  />
535
535
  )}
536
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
  <>