@parca/profile 0.16.450 → 0.16.451

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 (138) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.js +1 -1
  3. package/dist/ProfileIcicleGraph/IcicleGraph/index.js +1 -1
  4. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.js +1 -1
  5. package/dist/ProfileIcicleGraph/index.js +2 -2
  6. package/dist/ProfileView/components/ActionButtons/GroupByDropdown.d.ts.map +1 -0
  7. package/dist/{components → ProfileView/components}/ActionButtons/GroupByDropdown.js +1 -1
  8. package/dist/ProfileView/components/ActionButtons/SortByDropdown.d.ts.map +1 -0
  9. package/dist/{components → ProfileView/components}/ActionButtons/SortByDropdown.js +2 -2
  10. package/dist/ProfileView/components/ColorStackLegend.d.ts.map +1 -0
  11. package/dist/ProfileView/{ColorStackLegend.js → components/ColorStackLegend.js} +2 -2
  12. package/dist/ProfileView/components/DashboardItems/index.d.ts +26 -0
  13. package/dist/ProfileView/components/DashboardItems/index.d.ts.map +1 -0
  14. package/dist/ProfileView/components/DashboardItems/index.js +42 -0
  15. package/dist/ProfileView/components/DashboardLayout/index.d.ts +15 -0
  16. package/dist/ProfileView/components/DashboardLayout/index.d.ts.map +1 -0
  17. package/dist/ProfileView/components/DashboardLayout/index.js +20 -0
  18. package/dist/ProfileView/components/DiffLegend.d.ts.map +1 -0
  19. package/dist/ProfileView/components/FilterByFunctionButton.d.ts.map +1 -0
  20. package/dist/ProfileView/components/ProfileHeader/index.d.ts +9 -0
  21. package/dist/ProfileView/components/ProfileHeader/index.d.ts.map +1 -0
  22. package/dist/ProfileView/components/ProfileHeader/index.js +12 -0
  23. package/dist/ProfileView/components/ShareButton/ResultBox.d.ts.map +1 -0
  24. package/dist/{components → ProfileView/components}/ShareButton/index.d.ts +1 -1
  25. package/dist/ProfileView/components/ShareButton/index.d.ts.map +1 -0
  26. package/dist/ProfileView/components/Toolbars/MultiLevelDropdown.d.ts.map +1 -0
  27. package/dist/{components/VisualisationToolbar → ProfileView/components/Toolbars}/MultiLevelDropdown.js +2 -2
  28. package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.d.ts.map +1 -0
  29. package/dist/{components/VisualisationToolbar → ProfileView/components/Toolbars}/TableColumnsDropdown.js +4 -4
  30. package/dist/ProfileView/components/Toolbars/index.d.ts +41 -0
  31. package/dist/ProfileView/components/Toolbars/index.d.ts.map +1 -0
  32. package/dist/ProfileView/components/Toolbars/index.js +24 -0
  33. package/dist/ProfileView/components/ViewSelector/Dropdown.d.ts.map +1 -0
  34. package/dist/ProfileView/components/ViewSelector/index.d.ts.map +1 -0
  35. package/dist/ProfileView/components/VisualizationContainer/index.d.ts +21 -0
  36. package/dist/ProfileView/components/VisualizationContainer/index.d.ts.map +1 -0
  37. package/dist/ProfileView/components/VisualizationContainer/index.js +8 -0
  38. package/dist/ProfileView/{VisualizationPanel.d.ts → components/VisualizationPanel.d.ts} +4 -3
  39. package/dist/ProfileView/components/VisualizationPanel.d.ts.map +1 -0
  40. package/dist/ProfileView/context/DashboardContext.d.ts +12 -0
  41. package/dist/ProfileView/context/DashboardContext.d.ts.map +1 -0
  42. package/dist/ProfileView/context/DashboardContext.js +39 -0
  43. package/dist/ProfileView/{ProfileViewContext.d.ts → context/ProfileViewContext.d.ts} +1 -1
  44. package/dist/ProfileView/context/ProfileViewContext.d.ts.map +1 -0
  45. package/dist/ProfileView/hooks/useGraphviz.d.ts +12 -0
  46. package/dist/ProfileView/hooks/useGraphviz.d.ts.map +1 -0
  47. package/dist/ProfileView/hooks/useGraphviz.js +42 -0
  48. package/dist/ProfileView/hooks/useProfileMetadata.d.ts +17 -0
  49. package/dist/ProfileView/hooks/useProfileMetadata.d.ts.map +1 -0
  50. package/dist/ProfileView/hooks/useProfileMetadata.js +30 -0
  51. package/dist/ProfileView/hooks/useVisualizationState.d.ts +14 -0
  52. package/dist/ProfileView/hooks/useVisualizationState.d.ts.map +1 -0
  53. package/dist/ProfileView/hooks/useVisualizationState.js +52 -0
  54. package/dist/ProfileView/index.d.ts +2 -49
  55. package/dist/ProfileView/index.d.ts.map +1 -1
  56. package/dist/ProfileView/index.js +54 -173
  57. package/dist/ProfileView/types/visualization.d.ts +49 -0
  58. package/dist/ProfileView/types/visualization.d.ts.map +1 -0
  59. package/dist/ProfileView/types/visualization.js +13 -0
  60. package/dist/ProfileView/utils/colorUtils.d.ts +3 -0
  61. package/dist/ProfileView/utils/colorUtils.d.ts.map +1 -0
  62. package/dist/ProfileView/utils/colorUtils.js +21 -0
  63. package/dist/ProfileViewWithData.d.ts +2 -1
  64. package/dist/ProfileViewWithData.d.ts.map +1 -1
  65. package/dist/ProfileViewWithData.js +2 -2
  66. package/dist/SourceView/Highlighter.js +1 -1
  67. package/dist/Table/index.js +1 -1
  68. package/dist/TopTable/index.js +1 -1
  69. package/dist/styles.css +1 -1
  70. package/package.json +2 -2
  71. package/src/GraphTooltipArrow/useGraphTooltipMetaInfo/index.ts +1 -1
  72. package/src/ProfileIcicleGraph/IcicleGraph/index.tsx +1 -1
  73. package/src/ProfileIcicleGraph/IcicleGraphArrow/index.tsx +1 -1
  74. package/src/ProfileIcicleGraph/index.tsx +2 -2
  75. package/src/{components → ProfileView/components}/ActionButtons/GroupByDropdown.tsx +1 -1
  76. package/src/{components → ProfileView/components}/ActionButtons/SortByDropdown.tsx +2 -2
  77. package/src/ProfileView/{ColorStackLegend.tsx → components/ColorStackLegend.tsx} +2 -2
  78. package/src/ProfileView/components/DashboardItems/index.tsx +148 -0
  79. package/src/ProfileView/components/DashboardLayout/index.tsx +96 -0
  80. package/src/ProfileView/components/ProfileHeader/index.tsx +68 -0
  81. package/src/{components → ProfileView/components}/ShareButton/index.tsx +1 -1
  82. package/src/{components/VisualisationToolbar → ProfileView/components/Toolbars}/MultiLevelDropdown.tsx +2 -6
  83. package/src/{components/VisualisationToolbar → ProfileView/components/Toolbars}/TableColumnsDropdown.tsx +4 -4
  84. package/src/ProfileView/components/Toolbars/index.tsx +193 -0
  85. package/src/ProfileView/components/VisualizationContainer/index.tsx +68 -0
  86. package/src/ProfileView/{VisualizationPanel.tsx → components/VisualizationPanel.tsx} +5 -3
  87. package/src/ProfileView/context/DashboardContext.tsx +61 -0
  88. package/src/ProfileView/{ProfileViewContext.tsx → context/ProfileViewContext.tsx} +1 -1
  89. package/src/ProfileView/hooks/useGraphviz.ts +69 -0
  90. package/src/ProfileView/hooks/useProfileMetadata.ts +59 -0
  91. package/src/ProfileView/hooks/useVisualizationState.ts +82 -0
  92. package/src/ProfileView/index.tsx +126 -451
  93. package/src/ProfileView/types/visualization.ts +75 -0
  94. package/src/ProfileView/utils/colorUtils.ts +24 -0
  95. package/src/ProfileViewWithData.tsx +3 -0
  96. package/src/SourceView/Highlighter.tsx +1 -1
  97. package/src/Table/index.tsx +1 -1
  98. package/src/TopTable/index.tsx +1 -1
  99. package/dist/ProfileView/ColorStackLegend.d.ts.map +0 -1
  100. package/dist/ProfileView/ProfileViewContext.d.ts.map +0 -1
  101. package/dist/ProfileView/VisualizationPanel.d.ts.map +0 -1
  102. package/dist/components/ActionButtons/GroupByDropdown.d.ts.map +0 -1
  103. package/dist/components/ActionButtons/SortByDropdown.d.ts.map +0 -1
  104. package/dist/components/DiffLegend.d.ts.map +0 -1
  105. package/dist/components/FilterByFunctionButton.d.ts.map +0 -1
  106. package/dist/components/ShareButton/ResultBox.d.ts.map +0 -1
  107. package/dist/components/ShareButton/index.d.ts.map +0 -1
  108. package/dist/components/ViewSelector/Dropdown.d.ts.map +0 -1
  109. package/dist/components/ViewSelector/index.d.ts.map +0 -1
  110. package/dist/components/VisualisationToolbar/MultiLevelDropdown.d.ts.map +0 -1
  111. package/dist/components/VisualisationToolbar/TableColumnsDropdown.d.ts.map +0 -1
  112. package/dist/components/VisualisationToolbar/index.d.ts +0 -37
  113. package/dist/components/VisualisationToolbar/index.d.ts.map +0 -1
  114. package/dist/components/VisualisationToolbar/index.js +0 -64
  115. package/src/components/VisualisationToolbar/index.tsx +0 -228
  116. /package/dist/{components → ProfileView/components}/ActionButtons/GroupByDropdown.d.ts +0 -0
  117. /package/dist/{components → ProfileView/components}/ActionButtons/SortByDropdown.d.ts +0 -0
  118. /package/dist/ProfileView/{ColorStackLegend.d.ts → components/ColorStackLegend.d.ts} +0 -0
  119. /package/dist/{components → ProfileView/components}/DiffLegend.d.ts +0 -0
  120. /package/dist/{components → ProfileView/components}/DiffLegend.js +0 -0
  121. /package/dist/{components → ProfileView/components}/FilterByFunctionButton.d.ts +0 -0
  122. /package/dist/{components → ProfileView/components}/FilterByFunctionButton.js +0 -0
  123. /package/dist/{components → ProfileView/components}/ShareButton/ResultBox.d.ts +0 -0
  124. /package/dist/{components → ProfileView/components}/ShareButton/ResultBox.js +0 -0
  125. /package/dist/{components → ProfileView/components}/ShareButton/index.js +0 -0
  126. /package/dist/{components/VisualisationToolbar → ProfileView/components/Toolbars}/MultiLevelDropdown.d.ts +0 -0
  127. /package/dist/{components/VisualisationToolbar → ProfileView/components/Toolbars}/TableColumnsDropdown.d.ts +0 -0
  128. /package/dist/{components → ProfileView/components}/ViewSelector/Dropdown.d.ts +0 -0
  129. /package/dist/{components → ProfileView/components}/ViewSelector/Dropdown.js +0 -0
  130. /package/dist/{components → ProfileView/components}/ViewSelector/index.d.ts +0 -0
  131. /package/dist/{components → ProfileView/components}/ViewSelector/index.js +0 -0
  132. /package/dist/ProfileView/{VisualizationPanel.js → components/VisualizationPanel.js} +0 -0
  133. /package/dist/ProfileView/{ProfileViewContext.js → context/ProfileViewContext.js} +0 -0
  134. /package/src/{components → ProfileView/components}/DiffLegend.tsx +0 -0
  135. /package/src/{components → ProfileView/components}/FilterByFunctionButton.tsx +0 -0
  136. /package/src/{components → ProfileView/components}/ShareButton/ResultBox.tsx +0 -0
  137. /package/src/{components → ProfileView/components}/ViewSelector/Dropdown.tsx +0 -0
  138. /package/src/{components → ProfileView/components}/ViewSelector/index.tsx +0 -0
