Exemplars: Disable exemplars only on query it failed (#37296)

This commit is contained in:
Zoltán Bedi 2021-07-28 16:34:46 +02:00 committed by GitHub
parent 99891e1a88
commit 9a62db6943
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 21 additions and 12 deletions

View File

@ -3,25 +3,27 @@ import { IconButton, InlineLabel, Tooltip, useStyles2 } from '@grafana/ui';
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { PrometheusDatasource } from '../datasource'; import { PrometheusDatasource } from '../datasource';
import { filter } from 'rxjs/operators';
interface Props { interface Props {
isEnabled: boolean; isEnabled: boolean;
onChange: (isEnabled: boolean) => void; onChange: (isEnabled: boolean) => void;
datasource: PrometheusDatasource; datasource: PrometheusDatasource;
refId: string;
} }
export function PromExemplarField({ datasource, onChange, isEnabled }: Props) { export function PromExemplarField({ datasource, onChange, isEnabled, refId }: Props) {
const [error, setError] = useState<string>(); const [error, setError] = useState<string | null>(null);
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
useEffect(() => { useEffect(() => {
const subscription = datasource.exemplarErrors.subscribe((err) => { const subscription = datasource.exemplarErrors.pipe(filter((value) => refId === value.refId)).subscribe((err) => {
setError(err); setError(err.error);
}); });
return () => { return () => {
subscription.unsubscribe(); subscription.unsubscribe();
}; };
}, [datasource]); }, [datasource, refId]);
const iconButtonStyles = cx( const iconButtonStyles = cx(
{ {

View File

@ -78,6 +78,7 @@ export const PromExploreExtraField: React.FC<PromExploreExtraFieldProps> = memo(
</div> </div>
<PromExemplarField <PromExemplarField
refId={query.refId}
isEnabled={Boolean(query.exemplar)} isEnabled={Boolean(query.exemplar)}
onChange={(isEnabled) => onChange({ ...query, exemplar: isEnabled })} onChange={(isEnabled) => onChange({ ...query, exemplar: isEnabled })}
datasource={datasource} datasource={datasource}

View File

@ -223,7 +223,12 @@ export class PromQueryEditor extends PureComponent<PromQueryEditorProps, State>
/> />
</InlineFormLabel> </InlineFormLabel>
</div> </div>
<PromExemplarField isEnabled={exemplar} onChange={this.onExemplarChange} datasource={datasource} /> <PromExemplarField
refId={query.refId}
isEnabled={exemplar}
onChange={this.onExemplarChange}
datasource={datasource}
/>
</div> </div>
} }
/> />

View File

@ -203,6 +203,7 @@ exports[`Render PromQueryEditor with basic options should render 1`] = `
} }
isEnabled={true} isEnabled={true}
onChange={[Function]} onChange={[Function]}
refId="A"
/> />
</div> </div>
} }

View File

@ -45,7 +45,7 @@ import PrometheusMetricFindQuery from './metric_find_query';
import { DEFAULT_STEP_MODE } from './components/PromQueryEditor'; import { DEFAULT_STEP_MODE } from './components/PromQueryEditor';
export const ANNOTATION_QUERY_STEP_DEFAULT = '60s'; export const ANNOTATION_QUERY_STEP_DEFAULT = '60s';
const EXEMPLARS_NOT_AVAILABLE = 'Exemplars for this data source are not available.'; const EXEMPLARS_NOT_AVAILABLE = 'Exemplars for this query are not available.';
const GET_AND_POST_METADATA_ENDPOINTS = ['api/v1/query', 'api/v1/query_range', 'api/v1/series', 'api/v1/labels']; const GET_AND_POST_METADATA_ENDPOINTS = ['api/v1/query', 'api/v1/query_range', 'api/v1/series', 'api/v1/labels'];
export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions> { export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions> {
@ -64,7 +64,7 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
exemplarTraceIdDestinations: ExemplarTraceIdDestination[] | undefined; exemplarTraceIdDestinations: ExemplarTraceIdDestination[] | undefined;
lookupsDisabled: boolean; lookupsDisabled: boolean;
customQueryParameters: any; customQueryParameters: any;
exemplarErrors: Subject<string> = new Subject(); exemplarErrors: Subject<{ refId: string; error: string | null }> = new Subject();
constructor( constructor(
instanceSettings: DataSourceInstanceSettings<PromOptions>, instanceSettings: DataSourceInstanceSettings<PromOptions>,
@ -267,12 +267,12 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
exemplarTarget.requestId += '_exemplar'; exemplarTarget.requestId += '_exemplar';
queries.push(this.createQuery(exemplarTarget, options, start, end)); queries.push(this.createQuery(exemplarTarget, options, start, end));
activeTargets.push(exemplarTarget); activeTargets.push(exemplarTarget);
this.exemplarErrors.next(); this.exemplarErrors.next({ refId: exemplarTarget.refId, error: null });
} }
target.exemplar = false; target.exemplar = false;
} }
if (target.exemplar && target.instant) { if (target.exemplar && target.instant) {
this.exemplarErrors.next('Exemplars are not available for instant queries.'); this.exemplarErrors.next({ refId: target.refId, error: 'Exemplars are not available for instant queries.' });
} }
queries.push(this.createQuery(target, options, start, end)); queries.push(this.createQuery(target, options, start, end));
activeTargets.push(target); activeTargets.push(target);
@ -385,8 +385,8 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
if (query.exemplar) { if (query.exemplar) {
return this.getExemplars(query).pipe( return this.getExemplars(query).pipe(
catchError((err: FetchError) => { catchError(() => {
this.exemplarErrors.next(EXEMPLARS_NOT_AVAILABLE); this.exemplarErrors.next({ refId: query.refId, error: EXEMPLARS_NOT_AVAILABLE });
return of({ return of({
data: [], data: [],
state: LoadingState.Done, state: LoadingState.Done,