/usr/share/grafana/public/app/features/query/state/DashboardQueryRunner
import { cloneDeep } from 'lodash'; import { Observable, of } from 'rxjs'; import { AnnotationEvent, AnnotationQuery, DataFrame, DataFrameView, DataSourceApi } from '@grafana/data'; import { config, toDataQueryError } from '@grafana/runtime'; import { dispatch } from 'app/store/store'; import { createErrorNotification } from '../../../../core/copy/appNotification'; import { notifyApp } from '../../../../core/reducers/appNotification'; import { DashboardQueryRunnerWorkerResult } from './types'; export function handleAnnotationQueryRunnerError(err: any): Observable<AnnotationEvent[]> { if (err.cancelled) { return of([]); } notifyWithError('AnnotationQueryRunner failed', err); return of([]); } export function handleDatasourceSrvError(err: any): Observable<DataSourceApi | undefined> { notifyWithError('Failed to retrieve datasource', err); return of(undefined); } export const emptyResult: () => Observable<DashboardQueryRunnerWorkerResult> = () => of({ annotations: [], alertStates: [] }); export function handleDashboardQueryRunnerWorkerError(err: any): Observable<DashboardQueryRunnerWorkerResult> { if (err.cancelled) { return emptyResult(); } notifyWithError('DashboardQueryRunner failed', err); return emptyResult(); } function notifyWithError(title: string, err: any) { const error = toDataQueryError(err); console.error('handleAnnotationQueryRunnerError', error); const notification = createErrorNotification(title, error.message); dispatch(notifyApp(notification)); } export function getAnnotationsByPanelId(annotations: AnnotationEvent[], panelId?: number) { if (panelId == null) { return annotations; } return annotations.filter((item) => { let source: AnnotationQuery; source = item.source; if (!source) { return true; // should not happen } // generic panel filtering if (source.filter) { const includes = (source.filter.ids ?? []).includes(panelId); if (source.filter.exclude) { if (includes) { return false; } } else if (!includes) { return false; } } // this is valid for the main 'grafana' datasource if (item.panelId && item.source.type === 'dashboard') { return item.panelId === panelId; } return true; }); } export function translateQueryResult(annotation: AnnotationQuery, results: AnnotationEvent[]): AnnotationEvent[] { // if annotation has snapshotData // make clone and remove it if (annotation.snapshotData) { annotation = cloneDeep(annotation); delete annotation.snapshotData; } for (const item of results) { item.source = annotation; item.color = config.theme2.visualization.getColorByName(annotation.iconColor); item.type = annotation.name; item.isRegion = Boolean(item.timeEnd && item.time !== item.timeEnd); switch (item.newState?.toLowerCase()) { case 'pending': item.color = 'yellow'; break; case 'alerting': item.color = 'red'; break; case 'ok': item.color = 'green'; break; case 'normal': // ngalert ("normal" instead of "ok") item.color = 'green'; break; case 'no_data': item.color = 'gray'; break; case 'nodata': // ngalert item.color = 'gray'; break; } } return results; } export function annotationsFromDataFrames(data?: DataFrame[]): AnnotationEvent[] { if (!data || !data.length) { return []; } const annotations: AnnotationEvent[] = []; for (const frame of data) { const view = new DataFrameView<AnnotationEvent>(frame); for (let index = 0; index < frame.length; index++) { const annotation = cloneDeep(view.get(index)); annotations.push(annotation); } } return annotations; }
.
Edit
..
Edit
AnnotationsQueryRunner.test.ts
Edit
AnnotationsQueryRunner.ts
Edit
AnnotationsWorker.test.ts
Edit
AnnotationsWorker.ts
Edit
DashboardQueryRunner.test.ts
Edit
DashboardQueryRunner.ts
Edit
LegacyAnnotationQueryRunner.test.ts
Edit
LegacyAnnotationQueryRunner.ts
Edit
PublicAnnotationsDataSource.test.ts
Edit
PublicAnnotationsDataSource.ts
Edit
SnapshotWorker.test.ts
Edit
SnapshotWorker.ts
Edit
UnifiedAlertStatesWorker.test.ts
Edit
UnifiedAlertStatesWorker.ts
Edit
testHelpers.ts
Edit
types.ts
Edit
utils.ts
Edit