mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Explore: Remove datasource testing on selector (#19910)
* Explore: Remove datasource testing on selector - datasource testing gets in the way of fast query iteration: switching between datasources can take seconds - it should not be explore's duty to test datasources in the first place - removed the concept of datasourceError in Explore, should not be its concern - datasource erorrs will express themselves in query errors just fine - connection errors are still bubbled up - removed reconnection logic from explore, should not be its concern - missing labels in loki are still "visible" via an empty label selector - Loki and Prometheus treated connection errors differently than other datasources, making sure to pass through the original error message * Show datasource error in query field for prom/loki/influx * Removed connection test case, fixed disabled state
This commit is contained in:
@@ -17,6 +17,13 @@ export interface State {
|
||||
measurements: CascaderOption[];
|
||||
measurement: string;
|
||||
field: string;
|
||||
error: string;
|
||||
}
|
||||
|
||||
interface ChooserOptions {
|
||||
measurement: string;
|
||||
field: string;
|
||||
error: string;
|
||||
}
|
||||
|
||||
// Helper function for determining if a collection of pairs are valid
|
||||
@@ -32,37 +39,54 @@ export function pairsAreValid(pairs: KeyValuePair[]) {
|
||||
);
|
||||
}
|
||||
|
||||
function getChooserText({ measurement, field, error }: ChooserOptions): string {
|
||||
if (error) {
|
||||
return '(No measurement found)';
|
||||
}
|
||||
if (measurement) {
|
||||
return `Measurements (${measurement}/${field})`;
|
||||
}
|
||||
return 'Measurements';
|
||||
}
|
||||
|
||||
export class InfluxLogsQueryField extends React.PureComponent<Props, State> {
|
||||
templateSrv: TemplateSrv = new TemplateSrv();
|
||||
state: State = { measurements: [], measurement: null, field: null };
|
||||
state: State = { measurements: [], measurement: null, field: null, error: null };
|
||||
|
||||
async componentDidMount() {
|
||||
const { datasource } = this.props;
|
||||
const queryBuilder = new InfluxQueryBuilder({ measurement: '', tags: [] }, datasource.database);
|
||||
const measureMentsQuery = queryBuilder.buildExploreQuery('MEASUREMENTS');
|
||||
const influxMeasurements = await datasource.metricFindQuery(measureMentsQuery);
|
||||
try {
|
||||
const queryBuilder = new InfluxQueryBuilder({ measurement: '', tags: [] }, datasource.database);
|
||||
const measureMentsQuery = queryBuilder.buildExploreQuery('MEASUREMENTS');
|
||||
const influxMeasurements = await datasource.metricFindQuery(measureMentsQuery);
|
||||
|
||||
const measurements = [];
|
||||
for (let index = 0; index < influxMeasurements.length; index++) {
|
||||
const measurementObj = influxMeasurements[index];
|
||||
const queryBuilder = new InfluxQueryBuilder({ measurement: measurementObj.text, tags: [] }, datasource.database);
|
||||
const fieldsQuery = queryBuilder.buildExploreQuery('FIELDS');
|
||||
const influxFields = await datasource.metricFindQuery(fieldsQuery);
|
||||
const fields: any[] = influxFields.map(
|
||||
(field: any): any => ({
|
||||
label: field.text,
|
||||
value: field.text,
|
||||
children: [],
|
||||
})
|
||||
);
|
||||
measurements.push({
|
||||
label: measurementObj.text,
|
||||
value: measurementObj.text,
|
||||
children: fields,
|
||||
});
|
||||
const measurements = [];
|
||||
for (let index = 0; index < influxMeasurements.length; index++) {
|
||||
const measurementObj = influxMeasurements[index];
|
||||
const queryBuilder = new InfluxQueryBuilder(
|
||||
{ measurement: measurementObj.text, tags: [] },
|
||||
datasource.database
|
||||
);
|
||||
const fieldsQuery = queryBuilder.buildExploreQuery('FIELDS');
|
||||
const influxFields = await datasource.metricFindQuery(fieldsQuery);
|
||||
const fields: any[] = influxFields.map(
|
||||
(field: any): any => ({
|
||||
label: field.text,
|
||||
value: field.text,
|
||||
children: [],
|
||||
})
|
||||
);
|
||||
measurements.push({
|
||||
label: measurementObj.text,
|
||||
value: measurementObj.text,
|
||||
children: fields,
|
||||
});
|
||||
}
|
||||
this.setState({ measurements });
|
||||
} catch (error) {
|
||||
const message = error && error.message ? error.message : error;
|
||||
this.setState({ error: message });
|
||||
}
|
||||
|
||||
this.setState({ measurements });
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
@@ -107,8 +131,8 @@ export class InfluxLogsQueryField extends React.PureComponent<Props, State> {
|
||||
|
||||
render() {
|
||||
const { datasource } = this.props;
|
||||
const { measurements, measurement, field } = this.state;
|
||||
const cascadeText = measurement ? `Measurements (${measurement}/${field})` : 'Measurements';
|
||||
const { measurements, measurement, field, error } = this.state;
|
||||
const cascadeText = getChooserText({ measurement, field, error });
|
||||
|
||||
return (
|
||||
<div className="gf-form-inline gf-form-inline--nowrap">
|
||||
@@ -119,7 +143,7 @@ export class InfluxLogsQueryField extends React.PureComponent<Props, State> {
|
||||
onChange={this.onMeasurementsChange}
|
||||
expandIcon={null}
|
||||
>
|
||||
<button className="gf-form-label gf-form-label--btn">
|
||||
<button className="gf-form-label gf-form-label--btn" disabled={!measurement}>
|
||||
{cascadeText} <i className="fa fa-caret-down" />
|
||||
</button>
|
||||
</Cascader>
|
||||
@@ -132,6 +156,9 @@ export class InfluxLogsQueryField extends React.PureComponent<Props, State> {
|
||||
extendedOptions={{ measurement }}
|
||||
/>
|
||||
)}
|
||||
{error ? (
|
||||
<span className="gf-form-label gf-form-label--transparent gf-form-label--error m-l-2">{error}</span>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import React, { memo } from 'react';
|
||||
|
||||
// Types
|
||||
import { DataSourceStatus } from '@grafana/ui';
|
||||
import { LokiQuery } from '../types';
|
||||
import { useLokiSyntax } from './useLokiSyntax';
|
||||
import { LokiQueryFieldForm } from './LokiQueryFieldForm';
|
||||
@@ -25,7 +24,6 @@ export const LokiAnnotationsQueryEditor = memo(function LokiAnnotationQueryEdito
|
||||
|
||||
const { isSyntaxReady, setActiveOption, refreshLabels, ...syntaxProps } = useLokiSyntax(
|
||||
datasource.languageProvider,
|
||||
DataSourceStatus.Connected,
|
||||
absolute
|
||||
);
|
||||
|
||||
@@ -38,7 +36,6 @@ export const LokiAnnotationsQueryEditor = memo(function LokiAnnotationQueryEdito
|
||||
<div className="gf-form-group">
|
||||
<LokiQueryFieldForm
|
||||
datasource={datasource}
|
||||
datasourceStatus={DataSourceStatus.Connected}
|
||||
query={query}
|
||||
onChange={(query: LokiQuery) => onChange(query.expr)}
|
||||
onRunQuery={() => {}}
|
||||
|
||||
@@ -3,7 +3,7 @@ import React, { memo } from 'react';
|
||||
|
||||
// Types
|
||||
import { AbsoluteTimeRange } from '@grafana/data';
|
||||
import { QueryEditorProps, DataSourceStatus } from '@grafana/ui';
|
||||
import { QueryEditorProps } from '@grafana/ui';
|
||||
import { LokiDatasource } from '../datasource';
|
||||
import { LokiQuery } from '../types';
|
||||
import { LokiQueryField } from './LokiQueryField';
|
||||
@@ -30,8 +30,6 @@ export const LokiQueryEditor = memo(function LokiQueryEditor(props: Props) {
|
||||
|
||||
const { isSyntaxReady, setActiveOption, refreshLabels, ...syntaxProps } = useLokiSyntax(
|
||||
datasource.languageProvider,
|
||||
// TODO maybe use real status
|
||||
DataSourceStatus.Connected,
|
||||
absolute
|
||||
);
|
||||
|
||||
@@ -39,7 +37,6 @@ export const LokiQueryEditor = memo(function LokiQueryEditor(props: Props) {
|
||||
<div>
|
||||
<LokiQueryField
|
||||
datasource={datasource}
|
||||
datasourceStatus={DataSourceStatus.Connected}
|
||||
query={query}
|
||||
onChange={onChange}
|
||||
onRunQuery={onRunQuery}
|
||||
|
||||
@@ -3,21 +3,15 @@ import { LokiQueryFieldForm, LokiQueryFieldFormProps } from './LokiQueryFieldFor
|
||||
import { useLokiSyntax } from './useLokiSyntax';
|
||||
import LokiLanguageProvider from '../language_provider';
|
||||
|
||||
export const LokiQueryField: FunctionComponent<LokiQueryFieldFormProps> = ({
|
||||
datasource,
|
||||
datasourceStatus,
|
||||
...otherProps
|
||||
}) => {
|
||||
export const LokiQueryField: FunctionComponent<LokiQueryFieldFormProps> = ({ datasource, ...otherProps }) => {
|
||||
const { isSyntaxReady, setActiveOption, refreshLabels, ...syntaxProps } = useLokiSyntax(
|
||||
datasource.languageProvider as LokiLanguageProvider,
|
||||
datasourceStatus,
|
||||
otherProps.absoluteRange
|
||||
);
|
||||
|
||||
return (
|
||||
<LokiQueryFieldForm
|
||||
datasource={datasource}
|
||||
datasourceStatus={datasourceStatus}
|
||||
syntaxLoaded={isSyntaxReady}
|
||||
/**
|
||||
* setActiveOption name is intentional. Because of the way rc-cascader requests additional data
|
||||
|
||||
@@ -15,17 +15,14 @@ import { Plugin, Node } from 'slate';
|
||||
// Types
|
||||
import { LokiQuery } from '../types';
|
||||
import { TypeaheadOutput } from 'app/types/explore';
|
||||
import { ExploreQueryFieldProps, DataSourceStatus, DOMUtil } from '@grafana/ui';
|
||||
import { ExploreQueryFieldProps, DOMUtil } from '@grafana/ui';
|
||||
import { AbsoluteTimeRange } from '@grafana/data';
|
||||
import { Grammar } from 'prismjs';
|
||||
import LokiLanguageProvider, { LokiHistoryItem } from '../language_provider';
|
||||
import { SuggestionsState } from 'app/features/explore/slate-plugins/suggestions';
|
||||
import LokiDatasource from '../datasource';
|
||||
|
||||
function getChooserText(hasSyntax: boolean, hasLogLabels: boolean, datasourceStatus: DataSourceStatus) {
|
||||
if (datasourceStatus === DataSourceStatus.Disconnected) {
|
||||
return '(Disconnected)';
|
||||
}
|
||||
function getChooserText(hasSyntax: boolean, hasLogLabels: boolean) {
|
||||
if (!hasSyntax) {
|
||||
return 'Loading labels...';
|
||||
}
|
||||
@@ -144,21 +141,12 @@ export class LokiQueryFieldForm extends React.PureComponent<LokiQueryFieldFormPr
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
data,
|
||||
query,
|
||||
syntaxLoaded,
|
||||
logLabelOptions,
|
||||
onLoadOptions,
|
||||
onLabelsRefresh,
|
||||
datasource,
|
||||
datasourceStatus,
|
||||
} = this.props;
|
||||
const { data, query, syntaxLoaded, logLabelOptions, onLoadOptions, onLabelsRefresh, datasource } = this.props;
|
||||
const lokiLanguageProvider = datasource.languageProvider as LokiLanguageProvider;
|
||||
const cleanText = datasource.languageProvider ? lokiLanguageProvider.cleanText : undefined;
|
||||
const hasLogLabels = logLabelOptions && logLabelOptions.length > 0;
|
||||
const chooserText = getChooserText(syntaxLoaded, hasLogLabels, datasourceStatus);
|
||||
const buttonDisabled = !syntaxLoaded || datasourceStatus === DataSourceStatus.Disconnected;
|
||||
const chooserText = getChooserText(syntaxLoaded, hasLogLabels);
|
||||
const buttonDisabled = !(syntaxLoaded && hasLogLabels);
|
||||
const showError = data && data.error && data.error.refId === query.refId;
|
||||
|
||||
return (
|
||||
@@ -166,7 +154,7 @@ export class LokiQueryFieldForm extends React.PureComponent<LokiQueryFieldFormPr
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form">
|
||||
<Cascader
|
||||
options={logLabelOptions}
|
||||
options={logLabelOptions || []}
|
||||
onChange={this.onChangeLogLabels}
|
||||
loadData={onLoadOptions}
|
||||
expandIcon={null}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { renderHook, act } from 'react-hooks-testing-library';
|
||||
import LanguageProvider from 'app/plugins/datasource/loki/language_provider';
|
||||
import { useLokiLabels } from './useLokiLabels';
|
||||
import { DataSourceStatus } from '@grafana/ui/src/types/datasource';
|
||||
import { AbsoluteTimeRange } from '@grafana/data';
|
||||
import { makeMockLokiDatasource } from '../mocks';
|
||||
|
||||
@@ -20,49 +19,10 @@ describe('useLokiLabels hook', () => {
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
const { result, waitForNextUpdate } = renderHook(() =>
|
||||
useLokiLabels(languageProvider, true, [], rangeMock, DataSourceStatus.Connected, DataSourceStatus.Connected)
|
||||
);
|
||||
const { result, waitForNextUpdate } = renderHook(() => useLokiLabels(languageProvider, true, [], rangeMock));
|
||||
act(() => result.current.refreshLabels());
|
||||
expect(result.current.logLabelOptions).toEqual([]);
|
||||
await waitForNextUpdate();
|
||||
expect(result.current.logLabelOptions).toEqual(logLabelOptionsMock);
|
||||
});
|
||||
|
||||
it('should force refresh labels after a disconnect', () => {
|
||||
const datasource = makeMockLokiDatasource({});
|
||||
|
||||
const rangeMock: AbsoluteTimeRange = {
|
||||
from: 1560153109000,
|
||||
to: 1560153109000,
|
||||
};
|
||||
|
||||
const languageProvider = new LanguageProvider(datasource);
|
||||
languageProvider.refreshLogLabels = jest.fn();
|
||||
|
||||
renderHook(() =>
|
||||
useLokiLabels(languageProvider, true, [], rangeMock, DataSourceStatus.Connected, DataSourceStatus.Disconnected)
|
||||
);
|
||||
|
||||
expect(languageProvider.refreshLogLabels).toBeCalledTimes(1);
|
||||
expect(languageProvider.refreshLogLabels).toBeCalledWith(rangeMock, true);
|
||||
});
|
||||
|
||||
it('should not force refresh labels after a connect', () => {
|
||||
const datasource = makeMockLokiDatasource({});
|
||||
|
||||
const rangeMock: AbsoluteTimeRange = {
|
||||
from: 1560153109000,
|
||||
to: 1560153109000,
|
||||
};
|
||||
|
||||
const languageProvider = new LanguageProvider(datasource);
|
||||
languageProvider.refreshLogLabels = jest.fn();
|
||||
|
||||
renderHook(() =>
|
||||
useLokiLabels(languageProvider, true, [], rangeMock, DataSourceStatus.Disconnected, DataSourceStatus.Connected)
|
||||
);
|
||||
|
||||
expect(languageProvider.refreshLogLabels).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { DataSourceStatus } from '@grafana/ui/src/types/datasource';
|
||||
import { AbsoluteTimeRange } from '@grafana/data';
|
||||
|
||||
import LokiLanguageProvider from 'app/plugins/datasource/loki/language_provider';
|
||||
@@ -18,18 +17,13 @@ export const useLokiLabels = (
|
||||
languageProvider: LokiLanguageProvider,
|
||||
languageProviderInitialised: boolean,
|
||||
activeOption: CascaderOption[],
|
||||
absoluteRange: AbsoluteTimeRange,
|
||||
datasourceStatus: DataSourceStatus,
|
||||
initialDatasourceStatus?: DataSourceStatus // used for test purposes
|
||||
absoluteRange: AbsoluteTimeRange
|
||||
) => {
|
||||
const mounted = useRefMounted();
|
||||
|
||||
// State
|
||||
const [logLabelOptions, setLogLabelOptions] = useState([]);
|
||||
const [shouldTryRefreshLabels, setRefreshLabels] = useState(false);
|
||||
const [prevDatasourceStatus, setPrevDatasourceStatus] = useState(
|
||||
initialDatasourceStatus || DataSourceStatus.Connected
|
||||
);
|
||||
const [shouldForceRefreshLabels, setForceRefreshLabels] = useState(false);
|
||||
|
||||
// Async
|
||||
@@ -83,15 +77,6 @@ export const useLokiLabels = (
|
||||
}
|
||||
}, [shouldTryRefreshLabels, shouldForceRefreshLabels]);
|
||||
|
||||
// This effect is performed on datasourceStatus state change only.
|
||||
// We want to make sure to only force refresh AFTER a disconnected state thats why we store the previous datasourceStatus in state
|
||||
useEffect(() => {
|
||||
if (datasourceStatus === DataSourceStatus.Connected && prevDatasourceStatus === DataSourceStatus.Disconnected) {
|
||||
setForceRefreshLabels(true);
|
||||
}
|
||||
setPrevDatasourceStatus(datasourceStatus);
|
||||
}, [datasourceStatus]);
|
||||
|
||||
return {
|
||||
logLabelOptions,
|
||||
setLogLabelOptions,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { renderHook, act } from 'react-hooks-testing-library';
|
||||
import { DataSourceStatus } from '@grafana/ui/src/types/datasource';
|
||||
import { AbsoluteTimeRange } from '@grafana/data';
|
||||
|
||||
import LanguageProvider from 'app/plugins/datasource/loki/language_provider';
|
||||
@@ -36,9 +35,7 @@ describe('useLokiSyntax hook', () => {
|
||||
};
|
||||
|
||||
it('should provide Loki syntax when used', async () => {
|
||||
const { result, waitForNextUpdate } = renderHook(() =>
|
||||
useLokiSyntax(languageProvider, DataSourceStatus.Connected, rangeMock)
|
||||
);
|
||||
const { result, waitForNextUpdate } = renderHook(() => useLokiSyntax(languageProvider, rangeMock));
|
||||
expect(result.current.syntax).toEqual(null);
|
||||
|
||||
await waitForNextUpdate();
|
||||
@@ -47,9 +44,7 @@ describe('useLokiSyntax hook', () => {
|
||||
});
|
||||
|
||||
it('should fetch labels on first call', async () => {
|
||||
const { result, waitForNextUpdate } = renderHook(() =>
|
||||
useLokiSyntax(languageProvider, DataSourceStatus.Connected, rangeMock)
|
||||
);
|
||||
const { result, waitForNextUpdate } = renderHook(() => useLokiSyntax(languageProvider, rangeMock));
|
||||
expect(result.current.isSyntaxReady).toBeFalsy();
|
||||
expect(result.current.logLabelOptions).toEqual([]);
|
||||
|
||||
@@ -60,9 +55,7 @@ describe('useLokiSyntax hook', () => {
|
||||
});
|
||||
|
||||
it('should try to fetch missing options when active option changes', async () => {
|
||||
const { result, waitForNextUpdate } = renderHook(() =>
|
||||
useLokiSyntax(languageProvider, DataSourceStatus.Connected, rangeMock)
|
||||
);
|
||||
const { result, waitForNextUpdate } = renderHook(() => useLokiSyntax(languageProvider, rangeMock));
|
||||
await waitForNextUpdate();
|
||||
expect(result.current.logLabelOptions).toEqual(logLabelOptionsMock2);
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import Prism from 'prismjs';
|
||||
import { DataSourceStatus } from '@grafana/ui/src/types/datasource';
|
||||
import { AbsoluteTimeRange } from '@grafana/data';
|
||||
import LokiLanguageProvider from 'app/plugins/datasource/loki/language_provider';
|
||||
import { useLokiLabels } from 'app/plugins/datasource/loki/components/useLokiLabels';
|
||||
@@ -14,11 +13,7 @@ const PRISM_SYNTAX = 'promql';
|
||||
* @param languageProvider
|
||||
* @description Initializes given language provider, exposes Loki syntax and enables loading label option values
|
||||
*/
|
||||
export const useLokiSyntax = (
|
||||
languageProvider: LokiLanguageProvider,
|
||||
datasourceStatus: DataSourceStatus,
|
||||
absoluteRange: AbsoluteTimeRange
|
||||
) => {
|
||||
export const useLokiSyntax = (languageProvider: LokiLanguageProvider, absoluteRange: AbsoluteTimeRange) => {
|
||||
const mounted = useRefMounted();
|
||||
// State
|
||||
const [languageProviderInitialized, setLanguageProviderInitilized] = useState(false);
|
||||
@@ -35,8 +30,7 @@ export const useLokiSyntax = (
|
||||
languageProvider,
|
||||
languageProviderInitialized,
|
||||
activeOption,
|
||||
absoluteRange,
|
||||
datasourceStatus
|
||||
absoluteRange
|
||||
);
|
||||
|
||||
// Async
|
||||
|
||||
@@ -121,7 +121,7 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
||||
|
||||
processError = (err: any, target: any): DataQueryError => {
|
||||
const error: DataQueryError = {
|
||||
message: 'Unknown error during query transaction. Please check JS console logs.',
|
||||
message: (err && err.statusText) || 'Unknown error during query transaction. Please check JS console logs.',
|
||||
refId: target.refId,
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import _ from 'lodash';
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
// Types
|
||||
import { FormLabel, Select, Switch, QueryEditorProps, DataSourceStatus } from '@grafana/ui';
|
||||
import { FormLabel, Select, Switch, QueryEditorProps } from '@grafana/ui';
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
|
||||
import { PrometheusDatasource } from '../datasource';
|
||||
@@ -104,7 +104,6 @@ export class PromQueryEditor extends PureComponent<Props, State> {
|
||||
onChange={this.onFieldChange}
|
||||
history={[]}
|
||||
data={data}
|
||||
datasourceStatus={DataSourceStatus.Connected} // TODO: replace with real DataSourceStatus
|
||||
/>
|
||||
|
||||
<div className="gf-form-inline">
|
||||
|
||||
@@ -13,7 +13,7 @@ import BracesPlugin from 'app/features/explore/slate-plugins/braces';
|
||||
import QueryField, { TypeaheadInput } from 'app/features/explore/QueryField';
|
||||
import { PromQuery, PromContext, PromOptions } from '../types';
|
||||
import { CancelablePromise, makePromiseCancelable } from 'app/core/utils/CancelablePromise';
|
||||
import { ExploreQueryFieldProps, DataSourceStatus, QueryHint, DOMUtil } from '@grafana/ui';
|
||||
import { ExploreQueryFieldProps, QueryHint, DOMUtil } from '@grafana/ui';
|
||||
import { isDataFrame, toLegacyResponseData } from '@grafana/data';
|
||||
import { PrometheusDatasource } from '../datasource';
|
||||
import PromQlLanguageProvider from '../language_provider';
|
||||
@@ -24,13 +24,13 @@ const METRIC_MARK = 'metric';
|
||||
const PRISM_SYNTAX = 'promql';
|
||||
export const RECORDING_RULES_GROUP = '__recording_rules__';
|
||||
|
||||
function getChooserText(hasSyntax: boolean, datasourceStatus: DataSourceStatus) {
|
||||
if (datasourceStatus === DataSourceStatus.Disconnected) {
|
||||
return '(Disconnected)';
|
||||
}
|
||||
function getChooserText(hasSyntax: boolean, metrics: string[]) {
|
||||
if (!hasSyntax) {
|
||||
return 'Loading metrics...';
|
||||
}
|
||||
if (metrics && metrics.length === 0) {
|
||||
return '(No metrics found)';
|
||||
}
|
||||
return 'Metrics';
|
||||
}
|
||||
|
||||
@@ -159,21 +159,6 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
|
||||
if (data && prevProps.data && prevProps.data.series !== data.series) {
|
||||
this.refreshHint();
|
||||
}
|
||||
|
||||
const reconnected =
|
||||
prevProps.datasourceStatus === DataSourceStatus.Disconnected &&
|
||||
this.props.datasourceStatus === DataSourceStatus.Connected;
|
||||
if (!reconnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.languageProviderInitializationPromise) {
|
||||
this.languageProviderInitializationPromise.cancel();
|
||||
}
|
||||
|
||||
if (this.languageProvider) {
|
||||
this.refreshMetrics(makePromiseCancelable(this.languageProvider.fetchMetrics()));
|
||||
}
|
||||
}
|
||||
|
||||
refreshHint = () => {
|
||||
@@ -291,11 +276,11 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
|
||||
};
|
||||
|
||||
render() {
|
||||
const { data, query, datasourceStatus } = this.props;
|
||||
const { data, query } = this.props;
|
||||
const { metricsOptions, syntaxLoaded, hint } = this.state;
|
||||
const cleanText = this.languageProvider ? this.languageProvider.cleanText : undefined;
|
||||
const chooserText = getChooserText(syntaxLoaded, datasourceStatus);
|
||||
const buttonDisabled = !syntaxLoaded || datasourceStatus === DataSourceStatus.Disconnected;
|
||||
const chooserText = getChooserText(syntaxLoaded, metricsOptions);
|
||||
const buttonDisabled = !(syntaxLoaded && metricsOptions && metricsOptions.length > 0);
|
||||
const showError = data && data.error && data.error.refId === query.refId;
|
||||
|
||||
return (
|
||||
|
||||
@@ -9,7 +9,6 @@ exports[`Render PromQueryEditor with basic options should render 1`] = `
|
||||
"getPrometheusTime": [MockFunction],
|
||||
}
|
||||
}
|
||||
datasourceStatus={0}
|
||||
history={Array []}
|
||||
onChange={[Function]}
|
||||
onRunQuery={[Function]}
|
||||
|
||||
@@ -447,7 +447,7 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
|
||||
|
||||
handleErrors = (err: any, target: PromQuery) => {
|
||||
const error: DataQueryError = {
|
||||
message: 'Unknown error during query transaction. Please check JS console logs.',
|
||||
message: (err && err.statusText) || 'Unknown error during query transaction. Please check JS console logs.',
|
||||
refId: target.refId,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user