@parca/profile 0.16.111 → 0.16.113

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [0.16.113](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.112...@parca/profile@0.16.113) (2023-02-13)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
10
+ ## [0.16.112](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.111...@parca/profile@0.16.112) (2023-02-09)
11
+
12
+ **Note:** Version bump only for package @parca/profile
13
+
6
14
  ## [0.16.111](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.109...@parca/profile@0.16.111) (2023-02-09)
7
15
 
8
16
  **Note:** Version bump only for package @parca/profile
@@ -9,13 +9,26 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
- import { jsx as _jsx } from "react/jsx-runtime";
12
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
13
+ // Copyright 2022 The Parca Authors
14
+ // Licensed under the Apache License, Version 2.0 (the "License");
15
+ // you may not use this file except in compliance with the License.
16
+ // You may obtain a copy of the License at
17
+ //
18
+ // http://www.apache.org/licenses/LICENSE-2.0
19
+ //
20
+ // Unless required by applicable law or agreed to in writing, software
21
+ // distributed under the License is distributed on an "AS IS" BASIS,
22
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
+ // See the License for the specific language governing permissions and
24
+ // limitations under the License.
25
+ import { useProfileTypes } from '../ProfileSelector';
13
26
  import { ProfileSelectionFromParams, SuffixParams } from '..';
14
27
  import ProfileExplorerSingle from './ProfileExplorerSingle';
15
28
  import ProfileExplorerCompare from './ProfileExplorerCompare';
16
29
  import { store } from '@parca/store';
17
30
  import { Provider } from 'react-redux';
