@parca/profile 0.16.141 → 0.16.143
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 +8 -0
- package/dist/ProfileIcicleGraph/index.d.ts +3 -1
- package/dist/ProfileIcicleGraph/index.js +17 -15
- package/dist/ProfileView/index.d.ts +2 -0
- package/dist/ProfileView/index.js +2 -1
- package/dist/ProfileViewWithData.js +11 -9
- package/package.json +6 -6
- package/src/ProfileIcicleGraph/index.tsx +48 -20
- package/src/ProfileView/index.tsx +4 -0
- package/src/ProfileViewWithData.tsx +2 -0
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.143](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.142...@parca/profile@0.16.143) (2023-03-21)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
10
|
+
## [0.16.142](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.141...@parca/profile@0.16.142) (2023-03-21)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @parca/profile
|
|
13
|
+
|
|
6
14
|
## 0.16.141 (2023-03-20)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -5,6 +5,8 @@ export type ResizeHandler = (width: number, height: number) => void;
|
|
|
5
5
|
interface ProfileIcicleGraphProps {
|
|
6
6
|
width?: number;
|
|
7
7
|
graph: Flamegraph | undefined;
|
|
8
|
+
total: bigint;
|
|
9
|
+
filtered: bigint;
|
|
8
10
|
sampleUnit: string;
|
|
9
11
|
curPath: string[] | [];
|
|
10
12
|
setNewCurPath: (path: string[]) => void;
|
|
@@ -13,5 +15,5 @@ interface ProfileIcicleGraphProps {
|
|
|
13
15
|
loading: boolean;
|
|
14
16
|
setActionButtons?: (buttons: JSX.Element) => void;
|
|
15
17
|
}
|
|
16
|
-
declare const ProfileIcicleGraph: ({ graph, curPath, setNewCurPath, sampleUnit, onContainerResize, navigateTo, loading, setActionButtons, }: ProfileIcicleGraphProps) => JSX.Element;
|
|
18
|
+
declare const ProfileIcicleGraph: ({ graph, total, filtered, curPath, setNewCurPath, sampleUnit, onContainerResize, navigateTo, loading, setActionButtons, }: ProfileIcicleGraphProps) => JSX.Element;
|
|
17
19
|
export default ProfileIcicleGraph;
|
|
@@ -30,7 +30,7 @@ import DiffLegend from '../components/DiffLegend';
|
|
|
30
30
|
import { IcicleGraph } from './IcicleGraph';
|
|
31
31
|
var numberFormatter = new Intl.NumberFormat('en-US');
|
|
32
32
|
var ProfileIcicleGraph = function (_a) {
|
|
33
|
-
var graph = _a.graph, curPath = _a.curPath, setNewCurPath = _a.setNewCurPath, sampleUnit = _a.sampleUnit, onContainerResize = _a.onContainerResize, navigateTo = _a.navigateTo, loading = _a.loading, setActionButtons = _a.setActionButtons;
|
|
33
|
+
var graph = _a.graph, total = _a.total, filtered = _a.filtered, curPath = _a.curPath, setNewCurPath = _a.setNewCurPath, sampleUnit = _a.sampleUnit, onContainerResize = _a.onContainerResize, navigateTo = _a.navigateTo, loading = _a.loading, setActionButtons = _a.setActionButtons;
|
|
34
34
|
var compareMode = selectQueryParam('compare_a') === 'true' && selectQueryParam('compare_b') === 'true';
|
|
35
35
|
var _b = useContainerDimensions(), ref = _b.ref, dimensions = _b.dimensions;
|
|
36
36
|
useEffect(function () {
|
|
@@ -41,21 +41,24 @@ var ProfileIcicleGraph = function (_a) {
|
|
|
41
41
|
onContainerResize(dimensions.width, dimensions.height);
|
|
42
42
|
}, [dimensions, onContainerResize]);
|
|
43
43
|
var _c = useMemo(function () {
|
|
44
|
-
if (graph === undefined
|
|
45
|
-
return [false,
|
|
44
|
+
if (graph === undefined) {
|
|
45
|
+
return ['0', '0', false, '0', '0', false, '0', '0'];
|
|
46
46
|
}
|
|
47
|
-
var
|
|
48
|
-
var
|
|
49
|
-
|
|
50
|
-
var
|
|
47
|
+
var trimmed = BigInt(graph.trimmed);
|
|
48
|
+
var rawTotal = total + filtered + trimmed;
|
|
49
|
+
// safeguard against division by zero
|
|
50
|
+
var rawTotalDivisor = rawTotal > 0 ? rawTotal : BigInt(1);
|
|
51
51
|
return [
|
|
52
|
-
trimDifference > BigInt(0),
|
|
53
|
-
trimDifference,
|
|
54
|
-
trimmedPercentage.toString(),
|
|
55
52
|
numberFormatter.format(total),
|
|
56
|
-
numberFormatter.format(
|
|
53
|
+
numberFormatter.format(rawTotal),
|
|
54
|
+
trimmed > 0,
|
|
55
|
+
numberFormatter.format(trimmed),
|
|
56
|
+
numberFormatter.format((trimmed * BigInt(100)) / rawTotalDivisor),
|
|
57
|
+
filtered > 0,
|
|
58
|
+
numberFormatter.format(filtered),
|
|
59
|
+
numberFormatter.format((filtered * BigInt(100)) / rawTotalDivisor),
|
|
57
60
|
];
|
|
58
|
-
}, [graph]),
|
|
61
|
+
}, [filtered, graph, total]), totalFormatted = _c[0], rawFormatted = _c[1], isTrimmed = _c[2], trimmedFormatted = _c[3], trimmedPercentage = _c[4], isFiltered = _c[5], filteredFormatted = _c[6], filteredPercentage = _c[7];
|
|
59
62
|
useEffect(function () {
|
|
60
63
|
if (setActionButtons === undefined) {
|
|
61
64
|
return;
|
|
@@ -64,9 +67,8 @@ var ProfileIcicleGraph = function (_a) {
|
|
|
64
67
|
}, [setNewCurPath, curPath, setActionButtons]);
|
|
65
68
|
if (graph === undefined)
|
|
66
69
|
return _jsx("div", { children: "no data..." });
|
|
67
|
-
|
|
68
|
-
if (parseFloat(total) === 0 && !loading)
|
|
70
|
+
if (total === BigInt(0) && !loading)
|
|
69
71
|
return _jsx(_Fragment, { children: "Profile has no samples" });
|
|
70
|
-
return (_jsxs("div", __assign({ className: "relative" }, { children: [compareMode && _jsx(DiffLegend, {}),
|
|
72
|
+
return (_jsxs("div", __assign({ className: "relative" }, { children: [compareMode && _jsx(DiffLegend, {}), _jsx("div", __assign({ ref: ref }, { children: _jsx(IcicleGraph, { width: dimensions === null || dimensions === void 0 ? void 0 : dimensions.width, graph: graph, curPath: curPath, setCurPath: setNewCurPath, sampleUnit: sampleUnit, navigateTo: navigateTo }) })), _jsxs("p", __assign({ className: "my-2 text-xs" }, { children: ["Showing ", totalFormatted, " ", isFiltered || isTrimmed ? _jsxs("span", { children: ["of ", rawFormatted, " "] }) : _jsx(_Fragment, {}), "samples.", ' ', isFiltered ? (_jsxs("span", { children: ["Filtered ", filteredFormatted, " (", filteredPercentage, "%) samples.\u00A0"] })) : (_jsx(_Fragment, {})), isTrimmed ? (_jsxs("span", { children: ["Trimmed ", trimmedFormatted, " (", trimmedPercentage, "%) too small samples."] })) : (_jsx(_Fragment, {}))] }))] })));
|
|
71
73
|
};
|
|
72
74
|
export default ProfileIcicleGraph;
|
|
@@ -202,13 +202,14 @@ export var ProfileView = function (_a) {
|
|
|
202
202
|
}
|
|
203
203
|
};
|
|
204
204
|
var getDashboardItemByType = function (_a) {
|
|
205
|
+
var _b, _c;
|
|
205
206
|
var type = _a.type, isHalfScreen = _a.isHalfScreen, setActionButtons = _a.setActionButtons;
|
|
206
207
|
switch (type) {
|
|
207
208
|
case 'icicle': {
|
|
208
209
|
return (flamegraphData === null || flamegraphData === void 0 ? void 0 : flamegraphData.data) != null ? (_jsx(ConditionalWrapper, __assign({ condition: (perf === null || perf === void 0 ? void 0 : perf.onRender) != null, WrapperComponent: Profiler, wrapperProps: {
|
|
209
210
|
id: 'icicleGraph',
|
|
210
211
|
onRender: perf === null || perf === void 0 ? void 0 : perf.onRender,
|
|
211
|
-
} }, { children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, graph: flamegraphData.data, sampleUnit: sampleUnit, onContainerResize: onFlamegraphContainerResize, navigateTo: navigateTo, loading: flamegraphData.loading, setActionButtons: setActionButtons }) }))) : (_jsx(_Fragment, { children: " " }));
|
|
212
|
+
} }, { children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, graph: flamegraphData.data, total: (_b = flamegraphData === null || flamegraphData === void 0 ? void 0 : flamegraphData.total) !== null && _b !== void 0 ? _b : BigInt(0), filtered: (_c = flamegraphData === null || flamegraphData === void 0 ? void 0 : flamegraphData.filtered) !== null && _c !== void 0 ? _c : BigInt(0), sampleUnit: sampleUnit, onContainerResize: onFlamegraphContainerResize, navigateTo: navigateTo, loading: flamegraphData.loading, setActionButtons: setActionButtons }) }))) : (_jsx(_Fragment, { children: " " }));
|
|
212
213
|
}
|
|
213
214
|
case 'callgraph': {
|
|
214
215
|
return (callgraphData === null || callgraphData === void 0 ? void 0 : callgraphData.data) !== undefined &&
|
|
@@ -56,11 +56,11 @@ import { ProfileView } from './ProfileView';
|
|
|
56
56
|
import { useQuery } from './useQuery';
|
|
57
57
|
import { downloadPprof } from './utils';
|
|
58
58
|
export var ProfileViewWithData = function (_a) {
|
|
59
|
-
var _b, _c;
|
|
59
|
+
var _b, _c, _d, _e;
|
|
60
60
|
var queryClient = _a.queryClient, profileSource = _a.profileSource, navigateTo = _a.navigateTo;
|
|
61
61
|
var metadata = useGrpcMetadata();
|
|
62
62
|
var dashboardItems = useURLState({ param: 'dashboard_items', navigateTo: navigateTo })[0];
|
|
63
|
-
var
|
|
63
|
+
var _f = useState(0), nodeTrimThreshold = _f[0], setNodeTrimThreshold = _f[1];
|
|
64
64
|
var enableTrimming = useUserPreference(USER_PREFERENCES.ENABLE_GRAPH_TRIMMING.key)[0];
|
|
65
65
|
useEffect(function () {
|
|
66
66
|
if (!enableTrimming) {
|
|
@@ -77,17 +77,17 @@ export var ProfileViewWithData = function (_a) {
|
|
|
77
77
|
}
|
|
78
78
|
setNodeTrimThreshold(threshold);
|
|
79
79
|
};
|
|
80
|
-
var
|
|
80
|
+
var _g = useQuery(queryClient, profileSource, QueryRequest_ReportType.FLAMEGRAPH_TABLE, {
|
|
81
81
|
skip: !dashboardItems.includes('icicle'),
|
|
82
82
|
nodeTrimThreshold: nodeTrimThreshold,
|
|
83
|
-
}), flamegraphLoading =
|
|
83
|
+
}), flamegraphLoading = _g.isLoading, flamegraphResponse = _g.response, flamegraphError = _g.error;
|
|
84
84
|
var perf = useParcaContext().perf;
|
|
85
|
-
var
|
|
85
|
+
var _h = useQuery(queryClient, profileSource, QueryRequest_ReportType.TOP, {
|
|
86
86
|
skip: !dashboardItems.includes('table'),
|
|
87
|
-
}), topTableLoading =
|
|
88
|
-
var
|
|
87
|
+
}), topTableLoading = _h.isLoading, topTableResponse = _h.response, topTableError = _h.error;
|
|
88
|
+
var _j = useQuery(queryClient, profileSource, QueryRequest_ReportType.CALLGRAPH, {
|
|
89
89
|
skip: !dashboardItems.includes('callgraph'),
|
|
90
|
-
}), callgraphLoading =
|
|
90
|
+
}), callgraphLoading = _j.isLoading, callgraphResponse = _j.response, callgraphError = _j.error;
|
|
91
91
|
useEffect(function () {
|
|
92
92
|
var _a, _b;
|
|
93
93
|
if (!flamegraphLoading && (flamegraphResponse === null || flamegraphResponse === void 0 ? void 0 : flamegraphResponse.report.oneofKind) === 'flamegraph') {
|
|
@@ -138,6 +138,8 @@ export var ProfileViewWithData = function (_a) {
|
|
|
138
138
|
data: (flamegraphResponse === null || flamegraphResponse === void 0 ? void 0 : flamegraphResponse.report.oneofKind) === 'flamegraph'
|
|
139
139
|
? (_b = flamegraphResponse === null || flamegraphResponse === void 0 ? void 0 : flamegraphResponse.report) === null || _b === void 0 ? void 0 : _b.flamegraph
|
|
140
140
|
: undefined,
|
|
141
|
+
total: BigInt((_c = flamegraphResponse === null || flamegraphResponse === void 0 ? void 0 : flamegraphResponse.total) !== null && _c !== void 0 ? _c : '0'),
|
|
142
|
+
filtered: BigInt((_d = flamegraphResponse === null || flamegraphResponse === void 0 ? void 0 : flamegraphResponse.filtered) !== null && _d !== void 0 ? _d : '0'),
|
|
141
143
|
error: flamegraphError,
|
|
142
144
|
}, topTableData: {
|
|
143
145
|
loading: topTableLoading,
|
|
@@ -146,7 +148,7 @@ export var ProfileViewWithData = function (_a) {
|
|
|
146
148
|
}, callgraphData: {
|
|
147
149
|
loading: callgraphLoading,
|
|
148
150
|
data: (callgraphResponse === null || callgraphResponse === void 0 ? void 0 : callgraphResponse.report.oneofKind) === 'callgraph'
|
|
149
|
-
? (
|
|
151
|
+
? (_e = callgraphResponse === null || callgraphResponse === void 0 ? void 0 : callgraphResponse.report) === null || _e === void 0 ? void 0 : _e.callgraph
|
|
150
152
|
: undefined,
|
|
151
153
|
error: callgraphError,
|
|
152
154
|
}, sampleUnit: sampleUnit, profileSource: profileSource, queryClient: queryClient, navigateTo: navigateTo, onDownloadPProf: function () { return void downloadPProfClick(); }, onFlamegraphContainerResize: onFlamegraphContainerResize }));
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.143",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@parca/client": "^0.16.
|
|
7
|
-
"@parca/components": "^0.16.
|
|
6
|
+
"@parca/client": "^0.16.68",
|
|
7
|
+
"@parca/components": "^0.16.117",
|
|
8
8
|
"@parca/dynamicsize": "^0.16.54",
|
|
9
|
-
"@parca/functions": "^0.16.
|
|
9
|
+
"@parca/functions": "^0.16.69",
|
|
10
10
|
"@parca/parser": "^0.16.55",
|
|
11
|
-
"@parca/store": "^0.16.
|
|
11
|
+
"@parca/store": "^0.16.67",
|
|
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": "
|
|
48
|
+
"gitHead": "6bca71c40674ca2ee753adca4c9a719987a2f770"
|
|
49
49
|
}
|
|
@@ -28,6 +28,8 @@ export type ResizeHandler = (width: number, height: number) => void;
|
|
|
28
28
|
interface ProfileIcicleGraphProps {
|
|
29
29
|
width?: number;
|
|
30
30
|
graph: Flamegraph | undefined;
|
|
31
|
+
total: bigint;
|
|
32
|
+
filtered: bigint;
|
|
31
33
|
sampleUnit: string;
|
|
32
34
|
curPath: string[] | [];
|
|
33
35
|
setNewCurPath: (path: string[]) => void;
|
|
@@ -39,6 +41,8 @@ interface ProfileIcicleGraphProps {
|
|
|
39
41
|
|
|
40
42
|
const ProfileIcicleGraph = ({
|
|
41
43
|
graph,
|
|
44
|
+
total,
|
|
45
|
+
filtered,
|
|
42
46
|
curPath,
|
|
43
47
|
setNewCurPath,
|
|
44
48
|
sampleUnit,
|
|
@@ -58,25 +62,38 @@ const ProfileIcicleGraph = ({
|
|
|
58
62
|
onContainerResize(dimensions.width, dimensions.height);
|
|
59
63
|
}, [dimensions, onContainerResize]);
|
|
60
64
|
|
|
61
|
-
const [
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
const [
|
|
66
|
+
totalFormatted,
|
|
67
|
+
rawFormatted,
|
|
68
|
+
isTrimmed,
|
|
69
|
+
trimmedFormatted,
|
|
70
|
+
trimmedPercentage,
|
|
71
|
+
isFiltered,
|
|
72
|
+
filteredFormatted,
|
|
73
|
+
filteredPercentage,
|
|
74
|
+
] = useMemo(() => {
|
|
75
|
+
if (graph === undefined) {
|
|
76
|
+
return ['0', '0', false, '0', '0', false, '0', '0'];
|
|
64
77
|
}
|
|
65
78
|
|
|
66
|
-
const
|
|
67
|
-
const total = BigInt(graph.total);
|
|
79
|
+
const trimmed = BigInt(graph.trimmed);
|
|
68
80
|
|
|
69
|
-
const
|
|
70
|
-
|
|
81
|
+
const rawTotal = total + filtered + trimmed;
|
|
82
|
+
|
|
83
|
+
// safeguard against division by zero
|
|
84
|
+
const rawTotalDivisor = rawTotal > 0 ? rawTotal : BigInt(1);
|
|
71
85
|
|
|
72
86
|
return [
|
|
73
|
-
trimDifference > BigInt(0),
|
|
74
|
-
trimDifference,
|
|
75
|
-
trimmedPercentage.toString(),
|
|
76
87
|
numberFormatter.format(total),
|
|
77
|
-
numberFormatter.format(
|
|
88
|
+
numberFormatter.format(rawTotal),
|
|
89
|
+
trimmed > 0,
|
|
90
|
+
numberFormatter.format(trimmed),
|
|
91
|
+
numberFormatter.format((trimmed * BigInt(100)) / rawTotalDivisor),
|
|
92
|
+
filtered > 0,
|
|
93
|
+
numberFormatter.format(filtered),
|
|
94
|
+
numberFormatter.format((filtered * BigInt(100)) / rawTotalDivisor),
|
|
78
95
|
];
|
|
79
|
-
}, [graph]);
|
|
96
|
+
}, [filtered, graph, total]);
|
|
80
97
|
|
|
81
98
|
useEffect(() => {
|
|
82
99
|
if (setActionButtons === undefined) {
|
|
@@ -99,18 +116,11 @@ const ProfileIcicleGraph = ({
|
|
|
99
116
|
|
|
100
117
|
if (graph === undefined) return <div>no data...</div>;
|
|
101
118
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (parseFloat(total) === 0 && !loading) return <>Profile has no samples</>;
|
|
119
|
+
if (total === BigInt(0) && !loading) return <>Profile has no samples</>;
|
|
105
120
|
|
|
106
121
|
return (
|
|
107
122
|
<div className="relative">
|
|
108
123
|
{compareMode && <DiffLegend />}
|
|
109
|
-
{isTrimmed ? (
|
|
110
|
-
<p className="my-2 text-sm">
|
|
111
|
-
Showing {formattedTotal}({trimmedPercentage}%) out of {formattedUntrimmedTotal} samples
|
|
112
|
-
</p>
|
|
113
|
-
) : null}
|
|
114
124
|
<div ref={ref}>
|
|
115
125
|
<IcicleGraph
|
|
116
126
|
width={dimensions?.width}
|
|
@@ -121,6 +131,24 @@ const ProfileIcicleGraph = ({
|
|
|
121
131
|
navigateTo={navigateTo}
|
|
122
132
|
/>
|
|
123
133
|
</div>
|
|
134
|
+
<p className="my-2 text-xs">
|
|
135
|
+
Showing {totalFormatted} {isFiltered || isTrimmed ? <span>of {rawFormatted} </span> : <></>}
|
|
136
|
+
samples.{' '}
|
|
137
|
+
{isFiltered ? (
|
|
138
|
+
<span>
|
|
139
|
+
Filtered {filteredFormatted} ({filteredPercentage}%) samples.
|
|
140
|
+
</span>
|
|
141
|
+
) : (
|
|
142
|
+
<></>
|
|
143
|
+
)}
|
|
144
|
+
{isTrimmed ? (
|
|
145
|
+
<span>
|
|
146
|
+
Trimmed {trimmedFormatted} ({trimmedPercentage}%) too small samples.
|
|
147
|
+
</span>
|
|
148
|
+
) : (
|
|
149
|
+
<></>
|
|
150
|
+
)}
|
|
151
|
+
</p>
|
|
124
152
|
</div>
|
|
125
153
|
);
|
|
126
154
|
};
|
|
@@ -53,6 +53,8 @@ type NavigateFunction = (path: string, queryParams: any, options?: {replace?: bo
|
|
|
53
53
|
export interface FlamegraphData {
|
|
54
54
|
loading: boolean;
|
|
55
55
|
data?: Flamegraph;
|
|
56
|
+
total?: bigint;
|
|
57
|
+
filtered?: bigint;
|
|
56
58
|
error?: any;
|
|
57
59
|
}
|
|
58
60
|
|
|
@@ -233,6 +235,8 @@ export const ProfileView = ({
|
|
|
233
235
|
curPath={curPath}
|
|
234
236
|
setNewCurPath={setNewCurPath}
|
|
235
237
|
graph={flamegraphData.data}
|
|
238
|
+
total={flamegraphData?.total ?? BigInt(0)}
|
|
239
|
+
filtered={flamegraphData?.filtered ?? BigInt(0)}
|
|
236
240
|
sampleUnit={sampleUnit}
|
|
237
241
|
onContainerResize={onFlamegraphContainerResize}
|
|
238
242
|
navigateTo={navigateTo}
|
|
@@ -128,6 +128,8 @@ export const ProfileViewWithData = ({
|
|
|
128
128
|
flamegraphResponse?.report.oneofKind === 'flamegraph'
|
|
129
129
|
? flamegraphResponse?.report?.flamegraph
|
|
130
130
|
: undefined,
|
|
131
|
+
total: BigInt(flamegraphResponse?.total ?? '0'),
|
|
132
|
+
filtered: BigInt(flamegraphResponse?.filtered ?? '0'),
|
|
131
133
|
error: flamegraphError,
|
|
132
134
|
}}
|
|
133
135
|
topTableData={{
|