@@ -0,0 +1,193 @@
1
+ // Copyright 2022 The Parca Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+
14
+ import {FC} from 'react';
15
+
16
+ import {Icon} from '@iconify/react';
17
+
18
+ import {QueryServiceClient} from '@parca/client';
19
+ import {Button, UserPreferencesModal} from '@parca/components';
20
+ import {ProfileType} from '@parca/parser';
21
+
22
+ import {ProfileSource} from '../../../ProfileSource';
23
+ import {useDashboard} from '../../context/DashboardContext';
24
+ import GroupByDropdown from '../ActionButtons/GroupByDropdown';
25
+ import SortByDropdown from '../ActionButtons/SortByDropdown';
26
+ import FilterByFunctionButton from '../FilterByFunctionButton';
27
+ import ShareButton from '../ShareButton';
28
+ import ViewSelector from '../ViewSelector';
29
+ import MultiLevelDropdown from './MultiLevelDropdown';
30
+ import TableColumnsDropdown from './TableColumnsDropdown';
31
+
32
+ export interface VisualisationToolbarProps {
33
+ groupBy: string[];
34
+ toggleGroupBy: (key: string) => void;
35
+ hasProfileSource: boolean;
36
+ pprofdownloading?: boolean;
37
+ profileSource?: ProfileSource;
38
+ queryClient?: QueryServiceClient;
39
+ onDownloadPProf: () => void;
40
+ curPath: string[];
41
+ setNewCurPath: (path: string[]) => void;
42
+ profileType?: ProfileType;
43
+ total: bigint;
44
+ filtered: bigint;
45
+ currentSearchString?: string;
46
+ setSearchString?: (value: string) => void;
47
+ groupByLabels: string[];
48
+ preferencesModal?: boolean;
49
+ profileViewExternalSubActions?: React.ReactNode;
50
+ clearSelection: () => void;
51
+ setGroupByLabels: (labels: string[]) => void;
52
+ showVisualizationSelector?: boolean;
53
+ }
54
+
55
+ export interface TableToolbarProps {
56
+ profileType?: ProfileType;
57
+ total: bigint;
58
+ filtered: bigint;
59
+ clearSelection: () => void;
60
+ currentSearchString?: string;
61
+ }
62
+
63
+ export interface IcicleGraphToolbarProps {
64
+ curPath: string[];
65
+ setNewCurPath: (path: string[]) => void;
66
+ }
67
+
68
+ export const TableToolbar: FC<TableToolbarProps> = ({
69
+ profileType,
70
+ total,
71
+ filtered,
72
+ clearSelection,
73
+ currentSearchString,
74
+ }) => {
75
+ return (
76
+ <>
77
+ <div className="flex w-full gap-2 items-end">
78
+ <TableColumnsDropdown profileType={profileType} total={total} filtered={filtered} />
79
+ <Button
80
+ color="neutral"
81
+ onClick={clearSelection}
82
+ className="w-auto"
83
+ variant="neutral"
84
+ disabled={currentSearchString === undefined || currentSearchString.length === 0}
85
+ >
86
+ Clear selection
87
+ </Button>
88
+ </div>
89
+ </>
90
+ );
91
+ };
92
+
93
+ export const IcicleGraphToolbar: FC<IcicleGraphToolbarProps> = ({curPath, setNewCurPath}) => {
94
+ return (
95
+ <>
96
+ <div className="flex w-full gap-2 items-end">
97
+ <SortByDropdown />
98
+ <Button
99
+ variant="neutral"
100
+ className="gap-2 w-max h-fit"
101
+ onClick={() => setNewCurPath([])}
102
+ disabled={curPath.length === 0}
103
+ >
104
+ Reset graph
105
+ <Icon icon="system-uicons:reset" width={20} />
106
+ </Button>
107
+ </div>
108
+ </>
109
+ );
110
+ };
111
+
112
+ const Divider = (): JSX.Element => (
113
+ <div className="border-t mt-4 border-gray-200 dark:border-gray-700 h-[1px] w-full pb-4" />
114
+ );
115
+
116
+ export const VisualisationToolbar: FC<VisualisationToolbarProps> = ({
117
+ groupBy,
118
+ toggleGroupBy,
119
+ groupByLabels,
120
+ setGroupByLabels,
121
+ profileType,
122
+ preferencesModal,
123
+ profileSource,
124
+ queryClient,
125
+ onDownloadPProf,
126
+ pprofdownloading,
127
+ profileViewExternalSubActions,
128
+ curPath,
129
+ setNewCurPath,
130
+ total,
131
+ filtered,
132
+ currentSearchString,
133
+ clearSelection,
134
+ showVisualizationSelector = true,
135
+ }) => {
136
+ const {dashboardItems} = useDashboard();
137
+
138
+ const isTableViz = dashboardItems?.includes('table');
139
+ const isGraphViz = dashboardItems?.includes('icicle');
140
+
141
+ return (
142
+ <>
143
+ <div className="flex w-full justify-between items-end">
144
+ <div className="flex gap-3 items-end">
145
+ <>
146
+ <GroupByDropdown
147
+ groupBy={groupBy}
148
+ toggleGroupBy={toggleGroupBy}
149
+ labels={groupByLabels}
150
+ setGroupByLabels={setGroupByLabels}
151
+ />
152
+ <MultiLevelDropdown profileType={profileType} onSelect={() => {}} />
153
+ </>
154
+
155
+ <FilterByFunctionButton />
156
+
157
+ {profileViewExternalSubActions != null ? profileViewExternalSubActions : null}
158
+ </div>
159
+ <div className="flex gap-3">
160
+ {preferencesModal != null ? <UserPreferencesModal /> : null}
161
+ <ShareButton
162
+ profileSource={profileSource}
163
+ queryClient={queryClient}
164
+ queryRequest={profileSource?.QueryRequest() ?? undefined}
165
+ onDownloadPProf={onDownloadPProf}
166
+ pprofdownloading={pprofdownloading ?? false}
167
+ profileViewExternalSubActions={profileViewExternalSubActions}
168
+ />
169
+
170
+ {showVisualizationSelector ? <ViewSelector /> : null}
171
+ </div>
172
+ </div>
173
+ {isGraphViz && !isTableViz && (
174
+ <>
175
+ <Divider />
176
+ <IcicleGraphToolbar curPath={curPath} setNewCurPath={setNewCurPath} />
177
+ </>
178
+ )}
179
+ {isTableViz && !isGraphViz && (
180
+ <>
181
+ <Divider />
182
+ <TableToolbar
183
+ profileType={profileType}
184
+ total={total}
185
+ filtered={filtered}
186
+ clearSelection={clearSelection}
187
+ currentSearchString={currentSearchString}
188
+ />
189
+ </>
190
+ )}
191
+ </>
192
+ );
193
+ };
@@ -0,0 +1,68 @@
1
+ // Copyright 2022 The Parca Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+
14
+ import {FC} from 'react';
15
+
16
+ import cx from 'classnames';
17
+ import type {DraggableProvided, DraggableStateSnapshot} from 'react-beautiful-dnd';
18
+
19
+ import {useDashboard} from '../../context/DashboardContext';
20
+ import {VisualizationType} from '../../types/visualization';
21
+ import {VisualizationPanel} from '../VisualizationPanel';
22
+
23
+ interface VisualizationContainerProps {
24
+ provided: DraggableProvided;
25
+ snapshot: DraggableStateSnapshot;
26
+ dashboardItem: VisualizationType;
27
+ getDashboardItemByType: (props: {type: VisualizationType; isHalfScreen: boolean}) => JSX.Element;
28
+ isMultiPanelView: boolean;
29
+ index: number;
30
+ actionButtons: {
31
+ icicle: JSX.Element;
32
+ table: JSX.Element;
33
+ };
34
+ }
35
+
36
+ export const VisualizationContainer: FC<VisualizationContainerProps> = ({
37
+ provided,
38
+ snapshot,
39
+ dashboardItem,
40
+ getDashboardItemByType,
41
+ isMultiPanelView,
42
+ index,
43
+ actionButtons,
44
+ }) => {
45
+ const {handleClosePanel} = useDashboard();
46
+
47
+ return (
48
+ <div
49
+ ref={provided.innerRef}
50
+ {...provided.draggableProps}
51
+ className={cx(
52
+ 'w-full min-h-96',
53
+ snapshot.isDragging ? 'bg-gray-200 dark:bg-gray-500' : 'bg-white dark:bg-gray-900',
54
+ isMultiPanelView ? 'border-2 border-gray-100 dark:border-gray-700 rounded-md p-3' : ''
55
+ )}
56
+ >
57
+ <VisualizationPanel
58
+ handleClosePanel={handleClosePanel}
59
+ isMultiPanelView={isMultiPanelView}
60
+ dashboardItem={dashboardItem}
61
+ getDashboardItemByType={getDashboardItemByType}
62
+ dragHandleProps={provided.dragHandleProps}
63
+ index={index}
64
+ actionButtons={actionButtons}
65
+ />
66
+ </div>
67
+ );
68
+ };
@@ -20,13 +20,15 @@ import type {DraggableProvidedDragHandleProps} from 'react-beautiful-dnd';
20
20
  import {IconButton, useParcaContext} from '@parca/components';