18
- import { DateTimeRange } from '@parca/components';
31
+ import { DateTimeRange, useParcaContext } from '@parca/components';
19
32
  var getExpressionAsAString = function (expression) {
20
33
  var x = Array.isArray(expression) ? expression.join() : expression;
21
34
  return x;
@@ -49,6 +62,8 @@ var swapQueryParameters = function (o) {
49
62
  var ProfileExplorerApp = function (_a) {
50
63
  var _b, _c;
51
64
  var queryClient = _a.queryClient, queryParams = _a.queryParams, navigateTo = _a.navigateTo;
65
+ var _d = useProfileTypes(queryClient), profileTypesLoading = _d.loading, profileTypesData = _d.data, error = _d.error;
66
+ var _e = useParcaContext(), loader = _e.loader, noDataPrompt = _e.noDataPrompt;
52
67
  /* eslint-disable @typescript-eslint/naming-convention */
53
68
  var from_a = queryParams.from_a, to_a = queryParams.to_a, merge_a = queryParams.merge_a, profile_name_a = queryParams.profile_name_a, labels_a = queryParams.labels_a, time_a = queryParams.time_a, time_selection_a = queryParams.time_selection_a, compare_a = queryParams.compare_a, from_b = queryParams.from_b, to_b = queryParams.to_b, merge_b = queryParams.merge_b, profile_name_b = queryParams.profile_name_b, labels_b = queryParams.labels_b, time_b = queryParams.time_b, time_selection_b = queryParams.time_selection_b, compare_b = queryParams.compare_b, filter_by_function = queryParams.filter_by_function, dashboard_items = queryParams.dashboard_items;
54
69
  /* eslint-enable @typescript-eslint/naming-convention */
@@ -75,6 +90,12 @@ var ProfileExplorerApp = function (_a) {
75
90
  var selectProfileB = function (p) {
76
91
  return selectProfile(p, '_b');
77
92
  };
93
+ if (profileTypesLoading) {
94
+ return _jsx(_Fragment, { children: loader });
95
+ }
96
+ if ((profileTypesData === null || profileTypesData === void 0 ? void 0 : profileTypesData.types.length) === 0) {
97
+ return _jsx(_Fragment, { children: noDataPrompt });
98
+ }
78
99
  // Show the SingleProfileExplorer when not comparing
79
100
  if (compare_a !== 'true' && compare_b !== 'true') {
80
101
  var query_1 = {
@@ -26,15 +26,21 @@ import React, { useMemo } from 'react';
26
26
  import cx from 'classnames';
27
27
  import { scaleLinear } from 'd3-scale';
28
28
  import { isSearchMatch } from '@parca/functions';
29
+ import { useAppSelector, selectBinaries } from '@parca/store';
29
30
  import { nodeLabel } from './utils';
30
31
  import useNodeColor from './useNodeColor';
31
32
  import { useKeyDown } from '@parca/components';
32
33
  export var RowHeight = 26;
33
34
  export var IcicleGraphNodes = React.memo(function IcicleGraphNodes(_a) {
34
35
  var data = _a.data, strings = _a.strings, mappings = _a.mappings, locations = _a.locations, functions = _a.functions, x = _a.x, y = _a.y, xScale = _a.xScale, total = _a.total, totalWidth = _a.totalWidth, level = _a.level, setHoveringNode = _a.setHoveringNode, path = _a.path, setCurPath = _a.setCurPath, curPath = _a.curPath, searchString = _a.searchString, compareMode = _a.compareMode;
36
+ var binaries = useAppSelector(selectBinaries);
35
37
  var nodes = curPath.length === 0
36
38
  ? data
37
- : data.filter(function (d) { return d != null && curPath[0] === nodeLabel(d, strings, mappings, locations, functions); });
39
+ : data.filter(function (d) {
40
+ return d != null &&
41
+ curPath[0] ===
42
+ nodeLabel(d, strings, mappings, locations, functions, binaries.length > 1);
43
+ });
38
44
  return (_jsx("g", __assign({ transform: "translate(".concat(x, ", ").concat(y, ")") }, { children: nodes.map(function (d, i) {
39
45
  var start = nodes.slice(0, i).reduce(function (sum, d) { return sum + parseFloat(d.cumulative); }, 0);
40
46
  var xStart = xScale(start);
@@ -52,11 +58,14 @@ var fadedIcicleRectStyles = {
52
58
  };
53
59
  export var IcicleNode = React.memo(function IcicleNode(_a) {
54
60
  var x = _a.x, y = _a.y, height = _a.height, setCurPath = _a.setCurPath, setHoveringNode = _a.setHoveringNode, curPath = _a.curPath, level = _a.level, path = _a.path, data = _a.data, strings = _a.strings, mappings = _a.mappings, locations = _a.locations, functions = _a.functions, total = _a.total, totalWidth = _a.totalWidth, xScale = _a.xScale, _b = _a.isRoot, isRoot = _b === void 0 ? false : _b, searchString = _a.searchString, compareMode = _a.compareMode;
61
+ var binaries = useAppSelector(selectBinaries);
55
62
  var isShiftDown = useKeyDown().isShiftDown;
56
63
  var colorResult = useNodeColor({ data: data, compareMode: compareMode });
57
64
  var name = useMemo(function () {
58
- return isRoot ? 'root' : nodeLabel(data, strings, mappings, locations, functions);
59
- }, [data, strings, mappings, locations, functions, isRoot]);
65
+ return isRoot
66
+ ? 'root'
67
+ : nodeLabel(data, strings, mappings, locations, functions, binaries.length > 1);
68
+ }, [data, strings, mappings, locations, functions, isRoot, binaries]);
60
69
  var nextPath = path.concat([name]);
61
70
  var isFaded = curPath.length > 0 && name !== curPath[curPath.length - 1];
62
71
  var styles = isFaded ? fadedIcicleRectStyles : icicleRectStyles;
@@ -34,8 +34,9 @@ var colorNodes = function (nodes, strings, mappings, locations, functions, featu
34
34
  if (node.children != null) {
35
35
  coloredNode.children = colorNodes(node.children, strings, mappings, locations, functions, features);
36
36
  }
37
- coloredNode.feature = extractFeature(node, mappings, locations, strings, functions);
38
- features[coloredNode.feature] = true;
37
+ var feature = extractFeature(node, mappings, locations, strings, functions);
38
+ coloredNode.feature = feature.name;
39
+ features[feature.name] = feature.type;
39
40
  return coloredNode;
40
41
  });
41
42
  };
@@ -46,11 +47,11 @@ var useColoredGraph = function (graph) {
46
47
  var _a = useMemo(function () {
47
48
  var _a;
48
49
  if (graph.root == null) {
49
- return [graph, []];
50
+ return [graph, {}];
50
51
  }
51
52
  var features = {};
52
53
  var coloredGraph = __assign(__assign({}, graph), { root: __assign(__assign({}, graph.root), { children: colorNodes((_a = graph.root.children) !== null && _a !== void 0 ? _a : [], graph.stringTable, graph.mapping, graph.locations, graph.function, features) }) });
53
- return [coloredGraph, Object.keys(features)];
54
+ return [coloredGraph, features];
54
55
  }, [graph]), coloredGraph = _a[0], features = _a[1];
55
56
  useEffect(function () {
56
57
  dispatch(setFeatures({ features: features, colorProfileName: colorProfile, isDarkMode: isDarkMode }));
@@ -1,5 +1,6 @@
1
1
  import { FlamegraphNode } from '@parca/client';
2
2
  import { Mapping, Function as ParcaFunction, Location } from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
3
+ import type { Feature } from '@parca/store';
3
4
  export declare const getBinaryName: (node: FlamegraphNode, mappings: Mapping[], locations: Location[], strings: string[]) => string | undefined;
4
- export declare function nodeLabel(node: FlamegraphNode, strings: string[], mappings: Mapping[], locations: Location[], functions: ParcaFunction[]): string;
5
- export declare const extractFeature: (data: FlamegraphNode, mappings: Mapping[], locations: Location[], strings: string[], functions: ParcaFunction[]) => string;
5
+ export declare function nodeLabel(node: FlamegraphNode, strings: string[], mappings: Mapping[], locations: Location[], functions: ParcaFunction[], showBinaryName: boolean): string;
6
+ export declare const extractFeature: (data: FlamegraphNode, mappings: Mapping[], locations: Location[], strings: string[], functions: ParcaFunction[]) => Feature;
@@ -12,7 +12,7 @@
12
12
  // limitations under the License.
13
13
  import { getLastItem } from '@parca/functions';
14
14
  import { hexifyAddress } from '../../utils';
15
- import { EVERYTHING_ELSE } from '@parca/store';
15
+ import { EVERYTHING_ELSE, FEATURE_TYPES } from '@parca/store';
16
16
  export var getBinaryName = function (node, mappings, locations, strings) {
17
17
  var _a, _b;
18
18
  if (((_a = node.meta) === null || _a === void 0 ? void 0 : _a.locationIndex) === undefined || ((_b = node.meta) === null || _b === void 0 ? void 0 : _b.locationIndex) === 0) {
@@ -29,31 +29,35 @@ export var getBinaryName = function (node, mappings, locations, strings) {
29
29
  var mappingFile = strings[mapping.fileStringIndex];
30
30
  return getLastItem(mappingFile);
31
31
  };
32
- export function nodeLabel(node, strings, mappings, locations, functions) {
32
+ export function nodeLabel(node, strings, mappings, locations, functions, showBinaryName) {
33
33
  var _a, _b;
34
34
  if (((_a = node.meta) === null || _a === void 0 ? void 0 : _a.locationIndex) === undefined)
35
35
  return '<unknown>';
36
36
  if (((_b = node.meta) === null || _b === void 0 ? void 0 : _b.locationIndex) === 0)
37
37
  return '<unknown>';
38
38
  var location = locations[node.meta.locationIndex - 1];
39
- var binary = getBinaryName(node, mappings, locations, strings);
40
- var mappingString = binary != null ? "[".concat(binary, "]") : '';
39
+ var mappingString = '';
40
+ if (showBinaryName) {
41
+ var binary = getBinaryName(node, mappings, locations, strings);
42
+ if (binary != null)
43
+ mappingString = "[".concat(binary, "]");
44
+ }
41
45
  if (location.lines.length > 0) {
42
46
  var funcName = strings[functions[location.lines[node.meta.lineIndex].functionIndex - 1].nameStringIndex];
43
- return "".concat(mappingString, " ").concat(funcName);
47
+ return "".concat(mappingString.length > 0 ? "".concat(mappingString, " ") : '').concat(funcName);
44
48
  }
45
49
  var address = hexifyAddress(location.address);
46
50
  var fallback = "".concat(mappingString).concat(address);
47
51
  return fallback === '' ? '<unknown>' : fallback;
48
52
  }
49
53
  export var extractFeature = function (data, mappings, locations, strings, functions) {
50
- var name = nodeLabel(data, strings, mappings, locations, functions).trim();
54
+ var name = nodeLabel(data, strings, mappings, locations, functions, false).trim();
51
55
  if (name.startsWith('runtime') || name === 'root') {
52
- return 'runtime';
56
+ return { name: 'runtime', type: FEATURE_TYPES.Runtime };
53
57
  }
54
58
  var binaryName = getBinaryName(data, mappings, locations, strings);
55
59
  if (binaryName != null) {
56
- return binaryName;
60
+ return { name: binaryName, type: FEATURE_TYPES.Binary };
57
61
  }
58
- return EVERYTHING_ELSE;
62
+ return { name: EVERYTHING_ELSE, type: FEATURE_TYPES.Misc };
59
63
  };
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.111",
3
+ "version": "0.16.113",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@parca/client": "^0.16.62",
7
- "@parca/components": "^0.16.93",
7
+ "@parca/components": "^0.16.95",
8
8
  "@parca/dynamicsize": "^0.16.52",
9
9
  "@parca/functions": "^0.16.60",
10
10
  "@parca/parser": "^0.16.53",
11
- "@parca/store": "^0.16.55",
11
+ "@parca/store": "^0.16.56",
12
12
  "@types/react-beautiful-dnd": "^13.1.3",
13
13
  "d3": "7.8.2",
14
14
  "d3-scale": "^4.0.2",
@@ -45,5 +45,5 @@
45
45
  "access": "public",
46
46
  "registry": "https://registry.npmjs.org/"
47
47
  },
48
- "gitHead": "5a51bfaf98ebb147ff2cfd3a90457ec4f05a9c8c"
48
+ "gitHead": "425c828b992528c8588ad6992fcda1d9f160f170"
49
49
  }
@@ -11,14 +11,14 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
 
14
- import {QuerySelection} from '../ProfileSelector';
14
+ import {QuerySelection, useProfileTypes} from '../ProfileSelector';
15
15
  import {ProfileSelection, ProfileSelectionFromParams, SuffixParams} from '..';
16
16
  import ProfileExplorerSingle from './ProfileExplorerSingle';
17
17
  import ProfileExplorerCompare from './ProfileExplorerCompare';
18
18
  import {QueryServiceClient} from '@parca/client';
19
19
  import {store} from '@parca/store';
20
20
  import {Provider} from 'react-redux';
21
- import {DateTimeRange} from '@parca/components';
21
+ import {DateTimeRange, useParcaContext} from '@parca/components';
22
22
  import type {NavigateFunction} from '@parca/functions';
23
23
 
24
24
  interface ProfileExplorerProps {
@@ -71,6 +71,14 @@ const ProfileExplorerApp = ({
71
71
  queryParams,
72
72
  navigateTo,
73
73
  }: ProfileExplorerProps): JSX.Element => {
74
+ const {
75
+ loading: profileTypesLoading,
76
+ data: profileTypesData,
77
+ error,
78
+ } = useProfileTypes(queryClient);
79
+
80
+ const {loader, noDataPrompt} = useParcaContext();
81
+
74
82
  /* eslint-disable @typescript-eslint/naming-convention */
75
83
  let {
76
84
  from_a,
@@ -126,6 +134,14 @@ const ProfileExplorerApp = ({
126
134
  return selectProfile(p, '_b');
127
135
  };
128
136
 
137
+ if (profileTypesLoading) {
138
+ return <>{loader}</>;
139
+ }
140
+
141
+ if (profileTypesData?.types.length === 0) {
142
+ return <>{noDataPrompt}</>;
143
+ }
144
+
129
145
  // Show the SingleProfileExplorer when not comparing
130
146
  if (compare_a !== 'true' && compare_b !== 'true') {
131
147
  const query = {
@@ -22,7 +22,7 @@ import {
22
22
  } from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
23
23
  import {isSearchMatch} from '@parca/functions';
24
24
  import {FlamegraphNode, FlamegraphRootNode} from '@parca/client';
25
-
25
+ import {useAppSelector, selectBinaries} from '@parca/store';
26
26
  import {nodeLabel} from './utils';
27
27
  import useNodeColor from './useNodeColor';
28
28
  import {useKeyDown} from '@parca/components';
@@ -68,11 +68,15 @@ export const IcicleGraphNodes = React.memo(function IcicleGraphNodes({
68
68
  searchString,
69
69
  compareMode,
70
70
  }: IcicleGraphNodesProps): JSX.Element {
71
+ const binaries = useAppSelector(selectBinaries);
71
72
  const nodes =
72
73
  curPath.length === 0
73
74
  ? data
74
75
  : data.filter(
75
- d => d != null && curPath[0] === nodeLabel(d, strings, mappings, locations, functions)
76
+ d =>
77
+ d != null &&
78
+ curPath[0] ===
79
+ nodeLabel(d, strings, mappings, locations, functions, binaries.length > 1)
76
80
  );
77
81
 
78
82
  return (
@@ -162,11 +166,14 @@ export const IcicleNode = React.memo(function IcicleNode({
162
166
  searchString,
163
167
  compareMode,
164
168
  }: IcicleNodeProps): JSX.Element {
169
+ const binaries = useAppSelector(selectBinaries);
165
170
  const {isShiftDown} = useKeyDown();
166
171
  const colorResult = useNodeColor({data, compareMode});
167
172
  const name = useMemo(() => {
168
- return isRoot ? 'root' : nodeLabel(data, strings, mappings, locations, functions);
169
- }, [data, strings, mappings, locations, functions, isRoot]);
173
+ return isRoot
174
+ ? 'root'
175
+ : nodeLabel(data, strings, mappings, locations, functions, binaries.length > 1);
176
+ }, [data, strings, mappings, locations, functions, isRoot, binaries]);
170
177
  const nextPath = path.concat([name]);
171
178
  const isFaded = curPath.length > 0 && name !== curPath[curPath.length - 1];
172
179
  const styles = isFaded ? fadedIcicleRectStyles : icicleRectStyles;
@@ -20,6 +20,7 @@ import {
20
20
  import type {ColorProfileName} from '@parca/functions';
21
21
  import useUserPreference, {USER_PREFERENCES} from '@parca/functions/useUserPreference';
22
22
  import {setFeatures, useAppDispatch, useAppSelector, selectDarkMode} from '@parca/store';
23
+ import type {FeatureType, FeaturesMap} from '@parca/store';
23
24
  import {useEffect, useMemo} from 'react';
24
25
  import {extractFeature} from './utils';
25
26
 
@@ -43,7 +44,7 @@ const colorNodes = (
43
44
  mappings: Mapping[],
44
45
  locations: Location[],
45
46
  functions: ParcaFunction[],
46
- features: {[key: string]: boolean}
47
+ features: {[key: string]: FeatureType}
47
48
  ): ColoredFlamegraphNode[] => {
48
49
  if (nodes === undefined) {
49
50
  return [];
@@ -62,8 +63,9 @@ const colorNodes = (
62
63
  features
63
64
  );
64
65
  }
65
- coloredNode.feature = extractFeature(node, mappings, locations, strings, functions);
66
- features[coloredNode.feature] = true;
66
+ const feature = extractFeature(node, mappings, locations, strings, functions);
67
+ coloredNode.feature = feature.name;
68
+ features[feature.name] = feature.type;
67
69
  return coloredNode;
68
70
  });
69
71
  };
@@ -75,11 +77,11 @@ const useColoredGraph = (graph: Flamegraph): ColoredFlamegraph => {
75
77
  );
76
78
  const isDarkMode = useAppSelector(selectDarkMode);
77
79
 
78
- const [coloredGraph, features]: [ColoredFlamegraph, string[]] = useMemo(() => {
80
+ const [coloredGraph, features]: [ColoredFlamegraph, FeaturesMap] = useMemo(() => {
79
81
  if (graph.root == null) {
80
- return [graph as ColoredFlamegraph, []];
82
+ return [graph as ColoredFlamegraph, {}];
81
83
  }
82
- const features: {[key: string]: boolean} = {};
84
+ const features: FeaturesMap = {};
83
85
  const coloredGraph = {
84
86
  ...graph,
85
87
  root: {
@@ -94,7 +96,7 @@ const useColoredGraph = (graph: Flamegraph): ColoredFlamegraph => {
94
96
  ),
95
97
  },
96
98
  };
97
- return [coloredGraph, Object.keys(features)];
99
+ return [coloredGraph, features];
98
100
  }, [graph]);
99
101
 
100
102
  useEffect(() => {
@@ -19,7 +19,8 @@ import {
19
19
  Location,
20
20
  } from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
21
21
  import {hexifyAddress} from '../../utils';
22
- import {EVERYTHING_ELSE} from '@parca/store';
22
+ import {EVERYTHING_ELSE, FEATURE_TYPES} from '@parca/store';
23
+ import type {Feature} from '@parca/store';
23
24
 
24
25
  export const getBinaryName = (
25
26
  node: FlamegraphNode,
@@ -50,21 +51,25 @@ export function nodeLabel(
50
51
  strings: string[],
51
52
  mappings: Mapping[],
52
53
  locations: Location[],
53
- functions: ParcaFunction[]
54
+ functions: ParcaFunction[],
55
+ showBinaryName: boolean
54
56
  ): string {
55
57
  if (node.meta?.locationIndex === undefined) return '<unknown>';
56
58
  if (node.meta?.locationIndex === 0) return '<unknown>';
57
59
 
58
60
  const location = locations[node.meta.locationIndex - 1];
59
61
 
60
- const binary = getBinaryName(node, mappings, locations, strings);
62
+ let mappingString = '';
61
63
 
62
- const mappingString: string = binary != null ? `[${binary}]` : '';
64
+ if (showBinaryName) {
65
+ const binary = getBinaryName(node, mappings, locations, strings);
66
+ if (binary != null) mappingString = `[${binary}]`;
67
+ }
63
68
 
64
69
  if (location.lines.length > 0) {
65
70
  const funcName =
66
71
  strings[functions[location.lines[node.meta.lineIndex].functionIndex - 1].nameStringIndex];
67
- return `${mappingString} ${funcName}`;
72
+ return `${mappingString.length > 0 ? `${mappingString} ` : ''}${funcName}`;
68
73
  }
69
74
 
70
75
  const address = hexifyAddress(location.address);
@@ -79,16 +84,16 @@ export const extractFeature = (
79
84
  locations: Location[],
80
85
  strings: string[],
81
86
  functions: ParcaFunction[]
82
- ): string => {
83
- const name = nodeLabel(data, strings, mappings, locations, functions).trim();
87
+ ): Feature => {
88
+ const name = nodeLabel(data, strings, mappings, locations, functions, false).trim();
84
89
  if (name.startsWith('runtime') || name === 'root') {
85
- return 'runtime';
90
+ return {name: 'runtime', type: FEATURE_TYPES.Runtime};
86
91
  }
87
92
 
88
93
  const binaryName = getBinaryName(data, mappings, locations, strings);
89
94
  if (binaryName != null) {
90
- return binaryName;
95
+ return {name: binaryName, type: FEATURE_TYPES.Binary};
91
96
  }
92
97
 
93
- return EVERYTHING_ELSE;
98
+ return {name: EVERYTHING_ELSE, type: FEATURE_TYPES.Misc};
94
99
  };