@parca/profile 0.16.373 → 0.16.375

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/GraphTooltipArrow/Content.js +1 -1
  3. package/dist/GraphTooltipArrow/DockedGraphTooltip/index.js +1 -1
  4. package/dist/ProfileIcicleGraph/IcicleGraph/useColoredGraph.js +1 -1
  5. package/dist/ProfileIcicleGraph/IcicleGraph/utils.d.ts +1 -1
  6. package/dist/ProfileIcicleGraph/IcicleGraph/utils.js +1 -5
  7. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.js +23 -9
  8. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.d.ts +2 -1
  9. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.js +3 -2
  10. package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.js +0 -1
  11. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts +1 -0
  12. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.js +29 -47
  13. package/dist/ProfileIcicleGraph/IcicleGraphArrow/useNodeColor.d.ts +1 -2
  14. package/dist/ProfileIcicleGraph/IcicleGraphArrow/useNodeColor.js +2 -7
  15. package/dist/ProfileIcicleGraph/IcicleGraphArrow/utils.js +0 -3
  16. package/dist/ProfileIcicleGraph/index.d.ts +2 -1
  17. package/dist/ProfileIcicleGraph/index.js +26 -22
  18. package/dist/ProfileSource.js +2 -0
  19. package/dist/ProfileView/index.d.ts +2 -0
  20. package/dist/ProfileView/index.js +2 -2
  21. package/dist/ProfileViewWithData.js +17 -10
  22. package/dist/useQuery.d.ts +1 -3
  23. package/dist/useQuery.js +21 -8
  24. package/package.json +7 -7
  25. package/src/GraphTooltipArrow/Content.tsx +1 -5
  26. package/src/GraphTooltipArrow/DockedGraphTooltip/index.tsx +1 -1
  27. package/src/ProfileIcicleGraph/IcicleGraph/useColoredGraph.ts +1 -1
  28. package/src/ProfileIcicleGraph/IcicleGraph/utils.ts +1 -7
  29. package/src/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.tsx +26 -9
  30. package/src/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.tsx +21 -1
  31. package/src/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.tsx +0 -1
  32. package/src/ProfileIcicleGraph/IcicleGraphArrow/index.tsx +39 -48
  33. package/src/ProfileIcicleGraph/IcicleGraphArrow/useNodeColor.ts +1 -8
  34. package/src/ProfileIcicleGraph/IcicleGraphArrow/utils.ts +0 -5
  35. package/src/ProfileIcicleGraph/index.tsx +65 -50
  36. package/src/ProfileSource.tsx +2 -0
  37. package/src/ProfileView/index.tsx +4 -1
  38. package/src/ProfileViewWithData.tsx +26 -10
  39. package/src/useQuery.tsx +22 -11
  40. package/dist/ProfileIcicleGraph/ActionButtons/RuntimeFilterDropdown.d.ts +0 -9
  41. package/dist/ProfileIcicleGraph/ActionButtons/RuntimeFilterDropdown.js +0 -23
  42. package/src/ProfileIcicleGraph/ActionButtons/RuntimeFilterDropdown.tsx +0 -123
@@ -13,10 +13,8 @@ interface UseQueryOptions {
13
13
  sourceBuildID?: string;
14
14
  sourceFilename?: string;
15
15
  sourceOnly?: boolean;
16
- showRuntimeRuby?: boolean;
17
- showRuntimePython?: boolean;
18
- showInterpretedOnly?: boolean;
19
16
  invertCallStack?: boolean;
17
+ binaryFrameFilter?: string[];
20
18
  }
21
19
  export declare const useQuery: (client: QueryServiceClient, profileSource: ProfileSource, reportType: QueryRequest_ReportType, options?: UseQueryOptions) => IQueryResult;
22
20
  export {};
package/dist/useQuery.js CHANGED
@@ -25,10 +25,8 @@ export const useQuery = (client, profileSource, reportType, options) => {
25
25
  options?.sourceBuildID,
26
26
  options?.sourceOnly,
27
27
  options?.sourceOnly === true ? '' : options?.sourceFilename,
28
- options?.showRuntimeRuby ?? false,
29
- options?.showRuntimePython ?? false,
30
- options?.showInterpretedOnly ?? false,
31
28
  options?.invertCallStack ?? false,
29
+ options?.binaryFrameFilter ?? '',
32
30
  ],
