Further improve rendering performance
This commit is contained in:
+5
-5
@@ -12,12 +12,12 @@ interface Props {
|
||||
value: string;
|
||||
onChange: (val: string) => void;
|
||||
onRunQuery: (value: string) => void;
|
||||
labels?: string[];
|
||||
getLabelNames: () => string[];
|
||||
getLabelValues: (label: string) => Promise<string[]>;
|
||||
}
|
||||
|
||||
export function LabelsEditor(props: Props) {
|
||||
const setupAutocompleteFn = useAutocomplete(props.getLabelValues, props.labels);
|
||||
const setupAutocompleteFn = useAutocomplete(props.getLabelValues, props.getLabelNames);
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const onRunQueryRef = useLatest(props.onRunQuery);
|
||||
@@ -92,7 +92,7 @@ const EDITOR_HEIGHT_OFFSET = 2;
|
||||
/**
|
||||
* Hook that returns function that will set up monaco autocomplete for the label selector
|
||||
*/
|
||||
function useAutocomplete(getLabelValues: (label: string) => Promise<string[]>, labels?: string[]) {
|
||||
function useAutocomplete(getLabelValues: (label: string) => Promise<string[]>, getLabelNames: () => string[]) {
|
||||
const providerRef = useRef<CompletionProvider>();
|
||||
if (providerRef.current === undefined) {
|
||||
providerRef.current = new CompletionProvider();
|
||||
@@ -100,9 +100,9 @@ function useAutocomplete(getLabelValues: (label: string) => Promise<string[]>, l
|
||||
|
||||
useAsync(async () => {
|
||||
if (providerRef.current) {
|
||||
providerRef.current.init(labels || [], getLabelValues);
|
||||
providerRef.current.init(getLabelNames, getLabelValues);
|
||||
}
|
||||
}, [labels, getLabelValues]);
|
||||
}, [getLabelNames, getLabelValues]);
|
||||
|
||||
const autocompleteDisposeFun = useRef<(() => void) | null>(null);
|
||||
useEffect(() => {
|
||||
|
||||
+36
-15
@@ -1,6 +1,5 @@
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
import React, {useCallback, useEffect, useMemo} from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
import React, {useCallback, useEffect, useState} from 'react';
|
||||
|
||||
import { CoreApp, QueryEditorProps, TimeRange } from '@grafana/data';
|
||||
import { LoadingPlaceholder } from '@grafana/ui';
|
||||
@@ -26,7 +25,7 @@ export function QueryEditor(props: Props) {
|
||||
}
|
||||
|
||||
const profileTypes = useProfileTypes(datasource);
|
||||
const { labels, getLabelValues, onLabelSelectorChange } = useLabels(range, datasource, query, onChange);
|
||||
const { getLabelNames, getLabelValues, onLabelSelectorChange } = useLabels(range, datasource, query, onChange);
|
||||
useNormalizeQuery(query, profileTypes, onChange, app);
|
||||
|
||||
let cascader = <LoadingPlaceholder text={'Loading'} />;
|
||||
@@ -55,13 +54,13 @@ export function QueryEditor(props: Props) {
|
||||
value={query.labelSelector}
|
||||
onChange={onLabelSelectorChange}
|
||||
onRunQuery={handleRunQuery}
|
||||
labels={labels}
|
||||
getLabelNames={getLabelNames}
|
||||
getLabelValues={getLabelValues}
|
||||
/>
|
||||
<PyroscopeQueryLinkExtensions {...props} />
|
||||
</EditorRow>
|
||||
<EditorRow>
|
||||
<QueryOptions query={query} onQueryChange={props.onChange} app={props.app} labels={labels} />
|
||||
<QueryOptions query={query} onQueryChange={props.onChange} app={props.app} getLabelNames={getLabelNames} />
|
||||
</EditorRow>
|
||||
</EditorRows>
|
||||
);
|
||||
@@ -136,20 +135,38 @@ function useLabels(
|
||||
return `{${labels.join(',')}}`
|
||||
}
|
||||
|
||||
const labelSelector = useMemo(() => createSelector(query.labelSelector, query.profileTypeId, '')
|
||||
, [query.labelSelector, query.profileTypeId]);
|
||||
const [queryLabels, setQueryLabels] = useState(() => ({ labels: [] as string[] }));
|
||||
const [processedLabelSelector, setProcessedLabelSelector] = useState(() => ({ labelSelector: createSelector('', query.profileTypeId, '') }));
|
||||
const [rawQuery, setRawQuery] = useState(() => ( { data: ''}))
|
||||
|
||||
useEffect(() => {
|
||||
setProcessedLabelSelector({
|
||||
labelSelector: createSelector(rawQuery.data, query.profileTypeId, ''),
|
||||
});
|
||||
}, [rawQuery.data, query.profileTypeId]);
|
||||
|
||||
const getLabelNames = useCallback(
|
||||
() => datasource.getLabelNames(labelSelector, unpreciseRange.from, unpreciseRange.to),
|
||||
[datasource, labelSelector, unpreciseRange.from, unpreciseRange.to]
|
||||
() => queryLabels.labels,
|
||||
[queryLabels]
|
||||
);
|
||||
|
||||
const labelsResult = useAsync(getLabelNames, [getLabelNames]);
|
||||
useEffect(() => {
|
||||
const fetchData = async() => {
|
||||
const labels = await datasource.getLabelNames(
|
||||
processedLabelSelector.labelSelector,
|
||||
unpreciseRange.from,
|
||||
unpreciseRange.to
|
||||
);
|
||||
|
||||
setQueryLabels((prevQueryLabels) => ({ ...prevQueryLabels, labels }));
|
||||
}
|
||||
fetchData();
|
||||
}, [processedLabelSelector.labelSelector, unpreciseRange.from, unpreciseRange.to, datasource, setQueryLabels]);
|
||||
|
||||
// Create a function with range and query already baked in so we don't have to send those everywhere
|
||||
const getLabelValues = useCallback(
|
||||
(label: string) => {
|
||||
let labelSelector = createSelector(query.labelSelector, query.profileTypeId, label);
|
||||
let labelSelector = createSelector(rawQuery.data, query.profileTypeId, label);
|
||||
console.log(labelSelector)
|
||||
const labelValues = datasource.getLabelValues(
|
||||
labelSelector,
|
||||
@@ -160,15 +177,19 @@ function useLabels(
|
||||
console.log(labelValues)
|
||||
return labelValues;
|
||||
},
|
||||
[datasource, query, unpreciseRange.to, unpreciseRange.from]
|
||||
[datasource, rawQuery.data, query.profileTypeId, unpreciseRange.to, unpreciseRange.from]
|
||||
);
|
||||
|
||||
const onLabelSelectorChange = useCallback(
|
||||
(value: string) => {
|
||||
onChange({ ...query, labelSelector: value });
|
||||
// onChange({ ...query, labelSelector: value });
|
||||
setRawQuery({
|
||||
data: value,
|
||||
})
|
||||
query.labelSelector = value
|
||||
},
|
||||
[onChange, query]
|
||||
[setRawQuery, query]
|
||||
);
|
||||
|
||||
return { labels: labelsResult.value, getLabelValues, onLabelSelectorChange };
|
||||
return { getLabelNames, getLabelValues, onLabelSelectorChange };
|
||||
}
|
||||
|
||||
+4
-4
@@ -15,7 +15,7 @@ export interface Props {
|
||||
query: Query;
|
||||
onQueryChange: (query: Query) => void;
|
||||
app?: CoreApp;
|
||||
labels?: string[];
|
||||
getLabelNames: () => string[];
|
||||
}
|
||||
|
||||
const typeOptions: Array<{ value: Query['queryType']; label: string; description: string }> = [
|
||||
@@ -34,11 +34,11 @@ function getTypeOptions(app?: CoreApp) {
|
||||
/**
|
||||
* Base on QueryOptionGroup component from grafana/ui but that is not available yet.
|
||||
*/
|
||||
export function QueryOptions({ query, onQueryChange, app, labels }: Props) {
|
||||
export function QueryOptions({ query, onQueryChange, app, getLabelNames }: Props) {
|
||||
const styles = useStyles2(getStyles);
|
||||
const typeOptions = getTypeOptions(app);
|
||||
const groupByOptions = labels
|
||||
? labels.map((l) => ({
|
||||
const groupByOptions = getLabelNames()
|
||||
? getLabelNames().map((l) => ({
|
||||
label: l,
|
||||
value: l,
|
||||
}))
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ const defaultLabels = ['foo'];
|
||||
|
||||
function setup(value: string, offset: number, labels: string[] = []) {
|
||||
const provider = new CompletionProvider();
|
||||
provider.init(labels, (label) => {
|
||||
provider.init(() => labels, (label) => {
|
||||
if (labels.length === 0) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
+5
-5
@@ -14,11 +14,11 @@ export class CompletionProvider implements monacoTypes.languages.CompletionItemP
|
||||
monaco: Monaco | undefined;
|
||||
editor: monacoTypes.editor.IStandaloneCodeEditor | undefined;
|
||||
|
||||
private labels: string[] = [];
|
||||
private getLabelNames: () => string[] = () => [];
|
||||
private getLabelValues: (label: string) => Promise<string[]> = () => Promise.resolve([]);
|
||||
|
||||
init(labels: string[], getLabelValues: (label: string) => Promise<string[]>) {
|
||||
this.labels = labels;
|
||||
init(getLabelNames: () => string[], getLabelValues: (label: string) => Promise<string[]>) {
|
||||
this.getLabelNames = getLabelNames;
|
||||
this.getLabelValues = getLabelValues;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ export class CompletionProvider implements monacoTypes.languages.CompletionItemP
|
||||
return [];
|
||||
}
|
||||
case 'EMPTY': {
|
||||
return this.labels.map((key) => {
|
||||
return this.getLabelNames().map((key) => {
|
||||
return {
|
||||
label: key,
|
||||
insertText: `{${key}="`,
|
||||
@@ -77,7 +77,7 @@ export class CompletionProvider implements monacoTypes.languages.CompletionItemP
|
||||
});
|
||||
}
|
||||
case 'IN_LABEL_NAME':
|
||||
return this.labels.map((key) => {
|
||||
return this.getLabelNames().map((key) => {
|
||||
return {
|
||||
label: key,
|
||||
insertText: key,
|
||||
|
||||
Reference in New Issue
Block a user