utils.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { cloneDeep } from 'lodash';
  2. import { Observable, of } from 'rxjs';
  3. import { AnnotationEvent, AnnotationQuery, DataFrame, DataFrameView, DataSourceApi } from '@grafana/data';
  4. import { config, toDataQueryError } from '@grafana/runtime';
  5. import { dispatch } from 'app/store/store';
  6. import { createErrorNotification } from '../../../../core/copy/appNotification';
  7. import { notifyApp } from '../../../../core/reducers/appNotification';
  8. import { DashboardQueryRunnerWorkerResult } from './types';
  9. export function handleAnnotationQueryRunnerError(err: any): Observable<AnnotationEvent[]> {
  10. if (err.cancelled) {
  11. return of([]);
  12. }
  13. notifyWithError('AnnotationQueryRunner failed', err);
  14. return of([]);
  15. }
  16. export function handleDatasourceSrvError(err: any): Observable<DataSourceApi | undefined> {
  17. notifyWithError('Failed to retrieve datasource', err);
  18. return of(undefined);
  19. }
  20. export const emptyResult: () => Observable<DashboardQueryRunnerWorkerResult> = () =>
  21. of({ annotations: [], alertStates: [] });
  22. export function handleDashboardQueryRunnerWorkerError(err: any): Observable<DashboardQueryRunnerWorkerResult> {
  23. if (err.cancelled) {
  24. return emptyResult();
  25. }
  26. notifyWithError('DashboardQueryRunner failed', err);
  27. return emptyResult();
  28. }
  29. function notifyWithError(title: string, err: any) {
  30. const error = toDataQueryError(err);
  31. console.error('handleAnnotationQueryRunnerError', error);
  32. const notification = createErrorNotification(title, error.message);
  33. dispatch(notifyApp(notification));
  34. }
  35. export function getAnnotationsByPanelId(annotations: AnnotationEvent[], panelId?: number) {
  36. return annotations.filter((item) => {
  37. if (panelId !== undefined && item.panelId && item.source?.type === 'dashboard') {
  38. return item.panelId === panelId;
  39. }
  40. return true;
  41. });
  42. }
  43. export function translateQueryResult(annotation: AnnotationQuery, results: AnnotationEvent[]): AnnotationEvent[] {
  44. // if annotation has snapshotData
  45. // make clone and remove it
  46. if (annotation.snapshotData) {
  47. annotation = cloneDeep(annotation);
  48. delete annotation.snapshotData;
  49. }
  50. for (const item of results) {
  51. item.source = annotation;
  52. item.color = config.theme2.visualization.getColorByName(annotation.iconColor);
  53. item.type = annotation.name;
  54. item.isRegion = Boolean(item.timeEnd && item.time !== item.timeEnd);
  55. switch (item.newState?.toLowerCase()) {
  56. case 'pending':
  57. item.color = 'yellow';
  58. break;
  59. case 'alerting':
  60. item.color = 'red';
  61. break;
  62. case 'ok':
  63. item.color = 'green';
  64. break;
  65. case 'normal': // ngalert ("normal" instead of "ok")
  66. item.color = 'green';
  67. break;
  68. case 'no_data':
  69. item.color = 'gray';
  70. break;
  71. case 'nodata': // ngalert
  72. item.color = 'gray';
  73. break;
  74. }
  75. }
  76. return results;
  77. }
  78. export function annotationsFromDataFrames(data?: DataFrame[]): AnnotationEvent[] {
  79. if (!data || !data.length) {
  80. return [];
  81. }
  82. const annotations: AnnotationEvent[] = [];
  83. for (const frame of data) {
  84. const view = new DataFrameView<AnnotationEvent>(frame);
  85. for (let index = 0; index < frame.length; index++) {
  86. const annotation = cloneDeep(view.get(index));
  87. annotations.push(annotation);
  88. }
  89. }
  90. return annotations;
  91. }