@parca/profile 0.16.0 → 0.16.22
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 +40 -0
- package/dist/Callgraph/Edge/index.d.ts +22 -0
- package/dist/Callgraph/Edge/index.js +30 -0
- package/dist/Callgraph/Node/index.d.ts +19 -0
- package/dist/Callgraph/Node/index.js +37 -0
- package/dist/Callgraph/index.d.ts +8 -0
- package/dist/Callgraph/index.js +137 -0
- package/dist/Callgraph/mockData/index.d.ts +148 -0
- package/dist/Callgraph/mockData/index.js +577 -0
- package/dist/Callgraph/utils.d.ts +19 -0
- package/dist/Callgraph/utils.js +82 -0
- package/dist/GraphTooltip/index.d.ts +19 -0
- package/dist/GraphTooltip/index.js +119 -0
- package/dist/IcicleGraph.d.ts +35 -0
- package/dist/IcicleGraph.js +139 -0
- package/dist/MatchersInput/index.d.ts +23 -0
- package/dist/MatchersInput/index.js +479 -0
- package/dist/MetricsCircle/index.d.ts +7 -0
- package/dist/MetricsCircle/index.js +18 -0
- package/dist/MetricsGraph/index.d.ts +35 -0
- package/dist/MetricsGraph/index.js +349 -0
- package/dist/MetricsSeries/index.d.ts +11 -0
- package/dist/MetricsSeries/index.js +21 -0
- package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts +19 -0
- package/dist/ProfileExplorer/ProfileExplorerCompare.js +38 -0
- package/dist/ProfileExplorer/ProfileExplorerSingle.d.ts +15 -0
- package/dist/ProfileExplorer/ProfileExplorerSingle.js +19 -0
- package/dist/ProfileExplorer/index.d.ts +9 -0
- package/dist/ProfileExplorer/index.js +203 -0
- package/dist/ProfileIcicleGraph.d.ts +10 -0
- package/dist/ProfileIcicleGraph.js +28 -0
- package/dist/ProfileMetricsGraph/index.d.ts +22 -0
- package/dist/ProfileMetricsGraph/index.js +127 -0
- package/dist/ProfileSVG.module.css +3 -0
- package/dist/ProfileSelector/CompareButton.d.ts +5 -0
- package/dist/ProfileSelector/CompareButton.js +41 -0
- package/dist/ProfileSelector/MergeButton.d.ts +5 -0
- package/dist/ProfileSelector/MergeButton.js +41 -0
- package/dist/ProfileSelector/index.d.ts +29 -0
- package/dist/ProfileSelector/index.js +133 -0
- package/dist/ProfileSource.d.ts +88 -0
- package/dist/ProfileSource.js +239 -0
- package/dist/ProfileTypeSelector/index.d.ts +20 -0
- package/dist/ProfileTypeSelector/index.js +138 -0
- package/dist/ProfileView.d.ts +39 -0
- package/dist/ProfileView.js +111 -0
- package/dist/ProfileView.styles.css +3 -0
- package/dist/ProfileViewWithData.d.ts +11 -0
- package/dist/ProfileViewWithData.js +116 -0
- package/dist/TopTable.d.ts +9 -0
- package/dist/TopTable.js +140 -0
- package/dist/TopTable.styles.css +7 -0
- package/dist/components/DiffLegend.d.ts +2 -0
- package/dist/components/DiffLegend.js +62 -0
- package/dist/components/ProfileShareButton/ResultBox.d.ts +6 -0
- package/dist/components/ProfileShareButton/ResultBox.js +46 -0
- package/dist/components/ProfileShareButton/index.d.ts +7 -0
- package/dist/components/ProfileShareButton/index.js +119 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +64 -0
- package/dist/styles.css +1 -0
- package/dist/useDelayedLoader.d.ts +5 -0
- package/dist/useDelayedLoader.js +33 -0
- package/dist/useQuery.d.ts +13 -0
- package/dist/useQuery.js +41 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +83 -0
- package/package.json +12 -8
- package/src/Callgraph/Edge/index.tsx +59 -0
- package/src/Callgraph/Node/index.tsx +66 -0
- package/src/Callgraph/index.tsx +169 -0
- package/src/Callgraph/mockData/index.ts +605 -0
- package/src/Callgraph/utils.ts +116 -0
- package/src/GraphTooltip/index.tsx +245 -0
- package/src/IcicleGraph.tsx +3 -3
- package/src/MatchersInput/index.tsx +698 -0
- package/src/MetricsCircle/index.tsx +28 -0
- package/src/MetricsGraph/index.tsx +614 -0
- package/src/MetricsSeries/index.tsx +38 -0
- package/src/ProfileExplorer/ProfileExplorerCompare.tsx +109 -0
- package/src/ProfileExplorer/ProfileExplorerSingle.tsx +72 -0
- package/src/ProfileExplorer/index.tsx +377 -0
- package/src/ProfileMetricsGraph/index.tsx +143 -0
- package/src/ProfileSelector/CompareButton.tsx +72 -0
- package/src/ProfileSelector/MergeButton.tsx +72 -0
- package/src/ProfileSelector/index.tsx +270 -0
- package/src/ProfileTypeSelector/index.tsx +180 -0
- package/src/ProfileView.tsx +2 -7
- package/src/index.tsx +11 -0
- package/src/useQuery.tsx +1 -0
- package/tailwind.config.js +8 -0
- package/tsconfig.json +7 -3
- package/typings.d.ts +14 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
|
+
import { ProfileSelectionFromParams, SuffixParams } from '..';
|
|
14
|
+
import ProfileExplorerSingle from './ProfileExplorerSingle';
|
|
15
|
+
import ProfileExplorerCompare from './ProfileExplorerCompare';
|
|
16
|
+
import { useAppSelector, useAppDispatch, setCompare, selectCompareMode, setSearchNodeString, store, } from '@parca/store';
|
|
17
|
+
import { Provider, batch } from 'react-redux';
|
|
18
|
+
import { DateTimeRange } from '@parca/components';
|
|
19
|
+
import { useEffect } from 'react';
|
|
20
|
+
var getExpressionAsAString = function (expression) {
|
|
21
|
+
var x = Array.isArray(expression) ? expression.join() : expression;
|
|
22
|
+
return x;
|
|
23
|
+
};
|
|
24
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
25
|
+
var sanitizeDateRange = function (time_selection_a, from_a, to_a) {
|
|
26
|
+
var range = DateTimeRange.fromRangeKey(time_selection_a);
|
|
27
|
+
if (from_a == null && to_a == null) {
|
|
28
|
+
from_a = range.getFromMs();
|
|
29
|
+
to_a = range.getToMs();
|
|
30
|
+
}
|
|
31
|
+
return { time_selection_a: range.getRangeKey(), from_a: from_a, to_a: to_a };
|
|
32
|
+
};
|
|
33
|
+
/* eslint-enable @typescript-eslint/naming-convention */
|
|
34
|
+
var ProfileExplorerApp = function (_a) {
|
|
35
|
+
var _b, _c;
|
|
36
|
+
var queryClient = _a.queryClient, queryParams = _a.queryParams, navigateTo = _a.navigateTo;
|
|
37
|
+
var dispatch = useAppDispatch();
|
|
38
|
+
var compareMode = useAppSelector(selectCompareMode);
|
|
39
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
40
|
+
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;
|
|
41
|
+
/* eslint-enable @typescript-eslint/naming-convention */
|
|
42
|
+
var sanitizedRange = sanitizeDateRange(time_selection_a, from_a, to_a);
|
|
43
|
+
time_selection_a = sanitizedRange.time_selection_a;
|
|
44
|
+
from_a = sanitizedRange.from_a;
|
|
45
|
+
to_a = sanitizedRange.to_a;
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
47
|
+
var expression_a = getExpressionAsAString(queryParams.expression_a);
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
49
|
+
var expression_b = getExpressionAsAString(queryParams.expression_b);
|
|
50
|
+
if (((_b = queryParams === null || queryParams === void 0 ? void 0 : queryParams.expression_a) !== null && _b !== void 0 ? _b : '') !== '')
|
|
51
|
+
queryParams.expression_a = expression_a;
|
|
52
|
+
if (((_c = queryParams === null || queryParams === void 0 ? void 0 : queryParams.expression_b) !== null && _c !== void 0 ? _c : '') !== '')
|
|
53
|
+
queryParams.expression_b = expression_b;
|
|
54
|
+
useEffect(function () {
|
|
55
|
+
if (compare_a === 'true' && compare_b === 'true') {
|
|
56
|
+
dispatch(setCompare(true));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
dispatch(setCompare(false));
|
|
60
|
+
}
|
|
61
|
+
}, [dispatch, compare_a, compare_b]);
|
|
62
|
+
var filterSuffix = function (o, suffix) {
|
|
63
|
+
return Object.fromEntries(Object.entries(o).filter(function (_a) {
|
|
64
|
+
var key = _a[0];
|
|
65
|
+
return !key.endsWith(suffix);
|
|
66
|
+
}));
|
|
67
|
+
};
|
|
68
|
+
var swapQueryParameters = function (o) {
|
|
69
|
+
Object.entries(o).forEach(function (_a) {
|
|
70
|
+
var key = _a[0], value = _a[1];
|
|
71
|
+
if (key.endsWith('_b')) {
|
|
72
|
+
o[key.slice(0, -2) + '_a'] = value;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
return o;
|
|
76
|
+
};
|
|
77
|
+
var selectProfileA = function (p) {
|
|
78
|
+
queryParams.expression_a = encodeURIComponent(queryParams.expression_a);
|
|
79
|
+
queryParams.expression_b = encodeURIComponent(queryParams.expression_b);
|
|
80
|
+
return navigateTo('/', __assign(__assign({}, queryParams), SuffixParams(p.HistoryParams(), '_a')));
|
|
81
|
+
};
|
|
82
|
+
var selectProfileB = function (p) {
|
|
83
|
+
queryParams.expression_a = encodeURIComponent(queryParams.expression_a);
|
|
84
|
+
queryParams.expression_b = encodeURIComponent(queryParams.expression_b);
|
|
85
|
+
return navigateTo('/', __assign(__assign({}, queryParams), SuffixParams(p.HistoryParams(), '_b')));
|
|
86
|
+
};
|
|
87
|
+
// Show the SingleProfileExplorer when not comparing
|
|
88
|
+
if (compare_a !== 'true' && compare_b !== 'true') {
|
|
89
|
+
var query_1 = {
|
|
90
|
+
expression: expression_a,
|
|
91
|
+
from: parseInt(from_a),
|
|
92
|
+
to: parseInt(to_a),
|
|
93
|
+
merge: merge_a === 'true',
|
|
94
|
+
profile_name: profile_name_a,
|
|
95
|
+
timeSelection: time_selection_a,
|
|
96
|
+
};
|
|
97
|
+
var profile_1 = ProfileSelectionFromParams(expression_a, from_a, to_a, merge_a, labels_a, profile_name_a, time_a);
|
|
98
|
+
var selectQuery = function (q) {
|
|
99
|
+
return navigateTo('/', __assign(__assign({}, filterSuffix(queryParams, '_a')), {
|
|
100
|
+
expression_a: encodeURIComponent(q.expression),
|
|
101
|
+
from_a: q.from.toString(),
|
|
102
|
+
to_a: q.to.toString(),
|
|
103
|
+
merge_a: q.merge,
|
|
104
|
+
time_selection_a: q.timeSelection,
|
|
105
|
+
currentProfileView: 'icicle',
|
|
106
|
+
}));
|
|
107
|
+
};
|
|
108
|
+
var selectProfile = function (p) {
|
|
109
|
+
queryParams.expression_a = encodeURIComponent(queryParams.expression_a);
|
|
110
|
+
return navigateTo('/', __assign(__assign({}, queryParams), SuffixParams(p.HistoryParams(), '_a')));
|
|
111
|
+
};
|
|
112
|
+
var compareProfile = function () {
|
|
113
|
+
var compareQuery = {
|
|
114
|
+
compare_a: 'true',
|
|
115
|
+
expression_a: encodeURIComponent(query_1.expression),
|
|
116
|
+
from_a: query_1.from.toString(),
|
|
117
|
+
to_a: query_1.to.toString(),
|
|
118
|
+
merge_a: query_1.merge,
|
|
119
|
+
time_selection_a: query_1.timeSelection,
|
|
120
|
+
profile_name_a: query_1.profile_name,
|
|
121
|
+
compare_b: 'true',
|
|
122
|
+
expression_b: encodeURIComponent(query_1.expression),
|
|
123
|
+
from_b: query_1.from.toString(),
|
|
124
|
+
to_b: query_1.to.toString(),
|
|
125
|
+
merge_b: query_1.merge,
|
|
126
|
+
time_selection_b: query_1.timeSelection,
|
|
127
|
+
profile_name_b: query_1.profile_name,
|
|
128
|
+
};
|
|
129
|
+
if (profile_1 != null) {
|
|
130
|
+
compareQuery = __assign(__assign({}, SuffixParams(profile_1.HistoryParams(), '_a')), compareQuery);
|
|
131
|
+
}
|
|
132
|
+
compareQuery = __assign(__assign({}, compareQuery), {
|
|
133
|
+
currentProfileView: 'icicle',
|
|
134
|
+
});
|
|
135
|
+
batch(function () {
|
|
136
|
+
dispatch(setCompare(!compareMode));
|
|
137
|
+
dispatch(setSearchNodeString(undefined));
|
|
138
|
+
});
|
|
139
|
+
void navigateTo('/', compareQuery);
|
|
140
|
+
};
|
|
141
|
+
return (_jsx(ProfileExplorerSingle, { queryClient: queryClient, query: query_1, profile: profile_1, selectQuery: selectQuery, selectProfile: selectProfile, compareProfile: compareProfile, navigateTo: navigateTo }));
|
|
142
|
+
}
|
|
143
|
+
var queryA = {
|
|
144
|
+
expression: expression_a,
|
|
145
|
+
from: parseInt(from_a),
|
|
146
|
+
to: parseInt(to_a),
|
|
147
|
+
merge: merge_a === 'true',
|
|
148
|
+
timeSelection: time_selection_a,
|
|
149
|
+
profile_name: profile_name_a,
|
|
150
|
+
};
|
|
151
|
+
var queryB = {
|
|
152
|
+
expression: expression_b,
|
|
153
|
+
from: parseInt(from_b),
|
|
154
|
+
to: parseInt(to_b),
|
|
155
|
+
merge: merge_b === 'true',
|
|
156
|
+
timeSelection: time_selection_b,
|
|
157
|
+
profile_name: profile_name_b,
|
|
158
|
+
};
|
|
159
|
+
var profileA = ProfileSelectionFromParams(expression_a, from_a, to_a, merge_a, labels_a, profile_name_a, time_a);
|
|
160
|
+
var profileB = ProfileSelectionFromParams(expression_b, from_b, to_b, merge_b, labels_b, profile_name_b, time_b);
|
|
161
|
+
var selectQueryA = function (q) {
|
|
162
|
+
return navigateTo('/', __assign(__assign({}, filterSuffix(queryParams, '_a')), {
|
|
163
|
+
compare_a: 'true',
|
|
164
|
+
expression_a: encodeURIComponent(q.expression),
|
|
165
|
+
expression_b: encodeURIComponent(expression_b),
|
|
166
|
+
from_a: q.from.toString(),
|
|
167
|
+
to_a: q.to.toString(),
|
|
168
|
+
merge_a: q.merge,
|
|
169
|
+
time_selection_a: q.timeSelection,
|
|
170
|
+
}));
|
|
171
|
+
};
|
|
172
|
+
var selectQueryB = function (q) {
|
|
173
|
+
return navigateTo('/', __assign(__assign({}, filterSuffix(queryParams, '_b')), {
|
|
174
|
+
compare_b: 'true',
|
|
175
|
+
expression_b: encodeURIComponent(q.expression),
|
|
176
|
+
expression_a: encodeURIComponent(expression_a),
|
|
177
|
+
from_b: q.from.toString(),
|
|
178
|
+
to_b: q.to.toString(),
|
|
179
|
+
merge_b: q.merge,
|
|
180
|
+
time_selection_b: q.timeSelection,
|
|
181
|
+
}));
|
|
182
|
+
};
|
|
183
|
+
var closeProfile = function (card) {
|
|
184
|
+
var newQueryParameters = queryParams;
|
|
185
|
+
if (card === 'A') {
|
|
186
|
+
newQueryParameters = swapQueryParameters(queryParams);
|
|
187
|
+
}
|
|
188
|
+
batch(function () {
|
|
189
|
+
dispatch(setCompare(!compareMode));
|
|
190
|
+
dispatch(setSearchNodeString(undefined));
|
|
191
|
+
});
|
|
192
|
+
return navigateTo('/', __assign(__assign({}, filterSuffix(newQueryParameters, '_b')), {
|
|
193
|
+
compare_a: 'false',
|
|
194
|
+
}));
|
|
195
|
+
};
|
|
196
|
+
return (_jsx(ProfileExplorerCompare, { queryClient: queryClient, queryA: queryA, queryB: queryB, profileA: profileA, profileB: profileB, selectQueryA: selectQueryA, selectQueryB: selectQueryB, selectProfileA: selectProfileA, selectProfileB: selectProfileB, closeProfile: closeProfile, navigateTo: navigateTo }));
|
|
197
|
+
};
|
|
198
|
+
var ProfileExplorer = function (_a) {
|
|
199
|
+
var queryClient = _a.queryClient, queryParams = _a.queryParams, navigateTo = _a.navigateTo;
|
|
200
|
+
var reduxStore = store().store;
|
|
201
|
+
return (_jsx(Provider, __assign({ store: reduxStore }, { children: _jsx(ProfileExplorerApp, { queryClient: queryClient, queryParams: queryParams, navigateTo: navigateTo }) })));
|
|
202
|
+
};
|
|
203
|
+
export default ProfileExplorer;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Flamegraph } from '@parca/client';
|
|
2
|
+
interface ProfileIcicleGraphProps {
|
|
3
|
+
width?: number;
|
|
4
|
+
graph: Flamegraph | undefined;
|
|
5
|
+
sampleUnit: string;
|
|
6
|
+
curPath: string[] | [];
|
|
7
|
+
setNewCurPath: (path: string[]) => void;
|
|
8
|
+
}
|
|
9
|
+
declare const ProfileIcicleGraph: ({ graph, curPath, setNewCurPath, sampleUnit, }: ProfileIcicleGraphProps) => JSX.Element;
|
|
10
|
+
export default ProfileIcicleGraph;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
import { useAppSelector, selectCompareMode } from '@parca/store';
|
|
14
|
+
import { useContainerDimensions } from '@parca/dynamicsize';
|
|
15
|
+
import DiffLegend from './components/DiffLegend';
|
|
16
|
+
import IcicleGraph from './IcicleGraph';
|
|
17
|
+
var ProfileIcicleGraph = function (_a) {
|
|
18
|
+
var graph = _a.graph, curPath = _a.curPath, setNewCurPath = _a.setNewCurPath, sampleUnit = _a.sampleUnit;
|
|
19
|
+
var compareMode = useAppSelector(selectCompareMode);
|
|
20
|
+
var _b = useContainerDimensions(), ref = _b.ref, dimensions = _b.dimensions;
|
|
21
|
+
if (graph === undefined)
|
|
22
|
+
return _jsx("div", { children: "no data..." });
|
|
23
|
+
var total = graph.total;
|
|
24
|
+
if (parseFloat(total) === 0)
|
|
25
|
+
return _jsx(_Fragment, { children: "Profile has no samples" });
|
|
26
|
+
return (_jsxs(_Fragment, { 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 }) }))] }));
|
|
27
|
+
};
|
|
28
|
+
export default ProfileIcicleGraph;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ProfileSelection } from '..';
|
|
2
|
+
import { QueryServiceClient, QueryRangeResponse } from '@parca/client';
|
|
3
|
+
import { RpcError } from '@protobuf-ts/runtime-rpc';
|
|
4
|
+
import { DateTimeRange } from '@parca/components';
|
|
5
|
+
interface ProfileMetricsGraphProps {
|
|
6
|
+
queryClient: QueryServiceClient;
|
|
7
|
+
queryExpression: string;
|
|
8
|
+
profile: ProfileSelection | null;
|
|
9
|
+
from: number;
|
|
10
|
+
to: number;
|
|
11
|
+
select: (source: ProfileSelection) => void;
|
|
12
|
+
setTimeRange: (range: DateTimeRange) => void;
|
|
13
|
+
addLabelMatcher: (key: string, value: string) => void;
|
|
14
|
+
}
|
|
15
|
+
export interface IQueryRangeResult {
|
|
16
|
+
response: QueryRangeResponse | null;
|
|
17
|
+
isLoading: boolean;
|
|
18
|
+
error: RpcError | null;
|
|
19
|
+
}
|
|
20
|
+
export declare const useQueryRange: (client: QueryServiceClient, queryExpression: string, start: number, end: number) => IQueryRangeResult;
|
|
21
|
+
declare const ProfileMetricsGraph: ({ queryClient, queryExpression, profile, from, to, select, setTimeRange, addLabelMatcher, }: ProfileMetricsGraphProps) => JSX.Element;
|
|
22
|
+
export default ProfileMetricsGraph;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
14
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
22
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
23
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
24
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
25
|
+
function step(op) {
|
|
26
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
27
|
+
while (_) try {
|
|
28
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
29
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
30
|
+
switch (op[0]) {
|
|
31
|
+
case 0: case 1: t = op; break;
|
|
32
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
33
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
34
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
35
|
+
default:
|
|
36
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
37
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
38
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
39
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
40
|
+
if (t[2]) _.ops.pop();
|
|
41
|
+
_.trys.pop(); continue;
|
|
42
|
+
}
|
|
43
|
+
op = body.call(thisArg, _);
|
|
44
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
45
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
49
|
+
// Copyright 2022 The Parca Authors
|
|
50
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
51
|
+
// you may not use this file except in compliance with the License.
|
|
52
|
+
// You may obtain a copy of the License at
|
|
53
|
+
//
|
|
54
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
55
|
+
//
|
|
56
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
57
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
58
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
59
|
+
// See the License for the specific language governing permissions and
|
|
60
|
+
// limitations under the License.
|
|
61
|
+
import { useState, useEffect } from 'react';
|
|
62
|
+
import MetricsGraph from '../MetricsGraph';
|
|
63
|
+
import { SingleProfileSelection } from '..';
|
|
64
|
+
import { Timestamp } from '@parca/client';
|
|
65
|
+
import { useGrpcMetadata, useParcaTheme } from '@parca/components';
|
|
66
|
+
import { Query } from '@parca/parser';
|
|
67
|
+
import useDelayedLoader from '../useDelayedLoader';
|
|
68
|
+
export var useQueryRange = function (client, queryExpression, start, end) {
|
|
69
|
+
var _a = useState(false), isLoading = _a[0], setIsLoading = _a[1];
|
|
70
|
+
var _b = useState(null), error = _b[0], setError = _b[1];
|
|
71
|
+
var _c = useState(null), response = _c[0], setResponse = _c[1];
|
|
72
|
+
var metadata = useGrpcMetadata();
|
|
73
|
+
useEffect(function () {
|
|
74
|
+
void (function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
75
|
+
var response_1, e_1;
|
|
76
|
+
return __generator(this, function (_a) {
|
|
77
|
+
switch (_a.label) {
|
|
78
|
+
case 0:
|
|
79
|
+
setIsLoading(true);
|
|
80
|
+
_a.label = 1;
|
|
81
|
+
case 1:
|
|
82
|
+
_a.trys.push([1, 3, 4, 5]);
|
|
83
|
+
return [4 /*yield*/, client.queryRange({
|
|
84
|
+
query: queryExpression,
|
|
85
|
+
start: Timestamp.fromDate(new Date(start)),
|
|
86
|
+
end: Timestamp.fromDate(new Date(end)),
|
|
87
|
+
limit: 0,
|
|
88
|
+
}, { meta: metadata })];
|
|
89
|
+
case 2:
|
|
90
|
+
response_1 = (_a.sent()).response;
|
|
91
|
+
setResponse(response_1);
|
|
92
|
+
return [3 /*break*/, 5];
|
|
93
|
+
case 3:
|
|
94
|
+
e_1 = _a.sent();
|
|
95
|
+
setError(e_1);
|
|
96
|
+
return [3 /*break*/, 5];
|
|
97
|
+
case 4:
|
|
98
|
+
setIsLoading(false);
|
|
99
|
+
return [7 /*endfinally*/];
|
|
100
|
+
case 5: return [2 /*return*/];
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}); })();
|
|
104
|
+
}, [client, queryExpression, start, end, metadata]);
|
|
105
|
+
return { isLoading: isLoading, error: error, response: response };
|
|
106
|
+
};
|
|
107
|
+
var ProfileMetricsGraph = function (_a) {
|
|
108
|
+
var queryClient = _a.queryClient, queryExpression = _a.queryExpression, profile = _a.profile, from = _a.from, to = _a.to, select = _a.select, setTimeRange = _a.setTimeRange, addLabelMatcher = _a.addLabelMatcher;
|
|
109
|
+
var _b = useQueryRange(queryClient, queryExpression, from, to), isLoading = _b.isLoading, response = _b.response, error = _b.error;
|
|
110
|
+
var isLoaderVisible = useDelayedLoader(isLoading);
|
|
111
|
+
var loader = useParcaTheme().loader;
|
|
112
|
+
if (isLoaderVisible) {
|
|
113
|
+
return _jsx(_Fragment, { children: loader });
|
|
114
|
+
}
|
|
115
|
+
if (error !== null) {
|
|
116
|
+
return (_jsxs("div", __assign({ className: "bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative", role: "alert" }, { children: [_jsx("strong", __assign({ className: "font-bold" }, { children: "Error! " })), _jsx("span", __assign({ className: "block sm:inline" }, { children: error.message }))] })));
|
|
117
|
+
}
|
|
118
|
+
var series = response === null || response === void 0 ? void 0 : response.series;
|
|
119
|
+
if (series !== null && series !== undefined && (series === null || series === void 0 ? void 0 : series.length) > 0) {
|
|
120
|
+
var handleSampleClick = function (timestamp, _value, labels) {
|
|
121
|
+
select(new SingleProfileSelection(Query.parse(queryExpression).profileName(), labels, timestamp));
|
|
122
|
+
};
|
|
123
|
+
return (_jsx("div", __assign({ className: "dark:bg-gray-700 rounded border-gray-300 dark:border-gray-500", style: { borderWidth: 1 } }, { children: _jsx(MetricsGraph, { data: series, from: from, to: to, profile: profile, setTimeRange: setTimeRange, onSampleClick: handleSampleClick, onLabelClick: addLabelMatcher, width: 0, sampleUnit: Query.parse(queryExpression).profileType().sampleUnit }) })));
|
|
124
|
+
}
|
|
125
|
+
return (_jsx("div", __assign({ className: "grid grid-cols-1" }, { children: _jsx("div", __assign({ className: "py-20 flex justify-center" }, { children: _jsx("p", __assign({ className: "m-0" }, { children: "No data found. Try a different query." })) })) })));
|
|
126
|
+
};
|
|
127
|
+
export default ProfileMetricsGraph;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } 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 { useState } from 'react';
|
|
26
|
+
import { usePopper } from 'react-popper';
|
|
27
|
+
import { Button } from '@parca/components';
|
|
28
|
+
var CompareButton = function (_a) {
|
|
29
|
+
var disabled = _a.disabled, onClick = _a.onClick;
|
|
30
|
+
var _b = useState(false), compareHover = _b[0], setCompareHover = _b[1];
|
|
31
|
+
var _c = useState(null), comparePopperReferenceElement = _c[0], setComparePopperReferenceElement = _c[1];
|
|
32
|
+
var _d = useState(null), comparePopperElement = _d[0], setComparePopperElement = _d[1];
|
|
33
|
+
var _e = usePopper(comparePopperReferenceElement, comparePopperElement, {
|
|
34
|
+
placement: 'bottom',
|
|
35
|
+
}), styles = _e.styles, attributes = _e.attributes;
|
|
36
|
+
var compareExplanation = 'Compare two profiles and see the relative difference between them more clearly.';
|
|
37
|
+
if (disabled)
|
|
38
|
+
return _jsx(_Fragment, {});
|
|
39
|
+
return (_jsxs("div", __assign({ ref: setComparePopperReferenceElement }, { children: [_jsx(Button, __assign({ color: "neutral", disabled: disabled, onClick: onClick, onMouseEnter: function () { return setCompareHover(true); }, onMouseLeave: function () { return setCompareHover(false); } }, { children: "Compare" })), compareHover && (_jsx("div", __assign({ ref: setComparePopperElement, style: styles.popper }, attributes.popper, { className: "z-50" }, { children: _jsx("div", __assign({ className: "flex" }, { children: _jsxs("div", __assign({ className: "relative mx-2" }, { children: [_jsx("svg", __assign({ className: "text-black h-1 w-full left-0", x: "0px", y: "0px", viewBox: "0 0 255 127.5" }, { children: _jsx("polygon", { className: "fill-current", points: "0,127.5 127.5,0 255,127.5" }) })), _jsx("div", __assign({ className: "bg-black text-white text-xs rounded py-2 px-3 right-0 w-40" }, { children: compareExplanation }))] })) })) })))] })));
|
|
40
|
+
};
|
|
41
|
+
export default CompareButton;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } 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 { useState } from 'react';
|
|
26
|
+
import { usePopper } from 'react-popper';
|
|
27
|
+
import { Button } from '@parca/components';
|
|
28
|
+
var MergeButton = function (_a) {
|
|
29
|
+
var disabled = _a.disabled, onClick = _a.onClick;
|
|
30
|
+
var _b = useState(false), mergeHover = _b[0], setMergeHover = _b[1];
|
|
31
|
+
var _c = useState(null), mergePopperReferenceElement = _c[0], setMergePopperReferenceElement = _c[1];
|
|
32
|
+
var _d = useState(null), mergePopperElement = _d[0], setMergePopperElement = _d[1];
|
|
33
|
+
var _e = usePopper(mergePopperReferenceElement, mergePopperElement, {
|
|
34
|
+
placement: 'bottom',
|
|
35
|
+
}), styles = _e.styles, attributes = _e.attributes;
|
|
36
|
+
var mergeExplanation = 'Merging allows combining all profile samples of a query into a single report.';
|
|
37
|
+
if (disabled)
|
|
38
|
+
return _jsx(_Fragment, {});
|
|
39
|
+
return (_jsxs("div", __assign({ ref: setMergePopperReferenceElement }, { children: [_jsx(Button, __assign({ color: "neutral", disabled: disabled, onClick: onClick, onMouseEnter: function () { return setMergeHover(true); }, onMouseLeave: function () { return setMergeHover(false); } }, { children: "Merge" })), mergeHover && (_jsx("div", __assign({ ref: setMergePopperElement, style: styles.popper }, attributes.popper, { className: "z-50" }, { children: _jsx("div", __assign({ className: "flex" }, { children: _jsxs("div", __assign({ className: "relative mx-2" }, { children: [_jsx("svg", __assign({ className: "text-black h-1 w-full left-0", x: "0px", y: "0px", viewBox: "0 0 255 127.5" }, { children: _jsx("polygon", { className: "fill-current", points: "0,127.5 127.5,0 255,127.5" }) })), _jsx("div", __assign({ className: "bg-black text-white text-xs rounded py-2 px-3 right-0 w-40 z-50" }, { children: mergeExplanation }))] })) })) })))] })));
|
|
40
|
+
};
|
|
41
|
+
export default MergeButton;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { QueryServiceClient, ProfileTypesResponse } from '@parca/client';
|
|
2
|
+
import { RpcError } from '@protobuf-ts/runtime-rpc';
|
|
3
|
+
import { ProfileSelection } from '..';
|
|
4
|
+
export interface QuerySelection {
|
|
5
|
+
expression: string;
|
|
6
|
+
from: number;
|
|
7
|
+
to: number;
|
|
8
|
+
merge: boolean;
|
|
9
|
+
timeSelection: string;
|
|
10
|
+
}
|
|
11
|
+
interface ProfileSelectorProps {
|
|
12
|
+
queryClient: QueryServiceClient;
|
|
13
|
+
querySelection: QuerySelection;
|
|
14
|
+
selectProfile: (source: ProfileSelection) => void;
|
|
15
|
+
selectQuery: (query: QuerySelection) => void;
|
|
16
|
+
closeProfile: () => void;
|
|
17
|
+
enforcedProfileName: string;
|
|
18
|
+
profileSelection: ProfileSelection | null;
|
|
19
|
+
comparing: boolean;
|
|
20
|
+
onCompareProfile: () => void;
|
|
21
|
+
}
|
|
22
|
+
export interface IProfileTypesResult {
|
|
23
|
+
loading: boolean;
|
|
24
|
+
data?: ProfileTypesResponse;
|
|
25
|
+
error?: RpcError;
|
|
26
|
+
}
|
|
27
|
+
export declare const useProfileTypes: (client: QueryServiceClient) => IProfileTypesResult;
|
|
28
|
+
declare const ProfileSelector: ({ queryClient, querySelection, selectProfile, selectQuery, closeProfile, enforcedProfileName, profileSelection, comparing, onCompareProfile, }: ProfileSelectorProps) => JSX.Element;
|
|
29
|
+
export default ProfileSelector;
|