mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Prometheus: Show initial hint on builder mode when metric lookup disabled (#65827)
* Show initial hint on builder mode when metric lookup disabled * Disable MetricEncyclopedia and label request when metric lookup is disabled
This commit is contained in:
parent
e0385d08a8
commit
08727b7d6c
@ -1,8 +1,6 @@
|
|||||||
{
|
{
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"useWorkspaces": true,
|
"useWorkspaces": true,
|
||||||
"packages": [
|
"packages": ["packages/*"],
|
||||||
"packages/*"
|
|
||||||
],
|
|
||||||
"version": "10.0.0-pre"
|
"version": "10.0.0-pre"
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@ import (
|
|||||||
context "context"
|
context "context"
|
||||||
|
|
||||||
dashboards "github.com/grafana/grafana/pkg/services/dashboards"
|
dashboards "github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
mock "github.com/stretchr/testify/mock"
|
|
||||||
models "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
models "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FakePublicDashboardStore is an autogenerated mock type for the Store type
|
// FakePublicDashboardStore is an autogenerated mock type for the Store type
|
||||||
|
@ -7,7 +7,7 @@ import { DataSourceInstanceSettings, MetricFindValue } from '@grafana/data/src';
|
|||||||
import { PrometheusDatasource } from '../../datasource';
|
import { PrometheusDatasource } from '../../datasource';
|
||||||
import { PromOptions } from '../../types';
|
import { PromOptions } from '../../types';
|
||||||
|
|
||||||
import { MetricSelect } from './MetricSelect';
|
import { MetricSelect, Props } from './MetricSelect';
|
||||||
|
|
||||||
const instanceSettings = {
|
const instanceSettings = {
|
||||||
url: 'proxied',
|
url: 'proxied',
|
||||||
@ -44,7 +44,7 @@ dataSourceMock.metricFindQuery = jest.fn((query: string) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const props = {
|
const props: Props = {
|
||||||
labelsFilters: [],
|
labelsFilters: [],
|
||||||
datasource: dataSourceMock,
|
datasource: dataSourceMock,
|
||||||
query: {
|
query: {
|
||||||
@ -54,6 +54,7 @@ const props = {
|
|||||||
},
|
},
|
||||||
onChange: jest.fn(),
|
onChange: jest.fn(),
|
||||||
onGetMetrics: jest.fn().mockResolvedValue(mockValues),
|
onGetMetrics: jest.fn().mockResolvedValue(mockValues),
|
||||||
|
metricLookupDisabled: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('MetricSelect', () => {
|
describe('MetricSelect', () => {
|
||||||
|
@ -3,7 +3,7 @@ import debounce from 'debounce-promise';
|
|||||||
import React, { useCallback, useState } from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
import Highlighter from 'react-highlight-words';
|
import Highlighter from 'react-highlight-words';
|
||||||
|
|
||||||
import { SelectableValue, toOption, GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2, SelectableValue, toOption } from '@grafana/data';
|
||||||
import { EditorField, EditorFieldGroup } from '@grafana/experimental';
|
import { EditorField, EditorFieldGroup } from '@grafana/experimental';
|
||||||
import { AsyncSelect, FormatOptionLabelMeta, useStyles2 } from '@grafana/ui';
|
import { AsyncSelect, FormatOptionLabelMeta, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
@ -16,6 +16,7 @@ import { PromVisualQuery } from '../types';
|
|||||||
const splitSeparator = ' ';
|
const splitSeparator = ' ';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
metricLookupDisabled: boolean;
|
||||||
query: PromVisualQuery;
|
query: PromVisualQuery;
|
||||||
onChange: (query: PromVisualQuery) => void;
|
onChange: (query: PromVisualQuery) => void;
|
||||||
onGetMetrics: () => Promise<SelectableValue[]>;
|
onGetMetrics: () => Promise<SelectableValue[]>;
|
||||||
@ -25,7 +26,14 @@ export interface Props {
|
|||||||
|
|
||||||
export const PROMETHEUS_QUERY_BUILDER_MAX_RESULTS = 1000;
|
export const PROMETHEUS_QUERY_BUILDER_MAX_RESULTS = 1000;
|
||||||
|
|
||||||
export function MetricSelect({ datasource, query, onChange, onGetMetrics, labelsFilters }: Props) {
|
export function MetricSelect({
|
||||||
|
datasource,
|
||||||
|
query,
|
||||||
|
onChange,
|
||||||
|
onGetMetrics,
|
||||||
|
labelsFilters,
|
||||||
|
metricLookupDisabled,
|
||||||
|
}: Props) {
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
const [state, setState] = useState<{
|
const [state, setState] = useState<{
|
||||||
metrics?: Array<SelectableValue<any>>;
|
metrics?: Array<SelectableValue<any>>;
|
||||||
@ -114,6 +122,9 @@ export function MetricSelect({ datasource, query, onChange, onGetMetrics, labels
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// When metric and label lookup is disabled we won't request labels
|
||||||
|
const metricLookupDisabledSearch = () => Promise.resolve([]);
|
||||||
|
|
||||||
const debouncedSearch = debounce(
|
const debouncedSearch = debounce(
|
||||||
(query: string) => getMetricLabels(query),
|
(query: string) => getMetricLabels(query),
|
||||||
datasource.getDebounceTimeInMilliseconds()
|
datasource.getDebounceTimeInMilliseconds()
|
||||||
@ -126,11 +137,14 @@ export function MetricSelect({ datasource, query, onChange, onGetMetrics, labels
|
|||||||
inputId="prometheus-metric-select"
|
inputId="prometheus-metric-select"
|
||||||
className={styles.select}
|
className={styles.select}
|
||||||
value={query.metric ? toOption(query.metric) : undefined}
|
value={query.metric ? toOption(query.metric) : undefined}
|
||||||
placeholder="Select metric"
|
placeholder={'Select metric'}
|
||||||
allowCustomValue
|
allowCustomValue
|
||||||
formatOptionLabel={formatOptionLabel}
|
formatOptionLabel={formatOptionLabel}
|
||||||
filterOption={customFilterOption}
|
filterOption={customFilterOption}
|
||||||
onOpenMenu={async () => {
|
onOpenMenu={async () => {
|
||||||
|
if (metricLookupDisabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setState({ isLoading: true });
|
setState({ isLoading: true });
|
||||||
const metrics = await onGetMetrics();
|
const metrics = await onGetMetrics();
|
||||||
if (metrics.length > PROMETHEUS_QUERY_BUILDER_MAX_RESULTS) {
|
if (metrics.length > PROMETHEUS_QUERY_BUILDER_MAX_RESULTS) {
|
||||||
@ -138,7 +152,7 @@ export function MetricSelect({ datasource, query, onChange, onGetMetrics, labels
|
|||||||
}
|
}
|
||||||
setState({ metrics, isLoading: undefined });
|
setState({ metrics, isLoading: undefined });
|
||||||
}}
|
}}
|
||||||
loadOptions={debouncedSearch}
|
loadOptions={metricLookupDisabled ? metricLookupDisabledSearch : debouncedSearch}
|
||||||
isLoading={state.isLoading}
|
isLoading={state.isLoading}
|
||||||
defaultOptions={state.metrics}
|
defaultOptions={state.metrics}
|
||||||
onChange={({ value }) => {
|
onChange={({ value }) => {
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
LoadingState,
|
LoadingState,
|
||||||
MutableDataFrame,
|
MutableDataFrame,
|
||||||
PanelData,
|
PanelData,
|
||||||
|
QueryHint,
|
||||||
TimeRange,
|
TimeRange,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
|
|
||||||
@ -229,6 +230,45 @@ describe('PromQueryBuilder', () => {
|
|||||||
expect(await screen.queryByText(EXPLAIN_LABEL_FILTER_CONTENT)).not.toBeInTheDocument();
|
expect(await screen.queryByText(EXPLAIN_LABEL_FILTER_CONTENT)).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders hint if initial hint provided', async () => {
|
||||||
|
const { datasource } = createDatasource();
|
||||||
|
datasource.getInitHints = (): QueryHint[] => [
|
||||||
|
{
|
||||||
|
label: 'Initial hint',
|
||||||
|
type: 'warning',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const props = createProps(datasource);
|
||||||
|
render(
|
||||||
|
<PromQueryBuilder
|
||||||
|
{...props}
|
||||||
|
query={{
|
||||||
|
metric: 'histogram_metric_sum',
|
||||||
|
labels: [],
|
||||||
|
operations: [],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
expect(await screen.queryByText('Initial hint')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders no hint if no initial hint provided', async () => {
|
||||||
|
const { datasource } = createDatasource();
|
||||||
|
datasource.getInitHints = (): QueryHint[] => [];
|
||||||
|
const props = createProps(datasource);
|
||||||
|
render(
|
||||||
|
<PromQueryBuilder
|
||||||
|
{...props}
|
||||||
|
query={{
|
||||||
|
metric: 'histogram_metric_sum',
|
||||||
|
labels: [],
|
||||||
|
operations: [],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
expect(await screen.queryByText('Initial hint')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
// <ModernPrometheus>
|
// <ModernPrometheus>
|
||||||
it('tries to load labels when metric selected modern prom', async () => {
|
it('tries to load labels when metric selected modern prom', async () => {
|
||||||
const { languageProvider } = setup(undefined, undefined, {
|
const { languageProvider } = setup(undefined, undefined, {
|
||||||
|
@ -208,12 +208,14 @@ export const PromQueryBuilder = React.memo<Props>((props) => {
|
|||||||
}, [datasource, query, withTemplateVariableOptions]);
|
}, [datasource, query, withTemplateVariableOptions]);
|
||||||
|
|
||||||
const lang = { grammar: promqlGrammar, name: 'promql' };
|
const lang = { grammar: promqlGrammar, name: 'promql' };
|
||||||
const MetricEncyclopedia = config.featureToggles.prometheusMetricEncyclopedia;
|
const isMetricEncyclopediaEnabled = config.featureToggles.prometheusMetricEncyclopedia;
|
||||||
|
|
||||||
|
const initHints = datasource.getInitHints();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EditorRow>
|
<EditorRow>
|
||||||
{MetricEncyclopedia ? (
|
{isMetricEncyclopediaEnabled && !datasource.lookupsDisabled ? (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
className={styles.button}
|
className={styles.button}
|
||||||
@ -252,6 +254,7 @@ export const PromQueryBuilder = React.memo<Props>((props) => {
|
|||||||
onGetMetrics={onGetMetrics}
|
onGetMetrics={onGetMetrics}
|
||||||
datasource={datasource}
|
datasource={datasource}
|
||||||
labelsFilters={query.labels}
|
labelsFilters={query.labels}
|
||||||
|
metricLookupDisabled={datasource.lookupsDisabled}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<LabelFilters
|
<LabelFilters
|
||||||
@ -264,6 +267,18 @@ export const PromQueryBuilder = React.memo<Props>((props) => {
|
|||||||
onGetLabelValues={(forLabel) => withTemplateVariableOptions(onGetLabelValues(forLabel))}
|
onGetLabelValues={(forLabel) => withTemplateVariableOptions(onGetLabelValues(forLabel))}
|
||||||
/>
|
/>
|
||||||
</EditorRow>
|
</EditorRow>
|
||||||
|
{initHints.length ? (
|
||||||
|
<div className="query-row-break">
|
||||||
|
<div className="prom-query-field-info text-warning">
|
||||||
|
{initHints[0].label}{' '}
|
||||||
|
{initHints[0].fix ? (
|
||||||
|
<button type="button" className={'text-warning'}>
|
||||||
|
{initHints[0].fix.label}
|
||||||
|
</button>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
{showExplain && (
|
{showExplain && (
|
||||||
<OperationExplainedBox
|
<OperationExplainedBox
|
||||||
stepNumber={1}
|
stepNumber={1}
|
||||||
|
Loading…
Reference in New Issue
Block a user