@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.
Files changed (93) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/Callgraph/Edge/index.d.ts +22 -0
  3. package/dist/Callgraph/Edge/index.js +30 -0
  4. package/dist/Callgraph/Node/index.d.ts +19 -0
  5. package/dist/Callgraph/Node/index.js +37 -0
  6. package/dist/Callgraph/index.d.ts +8 -0
  7. package/dist/Callgraph/index.js +137 -0
  8. package/dist/Callgraph/mockData/index.d.ts +148 -0
  9. package/dist/Callgraph/mockData/index.js +577 -0
  10. package/dist/Callgraph/utils.d.ts +19 -0
  11. package/dist/Callgraph/utils.js +82 -0
  12. package/dist/GraphTooltip/index.d.ts +19 -0
  13. package/dist/GraphTooltip/index.js +119 -0
  14. package/dist/IcicleGraph.d.ts +35 -0
  15. package/dist/IcicleGraph.js +139 -0
  16. package/dist/MatchersInput/index.d.ts +23 -0
  17. package/dist/MatchersInput/index.js +479 -0
  18. package/dist/MetricsCircle/index.d.ts +7 -0
  19. package/dist/MetricsCircle/index.js +18 -0
  20. package/dist/MetricsGraph/index.d.ts +35 -0
  21. package/dist/MetricsGraph/index.js +349 -0
  22. package/dist/MetricsSeries/index.d.ts +11 -0
  23. package/dist/MetricsSeries/index.js +21 -0
  24. package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts +19 -0
  25. package/dist/ProfileExplorer/ProfileExplorerCompare.js +38 -0
  26. package/dist/ProfileExplorer/ProfileExplorerSingle.d.ts +15 -0
  27. package/dist/ProfileExplorer/ProfileExplorerSingle.js +19 -0
  28. package/dist/ProfileExplorer/index.d.ts +9 -0
  29. package/dist/ProfileExplorer/index.js +203 -0
  30. package/dist/ProfileIcicleGraph.d.ts +10 -0
  31. package/dist/ProfileIcicleGraph.js +28 -0
  32. package/dist/ProfileMetricsGraph/index.d.ts +22 -0
  33. package/dist/ProfileMetricsGraph/index.js +127 -0
  34. package/dist/ProfileSVG.module.css +3 -0
  35. package/dist/ProfileSelector/CompareButton.d.ts +5 -0
  36. package/dist/ProfileSelector/CompareButton.js +41 -0
  37. package/dist/ProfileSelector/MergeButton.d.ts +5 -0
  38. package/dist/ProfileSelector/MergeButton.js +41 -0
  39. package/dist/ProfileSelector/index.d.ts +29 -0
  40. package/dist/ProfileSelector/index.js +133 -0
  41. package/dist/ProfileSource.d.ts +88 -0
  42. package/dist/ProfileSource.js +239 -0
  43. package/dist/ProfileTypeSelector/index.d.ts +20 -0
  44. package/dist/ProfileTypeSelector/index.js +138 -0
  45. package/dist/ProfileView.d.ts +39 -0
  46. package/dist/ProfileView.js +111 -0
  47. package/dist/ProfileView.styles.css +3 -0
  48. package/dist/ProfileViewWithData.d.ts +11 -0
  49. package/dist/ProfileViewWithData.js +116 -0
  50. package/dist/TopTable.d.ts +9 -0
  51. package/dist/TopTable.js +140 -0
  52. package/dist/TopTable.styles.css +7 -0
  53. package/dist/components/DiffLegend.d.ts +2 -0
  54. package/dist/components/DiffLegend.js +62 -0
  55. package/dist/components/ProfileShareButton/ResultBox.d.ts +6 -0
  56. package/dist/components/ProfileShareButton/ResultBox.js +46 -0
  57. package/dist/components/ProfileShareButton/index.d.ts +7 -0
  58. package/dist/components/ProfileShareButton/index.js +119 -0
  59. package/dist/index.d.ts +13 -0
  60. package/dist/index.js +64 -0
  61. package/dist/styles.css +1 -0
  62. package/dist/useDelayedLoader.d.ts +5 -0
  63. package/dist/useDelayedLoader.js +33 -0
  64. package/dist/useQuery.d.ts +13 -0
  65. package/dist/useQuery.js +41 -0
  66. package/dist/utils.d.ts +4 -0
  67. package/dist/utils.js +83 -0
  68. package/package.json +12 -8
  69. package/src/Callgraph/Edge/index.tsx +59 -0
  70. package/src/Callgraph/Node/index.tsx +66 -0
  71. package/src/Callgraph/index.tsx +169 -0
  72. package/src/Callgraph/mockData/index.ts +605 -0
  73. package/src/Callgraph/utils.ts +116 -0
  74. package/src/GraphTooltip/index.tsx +245 -0
  75. package/src/IcicleGraph.tsx +3 -3
  76. package/src/MatchersInput/index.tsx +698 -0
  77. package/src/MetricsCircle/index.tsx +28 -0
  78. package/src/MetricsGraph/index.tsx +614 -0
  79. package/src/MetricsSeries/index.tsx +38 -0
  80. package/src/ProfileExplorer/ProfileExplorerCompare.tsx +109 -0
  81. package/src/ProfileExplorer/ProfileExplorerSingle.tsx +72 -0
  82. package/src/ProfileExplorer/index.tsx +377 -0
  83. package/src/ProfileMetricsGraph/index.tsx +143 -0
  84. package/src/ProfileSelector/CompareButton.tsx +72 -0
  85. package/src/ProfileSelector/MergeButton.tsx +72 -0
  86. package/src/ProfileSelector/index.tsx +270 -0
  87. package/src/ProfileTypeSelector/index.tsx +180 -0
  88. package/src/ProfileView.tsx +2 -7
  89. package/src/index.tsx +11 -0
  90. package/src/useQuery.tsx +1 -0
  91. package/tailwind.config.js +8 -0
  92. package/tsconfig.json +7 -3
  93. 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,3 @@
1
+ .ProfileSVG ::selection {
2
+ background: none;
3
+ }
@@ -0,0 +1,5 @@
1
+ declare const CompareButton: ({ disabled, onClick, }: {
2
+ disabled: boolean;
3
+ onClick: () => void;
4
+ }) => JSX.Element;
5
+ 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 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,5 @@
1
+ declare const MergeButton: ({ disabled, onClick, }: {
2
+ disabled: boolean;
3
+ onClick: () => void;
4
+ }) => JSX.Element;
5
+ export default MergeButton;
@@ -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;