@parca/profile 0.16.115 → 0.16.117
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/MetricsGraph/index.d.ts +2 -2
- package/dist/MetricsGraph/index.js +3 -2
- package/dist/ProfileExplorer/index.js +71 -75
- package/dist/ProfileMetricsGraph/index.d.ts +3 -3
- package/dist/ProfileMetricsGraph/index.js +7 -5
- package/dist/ProfileSelector/index.d.ts +2 -1
- package/dist/ProfileSelector/index.js +27 -21
- package/dist/ProfileSource.d.ts +11 -36
- package/dist/ProfileSource.js +30 -125
- package/dist/styles.css +1 -1
- package/package.json +6 -6
- package/src/MetricsGraph/index.tsx +5 -5
- package/src/ProfileExplorer/index.tsx +112 -80
- package/src/ProfileMetricsGraph/index.tsx +9 -8
- package/src/ProfileSelector/index.tsx +35 -22
- package/src/ProfileSource.tsx +62 -164
- package/dist/ProfileSelector/MergeButton.d.ts +0 -6
- package/dist/ProfileSelector/MergeButton.js +0 -41
- package/src/ProfileSelector/MergeButton.tsx +0 -72
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.117 (2023-02-16)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
10
|
+
## 0.16.116 (2023-02-15)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @parca/profile
|
|
13
|
+
|
|
6
14
|
## [0.16.115](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.114...@parca/profile@0.16.115) (2023-02-13)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { DateTimeRange } from '@parca/components';
|
|
3
3
|
import { MetricsSeries as MetricsSeriesPb, Label } from '@parca/client';
|
|
4
|
-
import {
|
|
4
|
+
import { MergedProfileSelection } from '..';
|
|
5
5
|
interface Props {
|
|
6
6
|
data: MetricsSeriesPb[];
|
|
7
7
|
from: number;
|
|
8
8
|
to: number;
|
|
9
|
-
profile:
|
|
9
|
+
profile: MergedProfileSelection | null;
|
|
10
10
|
onSampleClick: (timestamp: number, value: number, labels: Label[]) => void;
|
|
11
11
|
onLabelClick: (labelName: string, labelValue: string) => void;
|
|
12
12
|
setTimeRange: (range: DateTimeRange) => void;
|
|
@@ -28,7 +28,7 @@ import { pointer } from 'd3-selection';
|
|
|
28
28
|
import throttle from 'lodash.throttle';
|
|
29
29
|
import { DateTimeRange, useKeyDown } from '@parca/components';
|
|
30
30
|
import { useContainerDimensions } from '@parca/dynamicsize';
|
|
31
|
-
import { formatForTimespan } from '@parca/functions
|
|
31
|
+
import { formatForTimespan } from '@parca/functions';
|
|
32
32
|
import { valueFormatter, formatDate, sanitizeHighlightedValues } from '@parca/functions';
|
|
33
33
|
import MetricsSeries from '../MetricsSeries';
|
|
34
34
|
import MetricsCircle from '../MetricsCircle';
|
|
@@ -56,7 +56,8 @@ export var RawMetricsGraph = function (_a) {
|
|
|
56
56
|
var _e = useState([0, 0]), pos = _e[0], setPos = _e[1];
|
|
57
57
|
var metricPointRef = useRef(null);
|
|
58
58
|
var isShiftDown = useKeyDown().isShiftDown;
|
|
59
|
-
|
|
59
|
+
// the time of the selected point is the start of the merge window
|
|
60
|
+
var time = parseFloat(profile === null || profile === void 0 ? void 0 : profile.HistoryParams().merge_from);
|
|
60
61
|
if (width === undefined || width == null) {
|
|
61
62
|
width = 0;
|
|
62
63
|
}
|
|
@@ -9,7 +9,7 @@ var __assign = (this && this.__assign) || function () {
|
|
|
9
9
|
};
|
|
10
10
|
return __assign.apply(this, arguments);
|
|
11
11
|
};
|
|
12
|
-
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
13
|
// Copyright 2022 The Parca Authors
|
|
14
14
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
15
15
|
// you may not use this file except in compliance with the License.
|
|
@@ -22,6 +22,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
|
22
22
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
23
23
|
// See the License for the specific language governing permissions and
|
|
24
24
|
// limitations under the License.
|
|
25
|
+
import { useEffect, useState } from 'react';
|
|
25
26
|
import { useProfileTypes } from '../ProfileSelector';
|
|
26
27
|
import { ProfileSelectionFromParams, SuffixParams } from '..';
|
|
27
28
|
import ProfileExplorerSingle from './ProfileExplorerSingle';
|
|
@@ -62,11 +63,45 @@ var swapQueryParameters = function (o) {
|
|
|
62
63
|
var ProfileExplorerApp = function (_a) {
|
|
63
64
|
var _b, _c;
|
|
64
65
|
var queryClient = _a.queryClient, queryParams = _a.queryParams, navigateTo = _a.navigateTo;
|
|
65
|
-
var _d = useProfileTypes(queryClient), profileTypesLoading = _d.loading, profileTypesData = _d.data;
|
|
66
|
-
var _e = useParcaContext(), loader = _e.loader, noDataPrompt = _e.noDataPrompt;
|
|
66
|
+
var _d = useProfileTypes(queryClient), profileTypesLoading = _d.loading, profileTypesData = _d.data, profileTypesError = _d.error;
|
|
67
|
+
var _e = useParcaContext(), loader = _e.loader, noDataPrompt = _e.noDataPrompt, onError = _e.onError;
|
|
68
|
+
useEffect(function () {
|
|
69
|
+
if (profileTypesError !== undefined && profileTypesError !== null) {
|
|
70
|
+
onError === null || onError === void 0 ? void 0 : onError(profileTypesError, 'ProfileExplorer');
|
|
71
|
+
}
|
|
72
|
+
}, [profileTypesError, onError]);
|
|
67
73
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
68
|
-
var from_a = queryParams.from_a, to_a = queryParams.to_a,
|
|
74
|
+
var from_a = queryParams.from_a, to_a = queryParams.to_a, profile_name_a = queryParams.profile_name_a, labels_a = queryParams.labels_a, merge_from_a = queryParams.merge_from_a, merge_to_a = queryParams.merge_to_a, time_selection_a = queryParams.time_selection_a, compare_a = queryParams.compare_a, from_b = queryParams.from_b, to_b = queryParams.to_b, profile_name_b = queryParams.profile_name_b, labels_b = queryParams.labels_b, merge_from_b = queryParams.merge_from_b, merge_to_b = queryParams.merge_to_b, time_selection_b = queryParams.time_selection_b, compare_b = queryParams.compare_b, filter_by_function = queryParams.filter_by_function, dashboard_items = queryParams.dashboard_items;
|
|
69
75
|
/* eslint-enable @typescript-eslint/naming-convention */
|
|
76
|
+
var _f = useState(null), profileA = _f[0], setProfileA = _f[1];
|
|
77
|
+
var _g = useState(null), profileB = _g[0], setProfileB = _g[1];
|
|
78
|
+
useEffect(function () {
|
|
79
|
+
var _a;
|
|
80
|
+
var mergeFrom = merge_from_a !== null && merge_from_a !== void 0 ? merge_from_a : undefined;
|
|
81
|
+
var mergeTo = merge_to_a !== null && merge_to_a !== void 0 ? merge_to_a : undefined;
|
|
82
|
+
var labels = (_a = labels_a) !== null && _a !== void 0 ? _a : [''];
|
|
83
|
+
var profileA = ProfileSelectionFromParams(expression_a, from_a, to_a, mergeFrom, mergeTo, labels, filter_by_function);
|
|
84
|
+
setProfileA(profileA);
|
|
85
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
86
|
+
}, [merge_from_a, merge_to_a]);
|
|
87
|
+
useEffect(function () {
|
|
88
|
+
var _a;
|
|
89
|
+
var mergeFrom = merge_from_b !== null && merge_from_b !== void 0 ? merge_from_b : undefined;
|
|
90
|
+
var mergeTo = merge_to_b !== null && merge_to_b !== void 0 ? merge_to_b : undefined;
|
|
91
|
+
var labels = (_a = labels_b) !== null && _a !== void 0 ? _a : [''];
|
|
92
|
+
var profileB = ProfileSelectionFromParams(expression_b, from_b, to_b, mergeFrom, mergeTo, labels, filter_by_function);
|
|
93
|
+
setProfileB(profileB);
|
|
94
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
95
|
+
}, [merge_from_b, merge_to_b]);
|
|
96
|
+
if (profileTypesLoading) {
|
|
97
|
+
return _jsx(_Fragment, { children: loader });
|
|
98
|
+
}
|
|
99
|
+
if ((profileTypesData === null || profileTypesData === void 0 ? void 0 : profileTypesData.types.length) === 0) {
|
|
100
|
+
return _jsx(_Fragment, { children: noDataPrompt });
|
|
101
|
+
}
|
|
102
|
+
if (profileTypesError !== undefined && profileTypesError !== null) {
|
|
103
|
+
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: profileTypesError.message }))] })));
|
|
104
|
+
}
|
|
70
105
|
var sanitizedRange = sanitizeDateRange(time_selection_a, from_a, to_a);
|
|
71
106
|
time_selection_a = sanitizedRange.time_selection_a;
|
|
72
107
|
from_a = sanitizedRange.from_a;
|
|
@@ -90,32 +125,20 @@ var ProfileExplorerApp = function (_a) {
|
|
|
90
125
|
var selectProfileB = function (p) {
|
|
91
126
|
return selectProfile(p, '_b');
|
|
92
127
|
};
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
128
|
+
var queryA = {
|
|
129
|
+
expression: expression_a,
|
|
130
|
+
from: parseInt(from_a),
|
|
131
|
+
to: parseInt(to_a),
|
|
132
|
+
timeSelection: time_selection_a,
|
|
133
|
+
profile_name: profile_name_a,
|
|
134
|
+
};
|
|
99
135
|
// Show the SingleProfileExplorer when not comparing
|
|
100
136
|
if (compare_a !== 'true' && compare_b !== 'true') {
|
|
101
|
-
var query_1 = {
|
|
102
|
-
expression: expression_a,
|
|
103
|
-
from: parseInt(from_a),
|
|
104
|
-
to: parseInt(to_a),
|
|
105
|
-
merge: merge_a === 'true',
|
|
106
|
-
profile_name: profile_name_a,
|
|
107
|
-
timeSelection: time_selection_a,
|
|
108
|
-
};
|
|
109
|
-
var profile_1 = ProfileSelectionFromParams(expression_a, from_a, to_a, merge_a, labels_a, profile_name_a, time_a, filter_by_function);
|
|
110
137
|
var selectQuery = function (q) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
merge_a: q.merge,
|
|
116
|
-
time_selection_a: q.timeSelection,
|
|
117
|
-
dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS,
|
|
118
|
-
}));
|
|
138
|
+
var mergeParams = q.mergeFrom !== undefined && q.mergeTo !== undefined
|
|
139
|
+
? { merge_from_a: q.mergeFrom, merge_to_a: q.mergeTo }
|
|
140
|
+
: {};
|
|
141
|
+
return navigateTo('/', __assign(__assign({}, filterSuffix(queryParams, '_a')), __assign({ expression_a: encodeURIComponent(q.expression), from_a: q.from.toString(), to_a: q.to.toString(), time_selection_a: q.timeSelection, dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS }, mergeParams)));
|
|
119
142
|
};
|
|
120
143
|
var selectProfile_1 = function (p) {
|
|
121
144
|
queryParams.expression_a = encodeURIComponent(queryParams.expression_a);
|
|
@@ -124,70 +147,43 @@ var ProfileExplorerApp = function (_a) {
|
|
|
124
147
|
var compareProfile = function () {
|
|
125
148
|
var compareQuery = {
|
|
126
149
|
compare_a: 'true',
|
|
127
|
-
expression_a: encodeURIComponent(
|
|
128
|
-
from_a:
|
|
129
|
-
to_a:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
profile_name_a: query_1.profile_name,
|
|
150
|
+
expression_a: encodeURIComponent(queryA.expression),
|
|
151
|
+
from_a: queryA.from.toString(),
|
|
152
|
+
to_a: queryA.to.toString(),
|
|
153
|
+
time_selection_a: queryA.timeSelection,
|
|
154
|
+
profile_name_a: queryA.profile_name,
|
|
133
155
|
compare_b: 'true',
|
|
134
|
-
expression_b: encodeURIComponent(
|
|
135
|
-
from_b:
|
|
136
|
-
to_b:
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
profile_name_b: query_1.profile_name,
|
|
156
|
+
expression_b: encodeURIComponent(queryA.expression),
|
|
157
|
+
from_b: queryA.from.toString(),
|
|
158
|
+
to_b: queryA.to.toString(),
|
|
159
|
+
time_selection_b: queryA.timeSelection,
|
|
160
|
+
profile_name_b: queryA.profile_name,
|
|
140
161
|
};
|
|
141
|
-
if (
|
|
142
|
-
compareQuery = __assign(__assign({}, SuffixParams(
|
|
162
|
+
if (profileA != null) {
|
|
163
|
+
compareQuery = __assign(__assign({}, SuffixParams(profileA.HistoryParams(), '_a')), compareQuery);
|
|
143
164
|
}
|
|
144
165
|
void navigateTo('/', __assign(__assign({}, compareQuery), { search_string: '', dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS }));
|
|
145
166
|
};
|
|
146
|
-
return (_jsx(ProfileExplorerSingle, { queryClient: queryClient, query:
|
|
167
|
+
return (_jsx(ProfileExplorerSingle, { queryClient: queryClient, query: queryA, profile: profileA, selectQuery: selectQuery, selectProfile: selectProfile_1, compareProfile: compareProfile, navigateTo: navigateTo }));
|
|
147
168
|
}
|
|
148
|
-
var queryA = {
|
|
149
|
-
expression: expression_a,
|
|
150
|
-
from: parseInt(from_a),
|
|
151
|
-
to: parseInt(to_a),
|
|
152
|
-
merge: merge_a === 'true',
|
|
153
|
-
timeSelection: time_selection_a,
|
|
154
|
-
profile_name: profile_name_a,
|
|
155
|
-
};
|
|
156
169
|
var queryB = {
|
|
157
170
|
expression: expression_b,
|
|
158
171
|
from: parseInt(from_b),
|
|
159
172
|
to: parseInt(to_b),
|
|
160
|
-
merge: merge_b === 'true',
|
|
161
173
|
timeSelection: time_selection_b,
|
|
162
174
|
profile_name: profile_name_b,
|
|
163
175
|
};
|
|
164
|
-
var profileA = ProfileSelectionFromParams(expression_a, from_a, to_a, merge_a, labels_a, profile_name_a, time_a);
|
|
165
|
-
var profileB = ProfileSelectionFromParams(expression_b, from_b, to_b, merge_b, labels_b, profile_name_b, time_b);
|
|
166
176
|
var selectQueryA = function (q) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
from_a: q.from.toString(),
|
|
172
|
-
to_a: q.to.toString(),
|
|
173
|
-
merge_a: q.merge,
|
|
174
|
-
time_selection_a: q.timeSelection,
|
|
175
|
-
filter_by_function: filter_by_function !== null && filter_by_function !== void 0 ? filter_by_function : '',
|
|
176
|
-
dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS,
|
|
177
|
-
}));
|
|
177
|
+
var mergeParams = q.mergeFrom !== undefined && q.mergeTo !== undefined
|
|
178
|
+
? { merge_from_a: q.mergeFrom, merge_to_a: q.mergeTo }
|
|
179
|
+
: {};
|
|
180
|
+
return navigateTo('/', __assign(__assign({}, filterSuffix(queryParams, '_a')), __assign({ compare_a: 'true', expression_a: encodeURIComponent(q.expression), expression_b: encodeURIComponent(expression_b), from_a: q.from.toString(), to_a: q.to.toString(), time_selection_a: q.timeSelection, filter_by_function: filter_by_function !== null && filter_by_function !== void 0 ? filter_by_function : '', dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS }, mergeParams)));
|
|
178
181
|
};
|
|
179
182
|
var selectQueryB = function (q) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
from_b: q.from.toString(),
|
|
185
|
-
to_b: q.to.toString(),
|
|
186
|
-
merge_b: q.merge,
|
|
187
|
-
time_selection_b: q.timeSelection,
|
|
188
|
-
filter_by_function: filter_by_function !== null && filter_by_function !== void 0 ? filter_by_function : '',
|
|
189
|
-
dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS,
|
|
190
|
-
}));
|
|
183
|
+
var mergeParams = q.mergeFrom !== undefined && q.mergeTo !== undefined
|
|
184
|
+
? { merge_from_b: q.mergeFrom, merge_to_b: q.mergeTo }
|
|
185
|
+
: {};
|
|
186
|
+
return navigateTo('/', __assign(__assign({}, filterSuffix(queryParams, '_b')), __assign({ compare_b: 'true', expression_b: encodeURIComponent(q.expression), expression_a: encodeURIComponent(expression_a), from_b: q.from.toString(), to_b: q.to.toString(), time_selection_b: q.timeSelection, filter_by_function: filter_by_function !== null && filter_by_function !== void 0 ? filter_by_function : '', dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS }, mergeParams)));
|
|
191
187
|
};
|
|
192
188
|
var closeProfile = function (card) {
|
|
193
189
|
var newQueryParameters = queryParams;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { ProfileSelection } from '..';
|
|
3
|
-
import { QueryServiceClient, QueryRangeResponse } from '@parca/client';
|
|
3
|
+
import { QueryServiceClient, QueryRangeResponse, Label } from '@parca/client';
|
|
4
4
|
import { RpcError } from '@protobuf-ts/runtime-rpc';
|
|
5
5
|
import { DateTimeRange } from '@parca/components';
|
|
6
6
|
interface ProfileMetricsGraphProps {
|
|
@@ -9,9 +9,9 @@ interface ProfileMetricsGraphProps {
|
|
|
9
9
|
profile: ProfileSelection | null;
|
|
10
10
|
from: number;
|
|
11
11
|
to: number;
|
|
12
|
-
select: (source: ProfileSelection) => void;
|
|
13
12
|
setTimeRange: (range: DateTimeRange) => void;
|
|
14
13
|
addLabelMatcher: (key: string, value: string) => void;
|
|
14
|
+
onPointClick: (timestamp: number, labels: Label[], queryExpression: string) => void;
|
|
15
15
|
}
|
|
16
16
|
export interface IQueryRangeState {
|
|
17
17
|
response: QueryRangeResponse | null;
|
|
@@ -19,5 +19,5 @@ export interface IQueryRangeState {
|
|
|
19
19
|
error: RpcError | null;
|
|
20
20
|
}
|
|
21
21
|
export declare const useQueryRange: (client: QueryServiceClient, queryExpression: string, start: number, end: number) => IQueryRangeState;
|
|
22
|
-
declare const ProfileMetricsGraph: ({ queryClient, queryExpression, profile, from, to,
|
|
22
|
+
declare const ProfileMetricsGraph: ({ queryClient, queryExpression, profile, from, to, setTimeRange, addLabelMatcher, onPointClick, }: ProfileMetricsGraphProps) => JSX.Element;
|
|
23
23
|
export default ProfileMetricsGraph;
|
|
@@ -60,11 +60,11 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
60
60
|
// limitations under the License.
|
|
61
61
|
import { useState, useEffect } from 'react';
|
|
62
62
|
import MetricsGraph from '../MetricsGraph';
|
|
63
|
-
import {
|
|
64
|
-
import { Timestamp } from '@parca/client';
|
|
63
|
+
import { Timestamp, Duration } from '@parca/client';
|
|
65
64
|
import { useGrpcMetadata, useParcaContext } from '@parca/components';
|
|
66
65
|
import { Query } from '@parca/parser';
|
|
67
66
|
import useDelayedLoader from '../useDelayedLoader';
|
|
67
|
+
import { getStepDuration } from '@parca/functions';
|
|
68
68
|
export var useQueryRange = function (client, queryExpression, start, end) {
|
|
69
69
|
var _a = useState({
|
|
70
70
|
response: null,
|
|
@@ -74,17 +74,19 @@ export var useQueryRange = function (client, queryExpression, start, end) {
|
|
|
74
74
|
var metadata = useGrpcMetadata();
|
|
75
75
|
useEffect(function () {
|
|
76
76
|
void (function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
77
|
-
var call;
|
|
77
|
+
var stepDuration, call;
|
|
78
78
|
return __generator(this, function (_a) {
|
|
79
79
|
setState({
|
|
80
80
|
response: null,
|
|
81
81
|
isLoading: true,
|
|
82
82
|
error: null,
|
|
83
83
|
});
|
|
84
|
+
stepDuration = getStepDuration(start, end);
|
|
84
85
|
call = client.queryRange({
|
|
85
86
|
query: queryExpression,
|
|
86
87
|
start: Timestamp.fromDate(new Date(start)),
|
|
87
88
|
end: Timestamp.fromDate(new Date(end)),
|
|
89
|
+
step: Duration.create(stepDuration),
|
|
88
90
|
limit: 0,
|
|
89
91
|
}, { meta: metadata });
|
|
90
92
|
call.response
|
|
@@ -97,7 +99,7 @@ export var useQueryRange = function (client, queryExpression, start, end) {
|
|
|
97
99
|
return state;
|
|
98
100
|
};
|
|
99
101
|
var ProfileMetricsGraph = function (_a) {
|
|
100
|
-
var queryClient = _a.queryClient, queryExpression = _a.queryExpression, profile = _a.profile, from = _a.from, to = _a.to,
|
|
102
|
+
var queryClient = _a.queryClient, queryExpression = _a.queryExpression, profile = _a.profile, from = _a.from, to = _a.to, setTimeRange = _a.setTimeRange, addLabelMatcher = _a.addLabelMatcher, onPointClick = _a.onPointClick;
|
|
101
103
|
var _b = useQueryRange(queryClient, queryExpression, from, to), isLoading = _b.isLoading, response = _b.response, error = _b.error;
|
|
102
104
|
var isLoaderVisible = useDelayedLoader(isLoading);
|
|
103
105
|
var _c = useParcaContext(), loader = _c.loader, onError = _c.onError;
|
|
@@ -115,7 +117,7 @@ var ProfileMetricsGraph = function (_a) {
|
|
|
115
117
|
var series = response === null || response === void 0 ? void 0 : response.series;
|
|
116
118
|
if (series !== null && series !== undefined && (series === null || series === void 0 ? void 0 : series.length) > 0) {
|
|
117
119
|
var handleSampleClick = function (timestamp, _value, labels) {
|
|
118
|
-
|
|
120
|
+
onPointClick(timestamp, labels, queryExpression);
|
|
119
121
|
};
|
|
120
122
|
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 }) })));
|
|
121
123
|
}
|
|
@@ -23,10 +23,11 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
23
23
|
// See the License for the specific language governing permissions and
|
|
24
24
|
// limitations under the License.
|
|
25
25
|
import { Query } from '@parca/parser';
|
|
26
|
+
import { getStepDuration, getStepDurationInMilliseconds } from '@parca/functions';
|
|
27
|
+
import { MergedProfileSelection } from '..';
|
|
26
28
|
import { useEffect, useState } from 'react';
|
|
27
29
|
import ProfileMetricsGraph from '../ProfileMetricsGraph';
|
|
28
30
|
import MatchersInput from '../MatchersInput/index';
|
|
29
|
-
import MergeButton from './MergeButton';
|
|
30
31
|
import CompareButton from './CompareButton';
|
|
31
32
|
import { Card, DateTimeRangePicker, DateTimeRange, Button, ButtonGroup, useGrpcMetadata, } from '@parca/components';
|
|
32
33
|
import { CloseIcon } from '@parca/icons';
|
|
@@ -70,17 +71,21 @@ var ProfileSelector = function (_a) {
|
|
|
70
71
|
};
|
|
71
72
|
var query = enforcedProfileName !== '' ? enforcedProfileNameQuery() : Query.parse(queryExpressionString);
|
|
72
73
|
var selectedProfileName = query.profileName();
|
|
73
|
-
var setNewQueryExpression = function (expr
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
var setNewQueryExpression = function (expr) {
|
|
75
|
+
var query = enforcedProfileName !== '' ? enforcedProfileNameQuery() : Query.parse(expr);
|
|
76
|
+
var delta = query.profileType().delta;
|
|
77
|
+
var from = timeRangeSelection.getFromMs();
|
|
78
|
+
var to = timeRangeSelection.getToMs();
|
|
79
|
+
var mergeParams = delta
|
|
80
|
+
? {
|
|
81
|
+
mergeFrom: from,
|
|
82
|
+
mergeTo: to,
|
|
83
|
+
}
|
|
84
|
+
: {};
|
|
85
|
+
selectQuery(__assign({ expression: expr, from: from, to: to, timeSelection: timeRangeSelection.getRangeKey() }, mergeParams));
|
|
81
86
|
};
|
|
82
87
|
var setQueryExpression = function () {
|
|
83
|
-
setNewQueryExpression(query.toString()
|
|
88
|
+
setNewQueryExpression(query.toString());
|
|
84
89
|
};
|
|
85
90
|
var addLabelMatcher = function (key, value) {
|
|
86
91
|
// When a user clicks on a label on the metrics graph tooltip,
|
|
@@ -88,12 +93,9 @@ var ProfileSelector = function (_a) {
|
|
|
88
93
|
var newValue = value.includes('\\') ? value.replaceAll('\\', '\\\\') : value;
|
|
89
94
|
var _a = Query.parse(queryExpressionString).setMatcher(key, newValue), newQuery = _a[0], changed = _a[1];
|
|
90
95
|
if (changed) {
|
|
91
|
-
setNewQueryExpression(newQuery.toString()
|
|
96
|
+
setNewQueryExpression(newQuery.toString());
|
|
92
97
|
}
|
|
93
98
|
};
|
|
94
|
-
var setMergedSelection = function () {
|
|
95
|
-
setNewQueryExpression(queryExpressionString, true);
|
|
96
|
-
};
|
|
97
99
|
var setMatchersString = function (matchers) {
|
|
98
100
|
var newExpressionString = "".concat(selectedProfileName, "{").concat(matchers, "}");
|
|
99
101
|
setQueryExpressionString(newExpressionString);
|
|
@@ -112,24 +114,28 @@ var ProfileSelector = function (_a) {
|
|
|
112
114
|
var searchDisabled = queryExpressionString === undefined ||
|
|
113
115
|
queryExpressionString === '' ||
|
|
114
116
|
queryExpressionString === '{}';
|
|
115
|
-
var mergeDisabled = selectedProfileName === '' || querySelection.expression === undefined;
|
|
116
117
|
var compareDisabled = selectedProfileName === '' || querySelection.expression === undefined;
|
|
117
|
-
return (_jsxs(Card, { children: [_jsxs(Card.Header, __assign({ className: "flex space-x-2" }, { children: [_jsxs("div", __assign({ className: "flex flex-wrap w-full justify-start space-x-2 space-y-1" }, { children: [_jsx("div", __assign({ className: "ml-2 mt-1" }, { children: _jsx(ProfileTypeSelector, { profileTypesData: profileTypesData, loading: profileTypesLoading, selectedKey: selectedProfileName, onSelection: setProfileName, error: error }) })), _jsx("div", __assign({ className: "w-full flex-1" }, { children: _jsx(MatchersInput, { queryClient: queryClient, setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query }) })), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection }), _jsxs(ButtonGroup, { children: [!searchDisabled && (
|
|
118
|
+
return (_jsxs(Card, { children: [_jsxs(Card.Header, __assign({ className: "flex space-x-2" }, { children: [_jsxs("div", __assign({ className: "flex flex-wrap w-full justify-start space-x-2 space-y-1" }, { children: [_jsx("div", __assign({ className: "ml-2 mt-1" }, { children: _jsx(ProfileTypeSelector, { profileTypesData: profileTypesData, loading: profileTypesLoading, selectedKey: selectedProfileName, onSelection: setProfileName, error: error }) })), _jsx("div", __assign({ className: "w-full flex-1" }, { children: _jsx(MatchersInput, { queryClient: queryClient, setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query }) })), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection }), _jsxs(ButtonGroup, { children: [!searchDisabled && (_jsx(_Fragment, { children: !comparing && (_jsx(CompareButton, { disabled: compareDisabled, onClick: handleCompareClick })) })), _jsx(Button, __assign({ disabled: searchDisabled, onClick: function (e) {
|
|
118
119
|
e.preventDefault();
|
|
119
120
|
setQueryExpression();
|
|
120
|
-
} }, { children: "Search" }))] })] })), _jsx("div", { children: comparing && (_jsx("button", __assign({ type: "button", onClick: function () { return closeProfile(); } }, { children: _jsx(CloseIcon, {}) }))) })] })),
|
|
121
|
+
} }, { children: "Search" }))] })] })), _jsx("div", { children: comparing && (_jsx("button", __assign({ type: "button", onClick: function () { return closeProfile(); } }, { children: _jsx(CloseIcon, {}) }))) })] })), _jsx(Card.Body, { children: querySelection.expression !== undefined &&
|
|
121
122
|
querySelection.expression.length > 0 &&
|
|
122
123
|
querySelection.from !== undefined &&
|
|
123
|
-
querySelection.to !== undefined
|
|
124
|
-
(profileSelection == null || profileSelection.Type() !== 'merge') ? (_jsx(ProfileMetricsGraph, { queryClient: queryClient, queryExpression: querySelection.expression, from: querySelection.from, to: querySelection.to, select: selectProfile, profile: profileSelection, setTimeRange: function (range) {
|
|
124
|
+
querySelection.to !== undefined ? (_jsx(ProfileMetricsGraph, { queryClient: queryClient, queryExpression: querySelection.expression, from: querySelection.from, to: querySelection.to, profile: profileSelection, setTimeRange: function (range) {
|
|
125
125
|
setTimeRangeSelection(range);
|
|
126
126
|
selectQuery({
|
|
127
127
|
expression: queryExpressionString,
|
|
128
128
|
from: range.getFromMs(),
|
|
129
129
|
to: range.getToMs(),
|
|
130
|
-
merge: false,
|
|
131
130
|
timeSelection: range.getRangeKey(),
|
|
132
131
|
});
|
|
133
|
-
}, addLabelMatcher: addLabelMatcher
|
|
132
|
+
}, addLabelMatcher: addLabelMatcher, onPointClick: function (timestamp, labels, queryExpression) {
|
|
133
|
+
var stepDuration = getStepDuration(querySelection.from, querySelection.to);
|
|
134
|
+
var stepDurationInMilliseconds = getStepDurationInMilliseconds(stepDuration);
|
|
135
|
+
var isDeltaType = Query.parse(queryExpression).profileType().delta;
|
|
136
|
+
var mergeFrom = timestamp;
|
|
137
|
+
var mergeTo = isDeltaType ? mergeFrom + stepDurationInMilliseconds : mergeFrom;
|
|
138
|
+
selectProfile(new MergedProfileSelection(mergeFrom, mergeTo, labels, queryExpression));
|
|
139
|
+
} })) : (_jsx(_Fragment, { children: profileSelection == null && (_jsx("div", __assign({ className: "my-20 text-center" }, { children: _jsx("p", { children: "Run a query, and the result will be displayed here." }) }))) })) })] }));
|
|
134
140
|
};
|
|
135
141
|
export default ProfileSelector;
|
package/dist/ProfileSource.d.ts
CHANGED
|
@@ -27,48 +27,21 @@ export declare function SuffixParams(params: {
|
|
|
27
27
|
[key: string]: any;
|
|
28
28
|
};
|
|
29
29
|
export declare function ParseLabels(labels: string[]): Label[];
|
|
30
|
-
export declare function ProfileSelectionFromParams(expression: string | undefined, from: string | undefined, to: string | undefined,
|
|
31
|
-
export declare class SingleProfileSelection implements ProfileSelection {
|
|
32
|
-
profileName: string;
|
|
33
|
-
labels: Label[];
|
|
34
|
-
time: number;
|
|
35
|
-
filterQuery: string | undefined;
|
|
36
|
-
constructor(profileName: string, labels: Label[], time: number, filterQuery?: string);
|
|
37
|
-
ProfileName(): string;
|
|
38
|
-
HistoryParams(): {
|
|
39
|
-
[key: string]: any;
|
|
40
|
-
};
|
|
41
|
-
Type(): string;
|
|
42
|
-
ProfileSource(): ProfileSource;
|
|
43
|
-
}
|
|
30
|
+
export declare function ProfileSelectionFromParams(expression: string | undefined, from: string | undefined, to: string | undefined, mergeFrom: string | undefined, mergeTo: string | undefined, labels: string[], filterQuery?: string): ProfileSelection | null;
|
|
44
31
|
export declare class MergedProfileSelection implements ProfileSelection {
|
|
45
|
-
|
|
46
|
-
|
|
32
|
+
mergeFrom: number;
|
|
33
|
+
mergeTo: number;
|
|
47
34
|
query: string;
|
|
48
35
|
filterQuery: string | undefined;
|
|
49
|
-
|
|
36
|
+
labels: Label[];
|
|
37
|
+
constructor(mergeFrom: number, mergeTo: number, labels: Label[], query: string, filterQuery?: string);
|
|
50
38
|
ProfileName(): string;
|
|
51
39
|
HistoryParams(): {
|
|
52
|
-
[key: string]:
|
|
40
|
+
[key: string]: any;
|
|
53
41
|
};
|
|
54
42
|
Type(): string;
|
|
55
43
|
ProfileSource(): ProfileSource;
|
|
56
44
|
}
|
|
57
|
-
export declare class SingleProfileSource implements ProfileSource {
|
|
58
|
-
profName: string;
|
|
59
|
-
labels: Label[];
|
|
60
|
-
time: number;
|
|
61
|
-
filterQuery: string | undefined;
|
|
62
|
-
constructor(profileName: string, labels: Label[], time: number, filterQuery?: string);
|
|
63
|
-
query(): string;
|
|
64
|
-
DiffSelection(): ProfileDiffSelection;
|
|
65
|
-
QueryRequest(): QueryRequest;
|
|
66
|
-
ProfileType(): ProfileType;
|
|
67
|
-
profileName(): string;
|
|
68
|
-
Describe(): JSX.Element;
|
|
69
|
-
stringLabels(): string[];
|
|
70
|
-
toString(): string;
|
|
71
|
-
}
|
|
72
45
|
export declare class ProfileDiffSource implements ProfileSource {
|
|
73
46
|
a: ProfileSource;
|
|
74
47
|
b: ProfileSource;
|
|
@@ -81,14 +54,16 @@ export declare class ProfileDiffSource implements ProfileSource {
|
|
|
81
54
|
toString(): string;
|
|
82
55
|
}
|
|
83
56
|
export declare class MergedProfileSource implements ProfileSource {
|
|
84
|
-
|
|
85
|
-
|
|
57
|
+
mergeFrom: number;
|
|
58
|
+
mergeTo: number;
|
|
59
|
+
labels: Label[];
|
|
86
60
|
query: string;
|
|
87
61
|
filterQuery: string | undefined;
|
|
88
|
-
constructor(
|
|
62
|
+
constructor(mergeFrom: number, mergeTo: number, labels: Label[], query: string, filterQuery?: string);
|
|
89
63
|
DiffSelection(): ProfileDiffSelection;
|
|
90
64
|
QueryRequest(): QueryRequest;
|
|
91
65
|
ProfileType(): ProfileType;
|
|
92
66
|
Describe(): JSX.Element;
|
|
67
|
+
stringLabels(): string[];
|
|
93
68
|
toString(): string;
|
|
94
69
|
}
|