33
31
  queryFn: async () => {
34
32
  const req = profileSource.QueryRequest();
@@ -44,12 +42,27 @@ export const useQuery = (client, profileSource, reportType, options) => {
44
42
  sourceOnly: options?.sourceOnly ?? false,
45
43
  };
46
44
  }
47
- req.runtimeFilter = {
48
- showRuby: options?.showRuntimeRuby ?? false,
49
- showPython: options?.showRuntimePython ?? false,
50
- showInterpretedOnly: options?.showInterpretedOnly ?? false,
51
- };
52
45
  req.invertCallStack = options?.invertCallStack ?? false;
46
+ if (options?.binaryFrameFilter !== undefined && options?.binaryFrameFilter.length > 0) {
47
+ req.filter = [
48
+ {
49
+ filter: {
50
+ oneofKind: 'frameFilter',
51
+ frameFilter: {
52
+ filter: {
53
+ oneofKind: 'binaryFrameFilter',
54
+ binaryFrameFilter: {
55
+ includeBinaries: options?.binaryFrameFilter ?? [],
56
+ },
57
+ },
58
+ },
59
+ },
60
+ },
61
+ ];
62
+ }
63
+ else {
64
+ req.filter = [];
65
+ }
53
66
  try {
54
67
  const { response } = await client.query(req, { meta: metadata });
55
68
  return response;
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.373",
3
+ "version": "0.16.375",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@headlessui/react": "^1.7.19",
7
7
  "@iconify/react": "^4.0.0",
8
- "@parca/client": "^0.16.114",
9
- "@parca/components": "^0.16.277",
8
+ "@parca/client": "^0.16.115",
9
+ "@parca/components": "^0.16.278",
10
10
  "@parca/dynamicsize": "^0.16.65",
11
- "@parca/hooks": "^0.0.56",
11
+ "@parca/hooks": "^0.0.57",
12
12
  "@parca/icons": "^0.16.69",
13
13
  "@parca/parser": "^0.16.74",
14
- "@parca/store": "^0.16.145",
15
- "@parca/utilities": "^0.0.73",
14
+ "@parca/store": "^0.16.146",
15
+ "@parca/utilities": "^0.0.74",
16
16
  "@popperjs/core": "^2.11.8",
17
17
  "@protobuf-ts/runtime-rpc": "^2.5.0",
18
18
  "@tanstack/react-query": "^4.0.5",
@@ -71,5 +71,5 @@
71
71
  "access": "public",
72
72
  "registry": "https://registry.npmjs.org/"
73
73
  },
74
- "gitHead": "80826885820b5f15cc6559c47293cad10249f85f"
74
+ "gitHead": "1c9338c7294c1df88345032cee964653ce4e349b"
75
75
  }
