@parca/profile 0.16.416 → 0.16.418

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 (98) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/Callgraph/index.js +3 -2
  3. package/dist/GraphTooltipArrow/Content.d.ts +2 -3
  4. package/dist/GraphTooltipArrow/Content.d.ts.map +1 -1
  5. package/dist/GraphTooltipArrow/Content.js +6 -5
  6. package/dist/GraphTooltipArrow/DockedGraphTooltip/index.d.ts +2 -1
  7. package/dist/GraphTooltipArrow/DockedGraphTooltip/index.d.ts.map +1 -1
  8. package/dist/GraphTooltipArrow/DockedGraphTooltip/index.js +6 -7
  9. package/dist/GraphTooltipArrow/useGraphTooltip/index.d.ts +2 -3
  10. package/dist/GraphTooltipArrow/useGraphTooltip/index.d.ts.map +1 -1
  11. package/dist/GraphTooltipArrow/useGraphTooltip/index.js +9 -30
  12. package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.d.ts +1 -3
  13. package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.d.ts.map +1 -1
  14. package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.js +6 -16
  15. package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts.map +1 -1
  16. package/dist/ProfileExplorer/ProfileExplorerCompare.js +3 -3
  17. package/dist/ProfileExplorer/ProfileExplorerSingle.d.ts.map +1 -1
  18. package/dist/ProfileExplorer/ProfileExplorerSingle.js +1 -1
  19. package/dist/ProfileExplorer/index.d.ts.map +1 -1
  20. package/dist/ProfileExplorer/index.js +1 -7
  21. package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.d.ts +1 -3
  22. package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.d.ts.map +1 -1
  23. package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.js +2 -2
  24. package/dist/ProfileIcicleGraph/IcicleGraph/index.d.ts +0 -2
  25. package/dist/ProfileIcicleGraph/IcicleGraph/index.d.ts.map +1 -1
  26. package/dist/ProfileIcicleGraph/IcicleGraph/index.js +4 -3
  27. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.d.ts +1 -3
  28. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.d.ts.map +1 -1
  29. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.js +8 -20
  30. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.d.ts +2 -3
  31. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.d.ts.map +1 -1
  32. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.js +3 -2
  33. package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.d.ts.map +1 -1
  34. package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.js +6 -46
  35. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts +2 -5
  36. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts.map +1 -1
  37. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.js +6 -12
  38. package/dist/ProfileIcicleGraph/IcicleGraphArrow/useNodeColor.d.ts +1 -3
  39. package/dist/ProfileIcicleGraph/IcicleGraphArrow/useNodeColor.d.ts.map +1 -1
  40. package/dist/ProfileIcicleGraph/IcicleGraphArrow/useNodeColor.js +2 -5
  41. package/dist/ProfileIcicleGraph/index.d.ts +1 -3
  42. package/dist/ProfileIcicleGraph/index.d.ts.map +1 -1
  43. package/dist/ProfileIcicleGraph/index.js +21 -48
  44. package/dist/ProfileMetricsGraph/index.js +1 -2
  45. package/dist/ProfileView/FilterByFunctionButton.d.ts +1 -4
  46. package/dist/ProfileView/FilterByFunctionButton.d.ts.map +1 -1
  47. package/dist/ProfileView/FilterByFunctionButton.js +12 -3
  48. package/dist/ProfileView/ViewSelector.d.ts +1 -3
  49. package/dist/ProfileView/ViewSelector.d.ts.map +1 -1
  50. package/dist/ProfileView/ViewSelector.js +3 -4
  51. package/dist/ProfileView/VisualizationPanel.d.ts +0 -2
  52. package/dist/ProfileView/VisualizationPanel.d.ts.map +1 -1
  53. package/dist/ProfileView/VisualizationPanel.js +2 -2
  54. package/dist/ProfileView/index.d.ts +1 -5
  55. package/dist/ProfileView/index.d.ts.map +1 -1
  56. package/dist/ProfileView/index.js +11 -18
  57. package/dist/ProfileViewWithData.d.ts +1 -3
  58. package/dist/ProfileViewWithData.d.ts.map +1 -1
  59. package/dist/ProfileViewWithData.js +15 -12
  60. package/dist/SourceView/index.js +1 -1
  61. package/dist/SourceView/useSelectedLineRange.js +1 -1
  62. package/dist/Table/index.d.ts +1 -2
  63. package/dist/Table/index.d.ts.map +1 -1
  64. package/dist/Table/index.js +9 -25
  65. package/dist/TopTable/index.d.ts.map +1 -1
  66. package/dist/TopTable/index.js +3 -7
  67. package/dist/index.d.ts +3 -0
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +3 -0
  70. package/dist/styles.css +1 -1
  71. package/package.json +7 -7
  72. package/src/Callgraph/index.tsx +3 -3
  73. package/src/GraphTooltipArrow/Content.tsx +7 -36
  74. package/src/GraphTooltipArrow/DockedGraphTooltip/index.tsx +8 -16
  75. package/src/GraphTooltipArrow/useGraphTooltip/index.ts +10 -42
  76. package/src/GraphTooltipArrow/useGraphTooltipMetaInfo/index.ts +6 -22
  77. package/src/ProfileExplorer/ProfileExplorerCompare.tsx +2 -3
  78. package/src/ProfileExplorer/ProfileExplorerSingle.tsx +1 -5
  79. package/src/ProfileExplorer/index.tsx +0 -8
  80. package/src/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.tsx +2 -4
  81. package/src/ProfileIcicleGraph/IcicleGraph/index.tsx +5 -8
  82. package/src/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.tsx +8 -27
  83. package/src/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.tsx +5 -4
  84. package/src/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.tsx +9 -54
  85. package/src/ProfileIcicleGraph/IcicleGraphArrow/index.tsx +9 -20
  86. package/src/ProfileIcicleGraph/IcicleGraphArrow/useNodeColor.ts +1 -9
  87. package/src/ProfileIcicleGraph/index.tsx +21 -67
  88. package/src/ProfileMetricsGraph/index.tsx +2 -2
  89. package/src/ProfileView/FilterByFunctionButton.tsx +15 -9
  90. package/src/ProfileView/ViewSelector.tsx +6 -7
  91. package/src/ProfileView/VisualizationPanel.tsx +1 -9
  92. package/src/ProfileView/index.tsx +8 -23
  93. package/src/ProfileViewWithData.tsx +15 -18
  94. package/src/SourceView/index.tsx +1 -1
  95. package/src/SourceView/useSelectedLineRange.ts +2 -2
  96. package/src/Table/index.tsx +10 -41
  97. package/src/TopTable/index.tsx +3 -8
  98. package/src/index.tsx +4 -0
