diff --git a/public/app/plugins/datasource/loki/components/LokiLabelBrowser.tsx b/public/app/plugins/datasource/loki/components/LokiLabelBrowser.tsx index 80ffc5c8ec2..0857f1c0806 100644 --- a/public/app/plugins/datasource/loki/components/LokiLabelBrowser.tsx +++ b/public/app/plugins/datasource/loki/components/LokiLabelBrowser.tsx @@ -10,7 +10,7 @@ import { GrafanaTheme } from '@grafana/data'; import { LokiLabel } from './LokiLabel'; // Hard limit on labels to render -const MAX_LABEL_COUNT = 100; +const MAX_LABEL_COUNT = 1000; const MAX_VALUE_COUNT = 10000; const MAX_AUTO_SELECT = 4; const EMPTY_SELECTOR = '{}'; @@ -161,7 +161,7 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => ({ })); export class UnthemedLokiLabelBrowser extends React.Component { - state = { + state: BrowserState = { labels: [] as SelectableLabel[], searchTerm: '', status: 'Ready', @@ -269,7 +269,7 @@ export class UnthemedLokiLabelBrowser extends React.Component { this.state.labels.forEach((label) => { if (label.selected) { - this.fetchValues(label.name); + this.fetchValues(label.name, EMPTY_SELECTOR); } }); }); @@ -287,7 +287,7 @@ export class UnthemedLokiLabelBrowser extends React.Component { // Get fresh set of values - this.state.labels.forEach((label) => label.selected && this.fetchValues(label.name)); + this.state.labels.forEach((label) => label.selected && this.fetchValues(label.name, selector)); }); } else { // Do facetting @@ -312,18 +312,23 @@ export class UnthemedLokiLabelBrowser extends React.Component MAX_VALUE_COUNT) { const error = `Too many values for ${name} (showing only ${MAX_VALUE_COUNT} of ${rawValues.length})`; rawValues = rawValues.slice(0, MAX_VALUE_COUNT); this.setState({ error }); } const values: FacettableValue[] = rawValues.map((value) => ({ name: value })); - this.updateLabelState(name, { values, loading: false }, ''); + this.updateLabelState(name, { values, loading: false }); } catch (error) { console.error(error); } @@ -336,6 +341,13 @@ export class UnthemedLokiLabelBrowser extends React.Component label.selected && label.values); if (searchTerm) { - // TODO extract from render() and debounce selectedLabels = selectedLabels.map((label) => ({ ...label, values: label.values?.filter((value) => value.selected || value.name.includes(searchTerm)), diff --git a/public/app/plugins/datasource/prometheus/components/Label.tsx b/public/app/plugins/datasource/prometheus/components/Label.tsx index 43831b23fc6..f9a28ea4cc6 100644 --- a/public/app/plugins/datasource/prometheus/components/Label.tsx +++ b/public/app/plugins/datasource/prometheus/components/Label.tsx @@ -59,7 +59,12 @@ export const Label = forwardRef( )} {...rest} > - + ); } diff --git a/public/app/plugins/datasource/prometheus/components/PrometheusMetricsBrowser.test.tsx b/public/app/plugins/datasource/prometheus/components/PrometheusMetricsBrowser.test.tsx index bf9b47de4ca..9ba1deef673 100644 --- a/public/app/plugins/datasource/prometheus/components/PrometheusMetricsBrowser.test.tsx +++ b/public/app/plugins/datasource/prometheus/components/PrometheusMetricsBrowser.test.tsx @@ -270,10 +270,10 @@ describe('PrometheusMetricsBrowser', () => { await screen.findByLabelText('Values for label2'); expect(await screen.findAllByRole('option', { name: /value/ })).toHaveLength(4); // Typing '1' to filter for values - userEvent.type(screen.getByLabelText('Filter expression for label values'), '1'); + await userEvent.type(screen.getByLabelText('Filter expression for label values'), '1'); expect(screen.getByLabelText('Filter expression for label values')).toHaveValue('1'); - expect(screen.queryByRole('option', { name: 'value2-2' })).not.toBeInTheDocument(); expect(await screen.findAllByRole('option', { name: /value/ })).toHaveLength(3); + expect(screen.queryByRole('option', { name: 'value2-2' })).not.toBeInTheDocument(); }); it('facets labels', async () => { @@ -299,6 +299,7 @@ describe('PrometheusMetricsBrowser', () => { const value12 = await screen.findByRole('option', { name: 'value1-2', selected: false }); userEvent.click(value12); await screen.findByRole('option', { name: 'value1-2', selected: true }); + await screen.findByRole('option', { name: /label3/, selected: false }); userEvent.click(screen.getByRole('option', { name: /label3/ })); await screen.findByLabelText('Values for label3'); expect(screen.queryByRole('option', { name: 'value1-1', selected: true })).toBeInTheDocument(); diff --git a/public/app/plugins/datasource/prometheus/components/PrometheusMetricsBrowser.tsx b/public/app/plugins/datasource/prometheus/components/PrometheusMetricsBrowser.tsx index f6b83a569c9..b7b98415d33 100644 --- a/public/app/plugins/datasource/prometheus/components/PrometheusMetricsBrowser.tsx +++ b/public/app/plugins/datasource/prometheus/components/PrometheusMetricsBrowser.tsx @@ -10,7 +10,7 @@ import { Label as PromLabel } from './Label'; // Hard limit on labels to render const MAX_LABEL_COUNT = 10000; -const MAX_VALUE_COUNT = 10000; +const MAX_VALUE_COUNT = 50000; const EMPTY_SELECTOR = '{}'; const METRIC_LABEL = '__name__'; export const LAST_USED_LABELS_KEY = 'grafana.datasources.prometheus.browser.labels'; @@ -176,7 +176,7 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => ({ * to create a single, generic component. */ export class UnthemedPrometheusMetricsBrowser extends React.Component { - state = { + state: BrowserState = { labels: [] as SelectableLabel[], labelSearchTerm: '', metricSearchTerm: '', @@ -231,7 +231,7 @@ export class UnthemedPrometheusMetricsBrowser extends React.Component) => { @@ -314,7 +314,7 @@ export class UnthemedPrometheusMetricsBrowser extends React.Component ({ name: label, @@ -325,7 +325,7 @@ export class UnthemedPrometheusMetricsBrowser extends React.Component { this.state.labels.forEach((label) => { if (label.selected) { - this.fetchValues(label.name); + this.fetchValues(label.name, EMPTY_SELECTOR); } }); }); @@ -343,7 +343,7 @@ export class UnthemedPrometheusMetricsBrowser extends React.Component { // Get fresh set of values this.state.labels.forEach( - (label) => (label.selected || label.name === METRIC_LABEL) && this.fetchValues(label.name) + (label) => (label.selected || label.name === METRIC_LABEL) && this.fetchValues(label.name, selector) ); }); } else { @@ -370,18 +370,23 @@ export class UnthemedPrometheusMetricsBrowser extends React.Component MAX_VALUE_COUNT) { const error = `Too many values for ${name} (showing only ${MAX_VALUE_COUNT} of ${rawValues.length})`; rawValues = rawValues.slice(0, MAX_VALUE_COUNT); this.setState({ error }); } const values: FacettableValue[] = rawValues.map((value) => ({ name: value })); - this.updateLabelState(name, { values, loading: false }, ''); + this.updateLabelState(name, { values, loading: false }); } catch (error) { console.error(error); } @@ -394,6 +399,13 @@ export class UnthemedPrometheusMetricsBrowser extends React.Component label.name === METRIC_LABEL); if (metrics && metricSearchTerm) { - // TODO extract from render() and debounce metrics = { ...metrics, values: metrics.values?.filter((value) => value.selected || value.name.includes(metricSearchTerm)), @@ -442,14 +453,12 @@ export class UnthemedPrometheusMetricsBrowser extends React.Component !label.hidden && label.name !== METRIC_LABEL); if (labelSearchTerm) { - // TODO extract from render() and debounce nonMetricLabels = nonMetricLabels.filter((label) => label.selected || label.name.includes(labelSearchTerm)); } // Filter non-metric label values let selectedLabels = nonMetricLabels.filter((label) => label.selected && label.values); if (valueSearchTerm) { - // TODO extract from render() and debounce selectedLabels = selectedLabels.map((label) => ({ ...label, values: label.values?.filter((value) => value.selected || value.name.includes(valueSearchTerm)),