@@ -201,11 +201,7 @@ const TooltipMetaInfo = ({
201
201
  <tr>
202
202
  <td className="w-1/4">Build Id</td>
203
203
  <td className="w-3/4 break-all">
204
- {isMappingBuildIDAvailable ? (
205
- <div>{truncateString(getLastItem(mappingBuildID) as string, 28)}</div>
206
- ) : (
207
- <NoData />
208
- )}
204
+ {isMappingBuildIDAvailable ? <div>{truncateString(mappingBuildID, 28)}</div> : <NoData />}
209
205
  </td>
210
206
  </tr>
211
207
  {labelPairs.length > 0 && (
@@ -145,7 +145,7 @@ export const DockedGraphTooltip = ({
145
145
  title="Build ID"
146
146
  value={
147
147
  isMappingBuildIDAvailable ? (
148
- <div>{truncateString(getLastItem(mappingBuildID) as string, 28)}</div>
148
+ <div>{truncateString(mappingBuildID, 28)}</div>
149
149
  ) : (
150
150
  <NoData />
151
151
  )
@@ -71,7 +71,7 @@ const colorNodes = (
71
71
  features
72
72
  );
73
73
  }
74
- const feature = extractFeature(node, mappings, locations, strings, functions);
74
+ const feature = extractFeature(node, mappings, locations, strings);
75
75
  coloredNode.feature = feature.name;
76
76
  features[feature.name] = feature.type;
77
77
  return coloredNode;
@@ -91,14 +91,8 @@ export const extractFeature = (
91
91
  data: FlamegraphNode,
92
92
  mappings: Mapping[],
93
93
  locations: Location[],
94
- strings: string[],
95
- functions: ParcaFunction[]
94
+ strings: string[]
96
95
  ): Feature => {
97
- const name = nodeLabel(data, strings, mappings, locations, functions, false).trim();
98
- if (name.startsWith('runtime') || name === 'root') {
99
- return {name: 'runtime', type: FEATURE_TYPES.Runtime};
100
- }
101
-
102
96
  const binaryName = getBinaryName(data, mappings, locations, strings);
103
97
  if (binaryName != null) {
104
98
  return {name: binaryName, type: FEATURE_TYPES.Binary};
@@ -37,7 +37,10 @@ const ColorStackLegend = ({
37
37
  const [colorProfileName] = useUserPreference<string>(
38
38
  USER_PREFERENCES.FLAMEGRAPH_COLOR_PROFILE.key
39
39
  );
40
- const [currentSearchString, setSearchString] = useURLState({param: 'search_string', navigateTo});
40
+ const [currentSearchString, setSearchString] = useURLState({
41
+ param: 'binary_frame_filter',
42
+ navigateTo,
43
+ });
41
44
 
42
45
  const stackColorArray = useMemo(() => {
43
46
  return Object.entries(mappingColors).sort(([featureA], [featureB]) => {
@@ -67,7 +70,8 @@ const ColorStackLegend = ({
67
70
  <div className="my-4 flex w-full flex-wrap justify-start">
68
71
  {stackColorArray.map(([feature, color]) => {
69
72
  const filteringAllowed = feature !== EVERYTHING_ELSE;
70
- const isHighlighted = currentSearchString === feature;
73
+ const isHighlighted =
74
+ currentSearchString !== undefined ? currentSearchString.includes(feature) : false;
71
75
  return (
72
76
  <div
73
77
  key={feature}
@@ -79,14 +83,19 @@ const ColorStackLegend = ({
79
83
  }
80
84
  )}
81
85
  onClick={() => {
82
- if (!filteringAllowed) {
86
+ if (!filteringAllowed || isHighlighted) {
83
87
  return;
84
88
  }
85
- if (isHighlighted) {
86
- setSearchString('');
87
- return;
88
- }
89
- setSearchString(feature);
89
+
90
+ // Check if the current search string is defined and an array
91
+ const updatedSearchString = Array.isArray(currentSearchString)
92
+ ? [...currentSearchString, feature] // If array, append the feature
93
+ : // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
94
+ currentSearchString // If not array, preserve current value
95
+ ? currentSearchString.split(',') // If string, split by commas
96
+ : [feature]; // If undefined, initialize array with feature
97
+
98
+ setSearchString(updatedSearchString);
90
99
  }}
91
100
  >
92
101
  <div className="flex w-11/12 items-center justify-start">
@@ -102,7 +111,15 @@ const ColorStackLegend = ({
102
111
  <Icon
103
112
  icon="radix-icons:cross-circled"
104
113
  onClick={e => {
105
- setSearchString('');
114
+ let searchString: string[] = [];
115
+ if (typeof currentSearchString === 'string') {
116
+ searchString.push(currentSearchString);
117
+ } else {
118
+ searchString = currentSearchString;
119
+ }
120
+
121
+ // remove the current feature from the search string array of strings
122
+ setSearchString(searchString.filter((f: string) => f !== feature));
106
123
  e.stopPropagation();
107
124
  }}
108
125
  />
@@ -19,7 +19,7 @@ import {Tooltip} from 'react-tooltip';
19
19
  import {useParcaContext} from '@parca/components';
20
20
  import {USER_PREFERENCES, useUserPreference} from '@parca/hooks';
21
21
  import {ProfileType} from '@parca/parser';
22
- import {type NavigateFunction} from '@parca/utilities';
22
+ import {getLastItem, type NavigateFunction} from '@parca/utilities';
23
23
 
24
24
  import {useGraphTooltip} from '../../GraphTooltipArrow/useGraphTooltip';
25
25
  import {useGraphTooltipMetaInfo} from '../../GraphTooltipArrow/useGraphTooltipMetaInfo';
@@ -38,6 +38,7 @@ interface ContextMenuProps {
38
38
  curPath: string[];
39
39
  setCurPath: (path: string[]) => void;
40
40
  hideMenu: () => void;
41
+ hideBinary: (binaryToRemove: string) => void;
41
42
  }
42
43
 
43
44
  const ContextMenu = ({
@@ -53,6 +54,7 @@ const ContextMenu = ({
53
54
  setCurPath,
54
55
  hideMenu,
55
56
  profileType,
57
+ hideBinary,
56
58
  }: ContextMenuProps): JSX.Element => {
57
59
  const {isDarkMode} = useParcaContext();
58
60
  const {enableSourcesView} = useParcaContext();
@@ -157,6 +159,24 @@ const ContextMenu = ({
157
159
  <div>Reset view</div>
158
160
  </div>
159
161
  </Item>
162
+ <Item
163
+ id="hide-binary"
164
+ onClick={() => hideBinary(getLastItem(mappingFile) as string)}
165
+ disabled={mappingFile === null || mappingFile === ''}
166
+ >
167
+ <div
168
+ data-tooltip-id="hide-binary-help"
169
+ data-tooltip-content="Hide all frames for this binary"
170
+ >
171
+ <div className="flex w-full items-center gap-2">
172
+ <Icon icon="bx:bxs-hide" />
173
+ <div>
174
+ Hide Binary {mappingFile !== null && `(${getLastItem(mappingFile) as string})`}
175
+ </div>
176
+ </div>
177
+ </div>
178
+ <Tooltip place="left" id="hide-binary-help" />
179
+ </Item>
160
180
  <Submenu
161
181
  label={
162
182
  <div className="flex w-full items-center gap-2">
@@ -362,7 +362,6 @@ export const IcicleNode = React.memo(function IcicleNodeNoMemo({
362
362
  diffPerSecond,
363
363
  mappingColors,
364
364
  mappingFile,
365
- functionName,
366
365
  });
367
366
  const name = useMemo(() => {
368
367
  return isRoot ? 'root' : nodeLabel(table, row, level, binaries.length > 1);
@@ -13,10 +13,11 @@
13
13
 
14
14
  import React, {memo, useCallback, useEffect, useMemo, useRef, useState} from 'react';
15
15
 
16
- import {Dictionary, Table, Vector, tableFromIPC} from 'apache-arrow';
16
+ import {Table, tableFromIPC} from 'apache-arrow';
17
17
  import {useContextMenu} from 'react-contexify';
18
18
 
19
19
  import {FlamegraphArrow} from '@parca/client';
20
+ import {useURLState} from '@parca/components';
20
21
  import {USER_PREFERENCES, useCurrentColorProfile, useUserPreference} from '@parca/hooks';
21
22
  import {ProfileType} from '@parca/parser';
22
23
  import {
@@ -35,7 +36,7 @@ import {useProfileViewContext} from '../../ProfileView/ProfileViewContext';
35
36
  import ColorStackLegend from './ColorStackLegend';
36
37
  import ContextMenu from './ContextMenu';
37
38
  import {IcicleNode, RowHeight, mappingColors} from './IcicleGraphNodes';
38
- import {arrowToString, extractFeature} from './utils';
39
+ import {extractFeature} from './utils';
39
40
 
40
41
  export const FIELD_LABELS_ONLY = 'labels_only';
41
42
  export const FIELD_MAPPING_FILE = 'mapping_file';
@@ -64,6 +65,7 @@ interface IcicleGraphArrowProps {
64
65
  setCurPath: (path: string[]) => void;
65
66
  navigateTo?: NavigateFunction;
66
67
  sortBy: string;
68
+ mappings?: string[];
67
69
  }
68
70
 
69
71
  export const IcicleGraphArrow = memo(function IcicleGraphArrow({
@@ -76,6 +78,7 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
76
78
  profileType,
77
79
  navigateTo,
78
80
  sortBy,
81
+ mappings,
79
82
  }: IcicleGraphArrowProps): React.JSX.Element {
80
83
  const [isContextMenuOpen, setIsContextMenuOpen] = useState<boolean>(false);
81
84
  const dispatch = useAppDispatch();
@@ -96,68 +99,39 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
96
99
  const svg = useRef(null);
97
100
  const ref = useRef<SVGGElement>(null);
98
101
 
102
+ const [binaryFrameFilter, setBinaryFrameFilter] = useURLState({
103
+ param: 'binary_frame_filter',
104
+ navigateTo,
105
+ });
106
+
99
107
  const currentSearchString = (selectQueryParam('search_string') as string) ?? '';
100
108
  const {compareMode} = useProfileViewContext();
101
109
  const isColorStackLegendEnabled = selectQueryParam('color_stack_legend') === 'true';
102
110
  const currentColorProfile = useCurrentColorProfile();
103
111
  const colorForSimilarNodes = currentColorProfile.colorForSimilarNodes;
104
112
 
105
- const mappings = useMemo(() => {
106
- // Read the mappings from the dictionary that contains all mapping strings.
107
- // This is great, as might only have a dozen or so mappings,
108
- // and don't need to read through all the rows (potentially thousands).
109
- const mappingsDict: Vector<Dictionary> | null = table.getChild(FIELD_MAPPING_FILE);
110
- const mappings =
111
- mappingsDict?.data
112
- .map(mapping => {
113
- if (mapping.dictionary == null) {
114
- return [];
115
- }
116
- const len = mapping.dictionary.length;
117
- const entries: string[] = [];
118
- for (let i = 0; i < len; i++) {
119
- const fn = arrowToString(mapping.dictionary.get(i));
120
- entries.push(getLastItem(fn) ?? '');
121
- }
122
- return entries;
113
+ const mappingsList = useMemo(() => {
114
+ const list =
115
+ mappings
116
+ ?.map(mapping => {
117
+ return getLastItem(mapping) as string;
123
118
  })
124
119
  .flat() ?? [];
125
120
 
126
121
  // We add a EVERYTHING ELSE mapping to the list.
127
- mappings.push('');
128
-
129
- // We look through the function names to find out if there's a runtime function.
130
- // Again, we only read through the dictionary, which is much faster than reading through all the rows.
131
- // We stop as soon as we find a runtime function.
132
- const functionNamesDict: Vector<Dictionary> | null = table.getChild(FIELD_FUNCTION_NAME);
133
- functionNamesDict?.data.forEach(fn => {
134
- if (fn.dictionary == null) {
135
- return;
136
- }
137
- const len = fn.dictionary.length;
138
- for (let i = 0; i < len; i++) {
139
- const fn: string | null = arrowToString(functionNamesDict?.get(i));
140
- if (fn?.startsWith('runtime') === true) {
141
- mappings.push('runtime');
142
- break;
143
- }
144
- }
145
- });
122
+ list.push('');
146
123
 
147
124
  // We sort the mappings alphabetically to make sure that the order is always the same.
148
- mappings.sort((a, b) => a.localeCompare(b));
149
- return mappings;
150
- }, [table]);
125
+ list.sort((a, b) => a.localeCompare(b));
151
126
 
152
- // TODO: Somehow figure out how to add runtime to this, if stacks are present.
153
- // Potentially read the function name dictionary and check if it contains strings starting with runtime.
154
- const mappingFeatures = useMemo(() => {
155
- return mappings.map(mapping => extractFeature(mapping));
127
+ return list;
156
128
  }, [mappings]);
157
129
 
158
- // TODO: Unify with mappingFeatures
159
130
  const mappingColors = useMemo(() => {
131
+ const mappingFeatures = mappingsList.map(mapping => extractFeature(mapping));
132
+
160
133
  const colors: mappingColors = {};
134
+
161
135
  Object.entries(mappingFeatures).forEach(([_, feature]) => {
162
136
  colors[feature.name] = getColorForFeature(
163
137
  feature.name,
@@ -165,8 +139,9 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
165
139
  currentColorProfile.colors
166
140
  );
167
141
  });
142
+
168
143
  return colors;
169
- }, [isDarkMode, mappingFeatures, currentColorProfile]);
144
+ }, [mappingsList, isDarkMode, currentColorProfile]);
170
145
 
171
146
  useEffect(() => {
172
147
  if (ref.current != null) {
@@ -198,6 +173,21 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
198
173
  setIsContextMenuOpen(isVisible);
199
174
  };
200
175
 
176
+ const hideBinary = (binaryToRemove: string): void => {
177
+ // second/subsequent time filtering out a binary i.e. a binary has already been hidden
178
+ // and we want to hide more binaries, we simply remove the binary from the binaryFrameFilter array in the URL.
179
+ if (Array.isArray(binaryFrameFilter) && binaryFrameFilter.length > 0) {
180
+ const newMappingsList = binaryFrameFilter.filter(mapping => mapping !== binaryToRemove);
181
+
182
+ setBinaryFrameFilter(newMappingsList);
183
+ return;
184
+ }
185
+
186
+ // first time hiding a binary
187
+ const newMappingsList = mappingsList.filter(mapping => mapping !== binaryToRemove);
188
+ setBinaryFrameFilter(newMappingsList);
189
+ };
190
+
201
191
  // useMemo for the root graph as it otherwise renders the whole graph if the hoveringRow changes.
202
192
  const root = useMemo(() => {
203
193
  return (
@@ -286,6 +276,7 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
286
276
  curPath={curPath}
287
277
  setCurPath={setCurPath}
288
278
  hideMenu={hideAll}
279
+ hideBinary={hideBinary}
289
280
  />
290
281
  {isColorStackLegendEnabled && (
291
282
  <ColorStackLegend
@@ -26,7 +26,6 @@ interface Props {
26
26
  diff: bigint | null;
27
27
  diffPerSecond: number | null;
28
28
  mappingColors: mappingColors;
29
- functionName: string | null;
30
29
  mappingFile: string | null;
31
30
  }
32
31
 
@@ -38,7 +37,6 @@ const useNodeColor = ({
38
37
  diff,
39
38
  diffPerSecond,
40
39
  mappingColors,
41
- functionName,
42
40
  mappingFile,
43
41
  }: Props): string => {
44
42
  if (compareMode) {
@@ -49,12 +47,7 @@ const useNodeColor = ({
49
47
  return diffColor(diff ?? 0n, cumulative, isDarkMode);
50
48
  }
51
49
 
52
- // To get the color we first check if the function name starts with 'runtime'.
53
- // If it does, we color it as runtime. Otherwise, we check the mapping file.
54
- // If there is no mapping file, we color it as 'everything else'.
55
- return functionName?.startsWith('runtime') === true
56
- ? mappingColors.runtime
57
- : mappingColors[getLastItem(mappingFile ?? '') ?? EVERYTHING_ELSE];
50
+ return mappingColors[getLastItem(mappingFile ?? '') ?? EVERYTHING_ELSE];
58
51
  };
59
52
 
60
53
  export default useNodeColor;
@@ -19,7 +19,6 @@ import {divide, getLastItem, valueFormatter} from '@parca/utilities';
19
19
  import {hexifyAddress} from '../../utils';
20
20
  import {
21
21
  FIELD_FUNCTION_NAME,
22
- FIELD_LABELS,
23
22
  FIELD_LABELS_ONLY,
24
23
  FIELD_LOCATION_ADDRESS,
25
24
  FIELD_MAPPING_FILE,
@@ -66,10 +65,6 @@ export function nodeLabel(
66
65
  }
67
66
 
68
67
  export const extractFeature = (mapping: string): Feature => {
69
- if (mapping === 'runtime' || mapping === 'root') {
70
- return {name: 'runtime', type: FEATURE_TYPES.Runtime};
71
- }
72
-
73
68
  if (mapping != null && mapping !== '') {
74
69
  return {name: mapping, type: FEATURE_TYPES.Binary};
75
70
  }