@@ -11,7 +11,7 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
 
14
- import {Profiler, ProfilerProps, useEffect, useMemo, useState} from 'react';
14
+ import {Profiler, ProfilerProps, useEffect, useState} from 'react';
15
15
 
16
16
  import {Icon} from '@iconify/react';
17
17
  import cx from 'classnames';
@@ -51,15 +51,13 @@ import {jsonToDot} from '../Callgraph/utils';
51
51
  import ProfileIcicleGraph from '../ProfileIcicleGraph';
52
52
  import {ProfileSource} from '../ProfileSource';
53
53
  import {SourceView} from '../SourceView';
54
- import Table from '../Table';
54
+ import {Table} from '../Table';
55
55
  import ProfileShareButton from '../components/ProfileShareButton';
56
56
  import FilterByFunctionButton from './FilterByFunctionButton';
57
57
  import {ProfileViewContextProvider} from './ProfileViewContext';
58
58
  import ViewSelector from './ViewSelector';
59
59
  import {VisualizationPanel} from './VisualizationPanel';
60
60
 
61
- type NavigateFunction = (path: string, queryParams: any, options?: {replace?: boolean}) => void;
62
-
63
61
  export interface FlamegraphData {
64
62
  loading: boolean;
65
63
  data?: Flamegraph;
@@ -104,7 +102,6 @@ export interface ProfileViewProps {
104
102
  sourceData?: SourceData;
105
103
  profileSource?: ProfileSource;
106
104
  queryClient?: QueryServiceClient;
107
- navigateTo?: NavigateFunction;
108
105
  compare?: boolean;
109
106
  onDownloadPProf: () => void;
110
107
  pprofDownloading?: boolean;
@@ -128,7 +125,6 @@ export const ProfileView = ({
128
125
  sourceData,
129
126
  profileSource,
130
127
  queryClient,
131
- navigateTo,
132
128
  onDownloadPProf,
133
129
  pprofDownloading,
134
130
  compare,
@@ -136,20 +132,12 @@ export const ProfileView = ({
136
132
  const {timezone} = useParcaContext();
137
133
  const {ref, dimensions} = useContainerDimensions();
138
134
  const [curPath, setCurPath] = useState<string[]>([]);
139
- const [rawDashboardItems = ['icicle'], setDashboardItems] = useURLState({
140
- param: 'dashboard_items',
141
- navigateTo,
135
+ const [dashboardItems, setDashboardItems] = useURLState<string[]>('dashboard_items', {
136
+ alwaysReturnArray: true,
142
137
  });
143
138
  const [graphvizLoaded, setGraphvizLoaded] = useState(false);
144
139
  const [callgraphSVG, setCallgraphSVG] = useState<string | undefined>(undefined);
145
- const [currentSearchString] = useURLState({param: 'search_string'});
146
-
147
- const dashboardItems = useMemo(() => {
148
- if (rawDashboardItems !== undefined) {
149
- return rawDashboardItems as string[];
150
- }
151
- return ['icicle'];
152
- }, [rawDashboardItems]);
140
+ const [currentSearchString, setSearchString] = useURLState<string | undefined>('search_string');
153
141
 
154
142
  const isDarkMode = useAppSelector(selectDarkMode);
155
143
  const isMultiPanelView = dashboardItems.length > 1;
@@ -240,7 +228,6 @@ export const ProfileView = ({
240
228
  total={total}
241
229
  filtered={filtered}
242
230
  profileType={profileSource?.ProfileType()}
243
- navigateTo={navigateTo}
244
231
  loading={flamegraphData.loading}
245
232
  setActionButtons={setActionButtons}
246
233
  error={flamegraphData.error}
@@ -281,9 +268,9 @@ export const ProfileView = ({
281
268
  data={topTableData.arrow?.record}
282
269
  unit={topTableData.unit}
283
270
  profileType={profileSource?.ProfileType()}
284
- navigateTo={navigateTo}
285
271
  setActionButtons={setActionButtons}
286
- currentSearchString={currentSearchString as string}
272
+ currentSearchString={currentSearchString}
273
+ setSearchString={setSearchString}
287
274
  isHalfScreen={isHalfScreen}
288
275
  />
289
276
  ) : (
@@ -371,7 +358,7 @@ export const ProfileView = ({
371
358
  </div>
372
359
 
373
360
  <div className="lg:flex flex-wrap items-center gap-2 md:justify-end hidden">
374
- <FilterByFunctionButton navigateTo={navigateTo} />
361
+ <FilterByFunctionButton />
375
362
  {profileViewExternalSubActions != null ? profileViewExternalSubActions : null}
376
363
  <UserPreferences
377
364
  customButton={
@@ -402,7 +389,6 @@ export const ProfileView = ({
402
389
  </Button>
403
390
  <ViewSelector
404
391
  defaultValue=""
405
- navigateTo={navigateTo}
406
392
  position={-1}
407
393
  placeholderText="Add panel"
408
394
  icon={<Icon icon="material-symbols:add" width={20} />}
@@ -451,7 +437,6 @@ export const ProfileView = ({
451
437
  dashboardItem={dashboardItem}
452
438
  getDashboardItemByType={getDashboardItemByType}
453
439
  dragHandleProps={provided.dragHandleProps}
454
- navigateTo={navigateTo}
455
440
  index={index}
456
441
  />
457
442
  </div>
@@ -15,7 +15,7 @@ import {useEffect, useMemo, useState} from 'react';
15
15
 
16
16
  import {QueryRequest_ReportType, QueryServiceClient} from '@parca/client';
17
17
  import {useGrpcMetadata, useParcaContext, useURLState} from '@parca/components';
18
- import {saveAsBlob, type NavigateFunction} from '@parca/utilities';
18
+ import {saveAsBlob} from '@parca/utilities';
19
19
 
20
20
  import {FIELD_FUNCTION_NAME} from './ProfileIcicleGraph/IcicleGraphArrow';
21
21
  import {ProfileSource} from './ProfileSource';
@@ -26,26 +26,27 @@ import {downloadPprof} from './utils';
26
26
  interface ProfileViewWithDataProps {
27
27
  queryClient: QueryServiceClient;
28
28
  profileSource: ProfileSource;
29
- navigateTo?: NavigateFunction;
30
29
  compare?: boolean;
31
30
  }
32
31
 
33
32
  export const ProfileViewWithData = ({
34
33
  queryClient,
35
34
  profileSource,
36
- navigateTo,
37
35
  }: ProfileViewWithDataProps): JSX.Element => {
38
36
  const metadata = useGrpcMetadata();
39
- const [dashboardItems = ['icicle']] = useURLState({param: 'dashboard_items', navigateTo});
40
- const [sourceBuildID] = useURLState({param: 'source_buildid', navigateTo}) as unknown as [string];
41
- const [sourceFilename] = useURLState({param: 'source_filename', navigateTo}) as unknown as [
42
- string
43
- ];
44
- const [groupBy = [FIELD_FUNCTION_NAME]] = useURLState({param: 'group_by', navigateTo});
45
-
46
- const [invertStack] = useURLState({param: 'invert_call_stack', navigateTo});
37
+ const [dashboardItems] = useURLState<string[]>('dashboard_items', {
38
+ alwaysReturnArray: true,
39
+ });
40
+ const [sourceBuildID] = useURLState<string>('source_buildid');
41
+ const [sourceFilename] = useURLState<string>('source_filename');
42
+ const [groupBy] = useURLState<string[]>('group_by', {
43
+ defaultValue: [FIELD_FUNCTION_NAME],
44
+ alwaysReturnArray: true,
45
+ });
46
+
47
+ const [invertStack] = useURLState('invert_call_stack');
47
48
  const invertCallStack = invertStack === 'true';
48
- const [binaryFrameFilterStr] = useURLState({param: 'binary_frame_filter', navigateTo});
49
+ const [binaryFrameFilterStr] = useURLState<string[] | string>('binary_frame_filter');
49
50
 
50
51
  const binaryFrameFilter: string[] =
51
52
  typeof binaryFrameFilterStr === 'string'
@@ -63,9 +64,6 @@ export const ProfileViewWithData = ({
63
64
  return (1 / width) * 100;
64
65
  }, []);
65
66
 
66
- // make sure we get a string[]
67
- const groupByParam: string[] = typeof groupBy === 'string' ? [groupBy] : groupBy;
68
-
69
67
  const {
70
68
  isLoading: flamegraphLoading,
71
69
  response: flamegraphResponse,
@@ -73,7 +71,7 @@ export const ProfileViewWithData = ({
73
71
  } = useQuery(queryClient, profileSource, QueryRequest_ReportType.FLAMEGRAPH_ARROW, {
74
72
  skip: !dashboardItems.includes('icicle'),
75
73
  nodeTrimThreshold,
76
- groupBy: groupByParam,
74
+ groupBy,
77
75
  invertCallStack,
78
76
  binaryFrameFilter,
79
77
  });
@@ -85,7 +83,7 @@ export const ProfileViewWithData = ({
85
83
  {
86
84
  skip: !dashboardItems.includes('icicle'),
87
85
  nodeTrimThreshold,
88
- groupBy: groupByParam,
86
+ groupBy,
89
87
  invertCallStack,
90
88
  binaryFrameFilter: undefined,
91
89
  }
@@ -237,7 +235,6 @@ export const ProfileViewWithData = ({
237
235
  }}
238
236
  profileSource={profileSource}
239
237
  queryClient={queryClient}
240
- navigateTo={navigateTo}
241
238
  onDownloadPProf={() => void downloadPProfClick()}
242
239
  pprofDownloading={pprofDownloading}
243
240
  />
@@ -42,7 +42,7 @@ export const SourceView = React.memo(function SourceView({
42
42
  filtered,
43
43
  setActionButtons,
44
44
  }: SourceViewProps): JSX.Element {
45
- const [sourceFileName] = useURLState({param: 'source_filename', navigateTo: () => {}});
45
+ const [sourceFileName] = useURLState<string | undefined>('source_filename');
46
46
  const {isDarkMode, sourceViewContextMenuItems = []} = useParcaContext();
47
47
 
48
48
  const sourceCode = useMemo(() => {
@@ -22,12 +22,12 @@ interface LineRange {
22
22
  }
23
23
 
24
24
  const useLineRange = (): LineRange => {
25
- const [sourceLine, setSourceLine] = useURLState({param: 'source_line', navigateTo: () => {}});
25
+ const [sourceLine, setSourceLine] = useURLState<string | undefined>('source_line');
26
26
  const [startLine, endLine] = useMemo(() => {
27
27
  if (sourceLine == null) {
28
28
  return [-1, -1];
29
29
  }
30
- const [start, end] = (sourceLine as string).split('-');
30
+ const [start, end] = sourceLine.split('-');
31
31
 
32
32
  if (end === undefined) {
33
33
  return [parseInt(start, 10), parseInt(start, 10)];
@@ -34,13 +34,7 @@ import {
34
34
  } from '@parca/components';
35
35
  import {type RowRendererProps} from '@parca/components/dist/Table';
36
36
  import {ProfileType} from '@parca/parser';
37
- import {
38
- getLastItem,
39
- isSearchMatch,
40
- parseParams,
41
- valueFormatter,
42
- type NavigateFunction,
43
- } from '@parca/utilities';
37
+ import {getLastItem, isSearchMatch, valueFormatter} from '@parca/utilities';
44
38
 
45
39
  import {useProfileViewContext} from '../ProfileView/ProfileViewContext';
46
40
  import {hexifyAddress} from '../utils';
@@ -96,9 +90,9 @@ interface TableProps {
96
90
  total: bigint;
97
91
  filtered: bigint;
98
92
  profileType?: ProfileType;
99
- navigateTo?: NavigateFunction;
100
93
  loading: boolean;
101
94
  currentSearchString?: string;
95
+ setSearchString?: (searchString: string) => void;
102
96
  setActionButtons?: (buttons: React.JSX.Element) => void;
103
97
  isHalfScreen: boolean;
104
98
  unit?: string;
@@ -295,29 +289,22 @@ export const Table = React.memo(function Table({
295
289
  total,
296
290
  filtered,
297
291
  profileType,
298
- navigateTo,
299
292
  loading,
300
293
  currentSearchString,
294
+ setSearchString = () => {},
301
295
  setActionButtons,
302
296
  isHalfScreen,
303
297
  unit,
304
298
  }: TableProps): React.JSX.Element {
305
- const router = parseParams(window?.location.search);
306
- const [rawDashboardItems] = useURLState({param: 'dashboard_items'});
307
- const [filterByFunctionInput] = useURLState({param: 'filter_by_function'});
299
+ const [dashboardItems] = useURLState<string[]>('dashboard_items', {
300
+ alwaysReturnArray: true,
301
+ });
308
302
  const {isDarkMode} = useParcaContext();
309
303
  const [expanded, setExpanded] = useState<ExpandedState>({});
310
304
  const [scrollToIndex, setScrollToIndex] = useState<number | undefined>(undefined);
311
305
 
312
306
  const {compareMode} = useProfileViewContext();
313
307
 
314
- const dashboardItems = useMemo(() => {
315
- if (rawDashboardItems !== undefined) {
316
- return rawDashboardItems as string[];
317
- }
318
- return ['icicle'];
319
- }, [rawDashboardItems]);
320
-
321
308
  const percentageString = (value: bigint | number, total: bigint | number): string => {
322
309
  if (total === 0n) {
323
310
  return '0%';
@@ -486,18 +473,9 @@ export const Table = React.memo(function Table({
486
473
 
487
474
  const selectSpan = useCallback(
488
475
  (span: string): void => {
489
- if (navigateTo != null) {
490
- navigateTo(
491
- '/',
492
- {
493
- ...router,
494
- ...{search_string: span.trim()},
495
- },
496
- {replace: true}
497
- );
498
- }
476
+ setSearchString(span.trim());
499
477
  },
500
- [navigateTo, router]
478
+ [setSearchString]
501
479
  );
502
480
 
503
481
  const onRowClick = useCallback(
@@ -563,17 +541,8 @@ export const Table = React.memo(function Table({
563
541
  }, [currentSearchString]);
564
542
 
565
543
  const clearSelection = useCallback((): void => {
566
- if (navigateTo != null) {
567
- navigateTo(
568
- '/',
569
- {
570
- ...router,
571
- ...{search_string: filterByFunctionInput ?? ''},
572
- },
573
- {replace: true}
574
- );
575
- }
576
- }, [navigateTo, router, filterByFunctionInput]);
544
+ setSearchString('');
545
+ }, [setSearchString]);
577
546
 
578
547
  useEffect(() => {
579
548
  setActionButtons?.(
@@ -72,17 +72,12 @@ export const TopTable = React.memo(function TopTable({
72
72
  setActionButtons,
73
73
  }: TopTableProps): JSX.Element {
74
74
  const router = parseParams(window?.location.search);
75
- const [rawDashboardItems] = useURLState({param: 'dashboard_items'});
75
+ const [dashboardItems] = useURLState<string[]>('dashboard_items', {
76
+ alwaysReturnArray: true,
77
+ });
76
78
 
77
79
  const {compareMode} = useProfileViewContext();
78
80
 
79
- const dashboardItems = useMemo(() => {
80
- if (rawDashboardItems !== undefined) {
81
- return rawDashboardItems as string[];
82
- }
83
- return ['icicle'];
84
- }, [rawDashboardItems]);
85
-
86
81
  const columns = useMemo(() => {
87
82
  const cols: Array<ColumnDef<TopNode, any>> = [
88
83
  columnHelper.accessor('meta', {
package/src/index.tsx CHANGED
@@ -25,6 +25,10 @@ export * from './ProfileTypeSelector';
25
25
  export * from './SourceView';
26
26
  export {default as Callgraph} from './Callgraph';
27
27
 
28
+ export const DEFAULT_PROFILE_EXPLORER_PARAM_VALUES = {
29
+ dashboard_items: 'icicle',
30
+ };
31
+
28
32
  export type {CallgraphProps};
29
33
 
30
34
  export {ProfileExplorer, ProfileTypeSelector, getExpressionAsAString};