Skip to content

Commit 56b2b76

Browse files
ui: Fix redundant Label Values query (#5425)
* Fix redundant values query * [pre-commit.ci lite] apply automatic fixes * Linter fixes * [pre-commit.ci lite] apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent 801d740 commit 56b2b76

File tree

2 files changed

+63
-31
lines changed

2 files changed

+63
-31
lines changed

ui/packages/shared/profile/src/MatchersInput/index.tsx

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
// See the License for the specific language governing permissions and
1212
// limitations under the License.
1313

14-
import React, {useEffect, useMemo, useRef, useState} from 'react';
14+
import React, {useMemo, useRef, useState} from 'react';
1515

1616
import cx from 'classnames';
1717
import TextareaAutosize from 'react-textarea-autosize';
1818

19-
import {LabelsRequest, LabelsResponse, QueryServiceClient} from '@parca/client';
19+
import {LabelsRequest, LabelsResponse, QueryServiceClient, ValuesRequest} from '@parca/client';
2020
import {useGrpcMetadata} from '@parca/components';
2121
import {Query} from '@parca/parser';
2222
import {millisToProtoTimestamp, sanitizeLabelValue} from '@parca/utilities';
@@ -75,6 +75,42 @@ export const useLabelNames = (
7575
return {result: {response: data, error: error as Error}, loading: isLoading};
7676
};
7777

78+
interface UseLabelValues {
79+
result: {
80+
response: string[];
81+
error?: Error;
82+
};
83+
loading: boolean;
84+
}
85+
86+
export const useLabelValues = (
87+
client: QueryServiceClient,
88+
labelName: string,
89+
profileType: string
90+
): UseLabelValues => {
91+
const metadata = useGrpcMetadata();
92+
93+
const {data, isLoading, error} = useGrpcQuery<string[]>({
94+
key: ['labelValues', labelName, profileType],
95+
queryFn: async () => {
96+
const request: ValuesRequest = {labelName, match: [], profileType};
97+
const {response} = await client.values(request, {meta: metadata});
98+
return sanitizeLabelValue(response.labelValues);
99+
},
100+
options: {
101+
enabled:
102+
profileType !== undefined &&
103+
profileType !== '' &&
104+
labelName !== undefined &&
105+
labelName !== '',
106+
staleTime: 1000 * 60 * 5, // 5 minutes
107+
keepPreviousData: false,
108+
},
109+
});
110+
111+
return {result: {response: data ?? [], error: error as Error}, loading: isLoading};
112+
};
113+
78114
const MatchersInput = ({
79115
queryClient,
80116
setMatchersString,
@@ -84,34 +120,16 @@ const MatchersInput = ({
84120
}: MatchersInputProps): JSX.Element => {
85121
const inputRef = useRef<HTMLTextAreaElement | null>(null);
86122
const [focusedInput, setFocusedInput] = useState(false);
87-
const [labelValuesLoading, setLabelValuesLoading] = useState(false);
88123
const [lastCompleted, setLastCompleted] = useState<Suggestion>(new Suggestion('', '', ''));
89-
const [labelValues, setLabelValues] = useState<string[] | null>(null);
90124
const [currentLabelName, setCurrentLabelName] = useState<string | null>(null);
91-
const metadata = useGrpcMetadata();
92125

93126
const {loading: labelNamesLoading, result} = useLabelNames(queryClient, profileType);
94127
const {response: labelNamesResponse, error: labelNamesError} = result;
95128

96-
useEffect(() => {
97-
if (currentLabelName !== null) {
98-
const call = queryClient.values(
99-
{labelName: currentLabelName, match: [], profileType},
100-
{meta: metadata}
101-
);
102-
setLabelValuesLoading(true);
103-
104-
call.response
105-
.then(response => {
106-
// replace single `\` in the `labelValues` string with doubles `\\` if available.
107-
const newValues = sanitizeLabelValue(response.labelValues);
108-
109-
return setLabelValues(newValues);
110-
})
111-
.catch(() => setLabelValues(null))
112-
.finally(() => setLabelValuesLoading(false));
113-
}
114-
}, [currentLabelName, metadata, profileType, queryClient]);
129+
const {
130+
loading: labelValuesLoading,
131+
result: {response: labelValues},
132+
} = useLabelValues(queryClient, currentLabelName ?? '', profileType);
115133

116134
const labelNames = useMemo(() => {
117135
return (labelNamesError === undefined || labelNamesError == null) &&

ui/packages/shared/profile/src/SimpleMatchers/index.tsx

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import {useCallback, useEffect, useMemo, useState} from 'react';
1515

1616
import {Icon} from '@iconify/react';
17+
import {useQueryClient} from '@tanstack/react-query';
1718
import cx from 'classnames';
1819

1920
import {QueryServiceClient} from '@parca/client';
@@ -106,6 +107,7 @@ const SimpleMatchers = ({
106107
const [queryRows, setQueryRows] = useState<QueryRow[]>([
107108
{labelName: '', operator: '=', labelValue: '', labelValues: [], isLoading: false},
108109
]);
110+
const reactQueryClient = useQueryClient();
109111
const metadata = useGrpcMetadata();
110112

111113
const {loading: labelNamesLoading, result} = useLabelNames(queryClient, profileType);
@@ -129,19 +131,31 @@ const SimpleMatchers = ({
129131

130132
const fetchLabelValues = useCallback(
131133
async (labelName: string): Promise<string[]> => {
134+
if (labelName == null || labelName === '' || profileType == null || profileType === '') {
135+
return [];
136+
}
132137
try {
133-
const response = await queryClient.values(
134-
{labelName, match: [], profileType},
135-
{meta: metadata}
136-
).response;
137-
const sanitizedValues = sanitizeLabelValue(response.labelValues);
138-
return sanitizedValues;
138+
const values = await reactQueryClient.fetchQuery(
139+
[labelName, profileType],
140+
async () => {
141+
const response = await queryClient.values(
142+
{labelName, match: [], profileType},
143+
{meta: metadata}
144+
).response;
145+
const sanitizedValues = sanitizeLabelValue(response.labelValues);
146+
return sanitizedValues;
147+
},
148+
{
149+
staleTime: 1000 * 60 * 5, // 5 minutes
150+
}
151+
);
152+
return values;
139153
} catch (error) {
140154
console.error('Error fetching label values:', error);
141155
return [];
142156
}
143157
},
144-
[queryClient, metadata, profileType]
158+
[queryClient, metadata, profileType, reactQueryClient]
145159
);
146160

147161
const updateMatchersString = useCallback(

0 commit comments

Comments
 (0)