21
21
  import {CloseIcon} from '@parca/icons';
22
22
 
23
+ import {VisualizationType} from '../types/visualization';
24
+
23
25
  interface Props {
24
- dashboardItem: string;
26
+ dashboardItem: VisualizationType;
25
27
  index: number;
26
28
  isMultiPanelView: boolean;
27
- handleClosePanel: (dashboardItem: string) => void;
29
+ handleClosePanel: (dashboardItem: VisualizationType) => void;
28
30
  dragHandleProps: DraggableProvidedDragHandleProps | null | undefined;
29
- getDashboardItemByType: (props: {type: string; isHalfScreen: boolean}) => JSX.Element;
31
+ getDashboardItemByType: (props: {type: VisualizationType; isHalfScreen: boolean}) => JSX.Element;
30
32
  actionButtons: {
31
33
  icicle: JSX.Element;
32
34
  table: JSX.Element;
@@ -0,0 +1,61 @@
1
+ // Copyright 2022 The Parca Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+
14
+ import {FC, PropsWithChildren, createContext, useContext} from 'react';
15
+
16
+ import {useURLState} from '@parca/components';
17
+
18
+ import {VisualizationType} from '../types/visualization';
19
+
20
+ interface DashboardContextType {
21
+ dashboardItems: string[];
22
+ setDashboardItems: (items: string[]) => void;
23
+ handleClosePanel: (visualizationType: VisualizationType) => void;
24
+ isMultiPanelView: boolean;
25
+ }
26
+
27
+ const DashboardContext = createContext<DashboardContextType | undefined>(undefined);
28
+
29
+ export const DashboardProvider: FC<PropsWithChildren> = ({children}) => {
30
+ const [dashboardItems, setDashboardItems] = useURLState<string[]>('dashboard_items', {
31
+ alwaysReturnArray: true,
32
+ });
33
+
34
+ const handleClosePanel = (visualizationType: VisualizationType): void => {
35
+ const newDashboardItems = dashboardItems.filter(item => item !== visualizationType);
36
+ setDashboardItems(newDashboardItems);
37
+ };
38
+
39
+ const isMultiPanelView = dashboardItems.length > 1;
40
+
41
+ return (
42
+ <DashboardContext.Provider
43
+ value={{
44
+ dashboardItems,
45
+ setDashboardItems,
46
+ handleClosePanel,
47
+ isMultiPanelView,
48
+ }}
49
+ >
50
+ {children}
51
+ </DashboardContext.Provider>
52
+ );
53
+ };
54
+
55
+ export const useDashboard = (): DashboardContextType => {
56
+ const context = useContext(DashboardContext);
57
+ if (context === undefined) {
58
+ throw new Error('useDashboard must be used within a DashboardProvider');
59
+ }
60
+ return context;
61
+ };
@@ -13,7 +13,7 @@
13
13
 
14
14
  import {ReactNode, createContext, useContext} from 'react';
15
15
 
16
- import {ProfileSource} from '../ProfileSource';
16
+ import {ProfileSource} from '../../ProfileSource';
17
17
 
18
18
  interface Props {
19
19
  profileSource?: ProfileSource;
@@ -0,0 +1,69 @@
1
+ // Copyright 2022 The Parca Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+
14
+ import {useEffect, useState} from 'react';
15
+
16
+ import graphviz from 'graphviz-wasm';
17
+
18
+ import {Callgraph as CallgraphType} from '@parca/client';
19
+
20
+ import {jsonToDot} from '../../Callgraph/utils';
21
+
22
+ interface UseGraphvizProps {
23
+ callgraphData?: CallgraphType;
24
+ width?: number;
25
+ colorRange: [string, string];
26
+ }
27
+
28
+ export const useGraphviz = ({
29
+ callgraphData,
30
+ width,
31
+ colorRange,
32
+ }: UseGraphvizProps): {
33
+ graphvizLoaded: boolean;
34
+ callgraphSVG: string | undefined;
35
+ } => {
36
+ const [graphvizLoaded, setGraphvizLoaded] = useState(false);
37
+ const [callgraphSVG, setCallgraphSVG] = useState<string | undefined>(undefined);
38
+
39
+ useEffect(() => {
40
+ async function loadGraphviz(): Promise<void> {
41
+ await graphviz.loadWASM();
42
+ setGraphvizLoaded(true);
43
+ }
44
+ void loadGraphviz();
45
+ }, []);
46
+
47
+ useEffect(() => {
48
+ async function loadCallgraphSVG(
49
+ graph: CallgraphType,
50
+ width: number,
51
+ colorRange: [string, string]
52
+ ): Promise<void> {
53
+ await setCallgraphSVG(undefined);
54
+ const dataAsDot = await jsonToDot({
55
+ graph,
56
+ width,
57
+ colorRange,
58
+ });
59
+ const svgGraph = await graphviz.layout(dataAsDot, 'svg', 'dot');
60
+ await setCallgraphSVG(svgGraph);
61
+ }
62
+
63
+ if (graphvizLoaded && callgraphData != null && width != null) {
64
+ void loadCallgraphSVG(callgraphData, width, colorRange);
65
+ }
66
+ }, [graphvizLoaded, callgraphData, width, colorRange]);
67
+
68
+ return {graphvizLoaded, callgraphSVG};
69
+ };
@@ -0,0 +1,59 @@
1
+ // Copyright 2022 The Parca Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+
14
+ import {useMemo} from 'react';
15
+
16
+ import {Table as ArrowTable, tableFromIPC} from 'apache-arrow';
17
+
18
+ import {FlamegraphArrow} from '@parca/client';
19
+
20
+ import useMappingList, {
21
+ useFilenamesList,
22
+ } from '../../ProfileIcicleGraph/IcicleGraphArrow/useMappingList';
23
+
24
+ interface UseProfileMetadataProps {
25
+ flamegraphArrow?: FlamegraphArrow;
26
+ metadataMappingFiles?: string[];
27
+ metadataLoading: boolean;
28
+ colorBy: string;
29
+ }
30
+
31
+ export const useProfileMetadata = ({
32
+ flamegraphArrow,
33
+ metadataMappingFiles,
34
+ metadataLoading,
35
+ colorBy,
36
+ }: UseProfileMetadataProps): {
37
+ table: ArrowTable<any> | null;
38
+ mappingsList: string[];
39
+ filenamesList: string[];
40
+ colorMappings: string[];
41
+ metadataLoading: boolean;
42
+ } => {
43
+ const table: ArrowTable<any> | null = useMemo(() => {
44
+ return flamegraphArrow !== undefined ? tableFromIPC(flamegraphArrow.record) : null;
45
+ }, [flamegraphArrow]);
46
+
47
+ const mappingsList = useMappingList(metadataMappingFiles);
48
+ const filenamesList = useFilenamesList(table);
49
+
50
+ const colorMappings = colorBy === 'binary' ? mappingsList : filenamesList;
51
+
52
+ return {
53
+ table,
54
+ mappingsList,
55
+ filenamesList,
56
+ colorMappings,
57
+ metadataLoading,
58
+ };
59
+ };
@@ -0,0 +1,82 @@
1
+ // Copyright 2022 The Parca Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+
14
+ import {useCallback, useState} from 'react';
15
+
16
+ import {useURLState} from '@parca/components';
17
+
18
+ import {FIELD_FUNCTION_NAME, FIELD_LABELS} from '../../ProfileIcicleGraph/IcicleGraphArrow';
19
+
20
+ export const useVisualizationState = (): {
21
+ curPath: string[];
22
+ setCurPath: (path: string[]) => void;
23
+ currentSearchString: string | undefined;
24
+ setSearchString: (searchString: string | undefined) => void;
25
+ colorStackLegend: string | undefined;
26
+ colorBy: string;
27
+ groupBy: string[];
28
+ setGroupBy: (keys: string[]) => void;
29
+ toggleGroupBy: (key: string) => void;
30
+ clearSelection: () => void;
31
+ setGroupByLabels: (labels: string[]) => void;
32
+ } => {
33
+ const [curPath, setCurPath] = useState<string[]>([]);
34
+ const [currentSearchString, setSearchString] = useURLState<string | undefined>('search_string');
35
+ const [colorStackLegend] = useURLState<string | undefined>('color_stack_legend');
36
+ const [colorBy] = useURLState('color_by');
37
+ const [groupBy, setStoreGroupBy] = useURLState<string[]>('group_by', {
38
+ defaultValue: [FIELD_FUNCTION_NAME],
39
+ alwaysReturnArray: true,
40
+ });
41
+
42
+ const setGroupBy = useCallback(
43
+ (keys: string[]): void => {
44
+ setStoreGroupBy(keys);
45
+ },
46
+ [setStoreGroupBy]
47
+ );
48
+
49
+ const toggleGroupBy = useCallback(
50
+ (key: string): void => {
51
+ groupBy.includes(key)
52
+ ? setGroupBy(groupBy.filter(v => v !== key)) // remove
53
+ : setGroupBy([...groupBy, key]); // add
54
+ },
55
+ [groupBy, setGroupBy]
56
+ );
57
+
58
+ const setGroupByLabels = useCallback(
59
+ (labels: string[]): void => {
60
+ setGroupBy(groupBy.filter(l => !l.startsWith(`${FIELD_LABELS}.`)).concat(labels));
61
+ },
62
+ [groupBy, setGroupBy]
63
+ );
64
+
65
+ const clearSelection = useCallback((): void => {
66
+ setSearchString?.('');
67
+ }, [setSearchString]);
68
+
69
+ return {
70
+ curPath,
71
+ setCurPath,
72
+ currentSearchString,
73
+ setSearchString,
74
+ colorStackLegend,
75
+ colorBy: (colorBy as string) ?? '',
76
+ groupBy,
77
+ setGroupBy,
78
+ toggleGroupBy,
79
+ setGroupByLabels,
80
+ clearSelection,
81
+ };
82
+ };