@parca/profile 0.16.398 → 0.16.399
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
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
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.399](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.398...@parca/profile@0.16.399) (2024-07-02)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
6
10
|
## [0.16.398](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.397...@parca/profile@0.16.398) (2024-07-01)
|
|
7
11
|
|
|
8
12
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -12,6 +12,7 @@ interface ProfileMetricsGraphProps {
|
|
|
12
12
|
profile: ProfileSelection | null;
|
|
13
13
|
from: number;
|
|
14
14
|
to: number;
|
|
15
|
+
timeRange: DateTimeRange;
|
|
15
16
|
setTimeRange: (range: DateTimeRange) => void;
|
|
16
17
|
addLabelMatcher: (labels: {
|
|
17
18
|
key: string;
|
|
@@ -26,8 +27,9 @@ interface ProfileMetricsGraphProps {
|
|
|
26
27
|
export interface IQueryRangeState {
|
|
27
28
|
response: QueryRangeResponse | null;
|
|
28
29
|
isLoading: boolean;
|
|
30
|
+
isRefreshing?: boolean;
|
|
29
31
|
error: RpcError | null;
|
|
30
32
|
}
|
|
31
|
-
export declare const useQueryRange: (client: QueryServiceClient, queryExpression: string, start: number, end: number, sumBy?: string[], skip?: boolean) => IQueryRangeState;
|
|
32
|
-
declare const ProfileMetricsGraph: ({ queryClient, queryExpression, profile, from, to, setTimeRange, addLabelMatcher, onPointClick, comparing, }: ProfileMetricsGraphProps) => JSX.Element;
|
|
33
|
+
export declare const useQueryRange: (client: QueryServiceClient, queryExpression: string, start: number, end: number, timeRange: DateTimeRange, sumBy?: string[], skip?: boolean) => IQueryRangeState;
|
|
34
|
+
declare const ProfileMetricsGraph: ({ queryClient, queryExpression, profile, from, to, setTimeRange, addLabelMatcher, onPointClick, comparing, timeRange, }: ProfileMetricsGraphProps) => JSX.Element;
|
|
33
35
|
export default ProfileMetricsGraph;
|
|
@@ -11,7 +11,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
11
11
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
// See the License for the specific language governing permissions and
|
|
13
13
|
// limitations under the License.
|
|
14
|
-
import { useEffect, useState } from 'react';
|
|
14
|
+
import { useEffect, useRef, useState } from 'react';
|
|
15
15
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
16
16
|
import { Duration, Timestamp } from '@parca/client';
|
|
17
17
|
import { MetricsGraphSkeleton, useGrpcMetadata, useParcaContext, } from '@parca/components';
|
|
@@ -19,7 +19,6 @@ import { Query } from '@parca/parser';
|
|
|
19
19
|
import { capitalizeOnlyFirstLetter, getStepDuration } from '@parca/utilities';
|
|
20
20
|
import MetricsGraph from '../MetricsGraph';
|
|
21
21
|
import { useMetricsGraphDimensions } from '../MetricsGraph/useMetricsGraphDimensions';
|
|
22
|
-
import useDelayedLoader from '../useDelayedLoader';
|
|
23
22
|
const ErrorContent = ({ errorMessage }) => {
|
|
24
23
|
return (_jsx("div", { className: "relative rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700", role: "alert", children: _jsx("span", { className: "block sm:inline", children: errorMessage }) }));
|
|
25
24
|
};
|
|
@@ -27,7 +26,8 @@ export const ProfileMetricsEmptyState = ({ message }) => {
|
|
|
27
26
|
return (_jsx("div", { className: "flex h-full w-full flex-col items-center justify-center", children: _jsx("p", { children: message }) }));
|
|
28
27
|
};
|
|
29
28
|
const EMPTY_SUM_BY = [];
|
|
30
|
-
export const useQueryRange = (client, queryExpression, start, end, sumBy = EMPTY_SUM_BY, skip = false) => {
|
|
29
|
+
export const useQueryRange = (client, queryExpression, start, end, timeRange, sumBy = EMPTY_SUM_BY, skip = false) => {
|
|
30
|
+
const previousQueryParams = useRef({});
|
|
31
31
|
const [isLoading, setLoading] = useState(!skip);
|
|
32
32
|
const [state, setState] = useState({
|
|
33
33
|
response: null,
|
|
@@ -40,6 +40,15 @@ export const useQueryRange = (client, queryExpression, start, end, sumBy = EMPTY
|
|
|
40
40
|
if (skip) {
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
|
+
if (previousQueryParams.current.queryExpression !== queryExpression ||
|
|
44
|
+
previousQueryParams.current.timeRange !== timeRange) {
|
|
45
|
+
previousQueryParams.current.queryExpression = queryExpression;
|
|
46
|
+
previousQueryParams.current.timeRange = timeRange;
|
|
47
|
+
previousQueryParams.current.isRefresh = undefined;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
previousQueryParams.current.isRefresh = true;
|
|
51
|
+
}
|
|
43
52
|
setLoading(true);
|
|
44
53
|
const stepDuration = getStepDuration(start, end);
|
|
45
54
|
const call = client.queryRange({
|
|
@@ -59,14 +68,18 @@ export const useQueryRange = (client, queryExpression, start, end, sumBy = EMPTY
|
|
|
59
68
|
.catch(error => {
|
|
60
69
|
setState({ response: null, isLoading: false, error });
|
|
61
70
|
setLoading(false);
|
|
71
|
+
})
|
|
72
|
+
.finally(() => {
|
|
73
|
+
if (previousQueryParams.current.isRefresh !== undefined) {
|
|
74
|
+
previousQueryParams.current.isRefresh = undefined;
|
|
75
|
+
}
|
|
62
76
|
});
|
|
63
77
|
})();
|
|
64
|
-
}, [client, queryExpression, start, end, metadata, sumBy, skip]);
|
|
65
|
-
return { ...state, isLoading };
|
|
78
|
+
}, [client, queryExpression, start, end, metadata, timeRange, sumBy, skip]);
|
|
79
|
+
return { ...state, isLoading, isRefreshing: previousQueryParams.current.isRefresh };
|
|
66
80
|
};
|
|
67
|
-
const ProfileMetricsGraph = ({ queryClient, queryExpression, profile, from, to, setTimeRange, addLabelMatcher, onPointClick, comparing = false, }) => {
|
|
68
|
-
const { isLoading, response, error } = useQueryRange(queryClient, queryExpression, from, to);
|
|
69
|
-
const isLoaderVisible = useDelayedLoader(isLoading);
|
|
81
|
+
const ProfileMetricsGraph = ({ queryClient, queryExpression, profile, from, to, setTimeRange, addLabelMatcher, onPointClick, comparing = false, timeRange, }) => {
|
|
82
|
+
const { isLoading: metricsGraphLoading, response, error, } = useQueryRange(queryClient, queryExpression, from, to, timeRange);
|
|
70
83
|
const { onError, perf, authenticationErrorMessage, isDarkMode } = useParcaContext();
|
|
71
84
|
const { width, height, margin, heightStyle } = useMetricsGraphDimensions(comparing);
|
|
72
85
|
useEffect(() => {
|
|
@@ -82,7 +95,6 @@ const ProfileMetricsGraph = ({ queryClient, queryExpression, profile, from, to,
|
|
|
82
95
|
}, [perf, response]);
|
|
83
96
|
const series = response?.series;
|
|
84
97
|
const dataAvailable = series !== null && series !== undefined && series?.length > 0;
|
|
85
|
-
const metricsGraphLoading = isLoaderVisible || (isLoading && !dataAvailable);
|
|
86
98
|
if (metricsGraphLoading) {
|
|
87
99
|
return _jsx(MetricsGraphSkeleton, { heightStyle: heightStyle, isDarkMode: isDarkMode });
|
|
88
100
|
}
|
|
@@ -149,7 +149,7 @@ const ProfileSelector = ({ queryClient, querySelection, selectProfile, selectQue
|
|
|
149
149
|
}, id: "h-matcher-search-button", children: "Search" }) })] }), _jsx("div", { children: comparing && _jsx(IconButton, { onClick: () => closeProfile(), icon: _jsx(CloseIcon, {}) }) })] }), _jsx("div", { className: "rounded bg-white shadow dark:border-gray-500 dark:bg-gray-700", children: _jsx("div", { style: { height: heightStyle }, children: querySelection.expression !== undefined &&
|
|
150
150
|
querySelection.expression.length > 0 &&
|
|
151
151
|
querySelection.from !== undefined &&
|
|
152
|
-
querySelection.to !== undefined ? (_jsx("div", { className: "p-2", children: _jsx(ProfileMetricsGraph, { queryClient: queryClient, queryExpression: querySelection.expression, from: querySelection.from, to: querySelection.to, profile: profileSelection, comparing: comparing, setTimeRange: (range) => {
|
|
152
|
+
querySelection.to !== undefined ? (_jsx("div", { className: "p-2", children: _jsx(ProfileMetricsGraph, { queryClient: queryClient, queryExpression: querySelection.expression, from: querySelection.from, to: querySelection.to, profile: profileSelection, comparing: comparing, timeRange: timeRangeSelection, setTimeRange: (range) => {
|
|
153
153
|
const from = range.getFromMs();
|
|
154
154
|
const to = range.getToMs();
|
|
155
155
|
let mergedProfileParams = {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.399",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@headlessui/react": "^1.7.19",
|
|
@@ -73,5 +73,5 @@
|
|
|
73
73
|
"access": "public",
|
|
74
74
|
"registry": "https://registry.npmjs.org/"
|
|
75
75
|
},
|
|
76
|
-
"gitHead": "
|
|
76
|
+
"gitHead": "d1ea81e3ff9abe8c3cbb6a49ce2fed6217db407f"
|
|
77
77
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import {useEffect, useState} from 'react';
|
|
14
|
+
import {useEffect, useRef, useState} from 'react';
|
|
15
15
|
|
|
16
16
|
import {RpcError} from '@protobuf-ts/runtime-rpc';
|
|
17
17
|
import {AnimatePresence, motion} from 'framer-motion';
|
|
@@ -29,7 +29,6 @@ import {capitalizeOnlyFirstLetter, getStepDuration} from '@parca/utilities';
|
|
|
29
29
|
import {MergedProfileSelection, ProfileSelection} from '..';
|
|
30
30
|
import MetricsGraph from '../MetricsGraph';
|
|
31
31
|
import {useMetricsGraphDimensions} from '../MetricsGraph/useMetricsGraphDimensions';
|
|
32
|
-
import useDelayedLoader from '../useDelayedLoader';
|
|
33
32
|
|
|
34
33
|
interface ProfileMetricsEmptyStateProps {
|
|
35
34
|
message: string;
|
|
@@ -60,6 +59,7 @@ interface ProfileMetricsGraphProps {
|
|
|
60
59
|
profile: ProfileSelection | null;
|
|
61
60
|
from: number;
|
|
62
61
|
to: number;
|
|
62
|
+
timeRange: DateTimeRange;
|
|
63
63
|
setTimeRange: (range: DateTimeRange) => void;
|
|
64
64
|
addLabelMatcher: (
|
|
65
65
|
labels: {key: string; value: string} | Array<{key: string; value: string}>
|
|
@@ -76,6 +76,7 @@ interface ProfileMetricsGraphProps {
|
|
|
76
76
|
export interface IQueryRangeState {
|
|
77
77
|
response: QueryRangeResponse | null;
|
|
78
78
|
isLoading: boolean;
|
|
79
|
+
isRefreshing?: boolean;
|
|
79
80
|
error: RpcError | null;
|
|
80
81
|
}
|
|
81
82
|
|
|
@@ -86,9 +87,15 @@ export const useQueryRange = (
|
|
|
86
87
|
queryExpression: string,
|
|
87
88
|
start: number,
|
|
88
89
|
end: number,
|
|
90
|
+
timeRange: DateTimeRange,
|
|
89
91
|
sumBy: string[] = EMPTY_SUM_BY,
|
|
90
92
|
skip = false
|
|
91
93
|
): IQueryRangeState => {
|
|
94
|
+
const previousQueryParams = useRef<{
|
|
95
|
+
queryExpression?: string;
|
|
96
|
+
timeRange?: DateTimeRange;
|
|
97
|
+
isRefresh?: boolean;
|
|
98
|
+
}>({});
|
|
92
99
|
const [isLoading, setLoading] = useState<boolean>(!skip);
|
|
93
100
|
const [state, setState] = useState<IQueryRangeState>({
|
|
94
101
|
response: null,
|
|
@@ -102,6 +109,18 @@ export const useQueryRange = (
|
|
|
102
109
|
if (skip) {
|
|
103
110
|
return;
|
|
104
111
|
}
|
|
112
|
+
|
|
113
|
+
if (
|
|
114
|
+
previousQueryParams.current.queryExpression !== queryExpression ||
|
|
115
|
+
previousQueryParams.current.timeRange !== timeRange
|
|
116
|
+
) {
|
|
117
|
+
previousQueryParams.current.queryExpression = queryExpression;
|
|
118
|
+
previousQueryParams.current.timeRange = timeRange;
|
|
119
|
+
previousQueryParams.current.isRefresh = undefined;
|
|
120
|
+
} else {
|
|
121
|
+
previousQueryParams.current.isRefresh = true;
|
|
122
|
+
}
|
|
123
|
+
|
|
105
124
|
setLoading(true);
|
|
106
125
|
|
|
107
126
|
const stepDuration = getStepDuration(start, end);
|
|
@@ -126,11 +145,16 @@ export const useQueryRange = (
|
|
|
126
145
|
.catch(error => {
|
|
127
146
|
setState({response: null, isLoading: false, error});
|
|
128
147
|
setLoading(false);
|
|
148
|
+
})
|
|
149
|
+
.finally(() => {
|
|
150
|
+
if (previousQueryParams.current.isRefresh !== undefined) {
|
|
151
|
+
previousQueryParams.current.isRefresh = undefined;
|
|
152
|
+
}
|
|
129
153
|
});
|
|
130
154
|
})();
|
|
131
|
-
}, [client, queryExpression, start, end, metadata, sumBy, skip]);
|
|
155
|
+
}, [client, queryExpression, start, end, metadata, timeRange, sumBy, skip]);
|
|
132
156
|
|
|
133
|
-
return {...state, isLoading};
|
|
157
|
+
return {...state, isLoading, isRefreshing: previousQueryParams.current.isRefresh};
|
|
134
158
|
};
|
|
135
159
|
|
|
136
160
|
const ProfileMetricsGraph = ({
|
|
@@ -143,9 +167,13 @@ const ProfileMetricsGraph = ({
|
|
|
143
167
|
addLabelMatcher,
|
|
144
168
|
onPointClick,
|
|
145
169
|
comparing = false,
|
|
170
|
+
timeRange,
|
|
146
171
|
}: ProfileMetricsGraphProps): JSX.Element => {
|
|
147
|
-
const {
|
|
148
|
-
|
|
172
|
+
const {
|
|
173
|
+
isLoading: metricsGraphLoading,
|
|
174
|
+
response,
|
|
175
|
+
error,
|
|
176
|
+
} = useQueryRange(queryClient, queryExpression, from, to, timeRange);
|
|
149
177
|
const {onError, perf, authenticationErrorMessage, isDarkMode} = useParcaContext();
|
|
150
178
|
const {width, height, margin, heightStyle} = useMetricsGraphDimensions(comparing);
|
|
151
179
|
|
|
@@ -166,8 +194,6 @@ const ProfileMetricsGraph = ({
|
|
|
166
194
|
const series = response?.series;
|
|
167
195
|
const dataAvailable = series !== null && series !== undefined && series?.length > 0;
|
|
168
196
|
|
|
169
|
-
const metricsGraphLoading = isLoaderVisible || (isLoading && !dataAvailable);
|
|
170
|
-
|
|
171
197
|
if (metricsGraphLoading) {
|
|
172
198
|
return <MetricsGraphSkeleton heightStyle={heightStyle} isDarkMode={isDarkMode} />;
|
|
173
199
|
}
|
|
@@ -287,6 +287,7 @@ const ProfileSelector = ({
|
|
|
287
287
|
to={querySelection.to}
|
|
288
288
|
profile={profileSelection}
|
|
289
289
|
comparing={comparing}
|
|
290
|
+
timeRange={timeRangeSelection}
|
|
290
291
|
setTimeRange={(range: DateTimeRange) => {
|
|
291
292
|
const from = range.getFromMs();
|
|
292
293
|
const to = range.getToMs();
|