diff --git a/.betterer.results b/.betterer.results index 1c962564432..861cd743365 100644 --- a/.betterer.results +++ b/.betterer.results @@ -7288,12 +7288,14 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "52"], [0, 0, 0, "Unexpected any. Specify a different type.", "53"], [0, 0, 0, "Unexpected any. Specify a different type.", "54"], - [0, 0, 0, "Unexpected any. Specify a different type.", "55"], - [0, 0, 0, "Do not use any type assertions.", "56"], + [0, 0, 0, "Do not use any type assertions.", "55"], + [0, 0, 0, "Unexpected any. Specify a different type.", "56"], [0, 0, 0, "Unexpected any. Specify a different type.", "57"], [0, 0, 0, "Unexpected any. Specify a different type.", "58"], - [0, 0, 0, "Unexpected any. Specify a different type.", "59"], - [0, 0, 0, "Unexpected any. Specify a different type.", "60"] + [0, 0, 0, "Unexpected any. Specify a different type.", "59"] + ], + "public/app/plugins/datasource/opentsdb/migrations.ts:5381": [ + [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], "public/app/plugins/datasource/opentsdb/query_ctrl.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], diff --git a/public/app/plugins/datasource/opentsdb/components/AnnotationEditor.tsx b/public/app/plugins/datasource/opentsdb/components/AnnotationEditor.tsx new file mode 100644 index 00000000000..80c69846b8a --- /dev/null +++ b/public/app/plugins/datasource/opentsdb/components/AnnotationEditor.tsx @@ -0,0 +1,45 @@ +import React, { useState } from 'react'; + +import { QueryEditorProps } from '@grafana/data'; +import { InlineFormLabel, Input, InlineSwitch } from '@grafana/ui'; + +import OpenTsDatasource from '../datasource'; +import { OpenTsdbQuery, OpenTsdbOptions } from '../types'; + +export const AnnotationEditor = (props: QueryEditorProps) => { + const { query, onChange } = props; + const [target, setTarget] = useState(query.target ?? ''); + const [isGlobal, setIsGlobal] = useState(query.isGlobal ?? false); + + const updateValue = (key: K, val: V) => { + onChange({ + ...query, + [key]: val, + fromAnnotations: true, + }); + }; + + const updateIsGlobal = (isGlobal: boolean) => { + isGlobal = !isGlobal; + setIsGlobal(isGlobal); + updateValue('isGlobal', isGlobal); + }; + + return ( +
+
+ OpenTSDB metrics query + setTarget(e.currentTarget.value ?? '')} + onBlur={() => updateValue('target', target)} + placeholder="events.eventname" + /> +
+
+ Show Global Annotations? + updateIsGlobal(isGlobal)} /> +
+
+ ); +}; diff --git a/public/app/plugins/datasource/opentsdb/datasource.ts b/public/app/plugins/datasource/opentsdb/datasource.ts index ca681e730a1..f05d97b52e7 100644 --- a/public/app/plugins/datasource/opentsdb/datasource.ts +++ b/public/app/plugins/datasource/opentsdb/datasource.ts @@ -13,7 +13,7 @@ import { map as _map, toPairs, } from 'lodash'; -import { lastValueFrom, Observable, of } from 'rxjs'; +import { lastValueFrom, merge, Observable, of } from 'rxjs'; import { catchError, map } from 'rxjs/operators'; import { @@ -23,10 +23,13 @@ import { DataSourceApi, dateMath, ScopedVars, + toDataFrame, } from '@grafana/data'; import { FetchResponse, getBackendSrv } from '@grafana/runtime'; import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv'; +import { AnnotationEditor } from './components/AnnotationEditor'; +import { prepareAnnotation } from './migrations'; import { OpenTsdbOptions, OpenTsdbQuery } from './types'; export default class OpenTsDatasource extends DataSourceApi { @@ -58,10 +61,39 @@ export default class OpenTsDatasource extends DataSourceApi): Observable { + // migrate annotations + if (options.targets.some((target: OpenTsdbQuery) => target.fromAnnotations)) { + const streams: Array> = []; + + for (const annotation of options.targets) { + if (annotation.target) { + streams.push( + new Observable((subscriber) => { + this.annotationEvent(options, annotation) + .then((events) => subscriber.next({ data: [toDataFrame(events)] })) + .catch((ex) => { + // grafana fetch throws the error so for annotation consistency among datasources + // we return an empty array which displays as 'no events found' + // in the annnotation editor + return subscriber.next({ data: [toDataFrame([])] }); + }) + .finally(() => subscriber.complete()); + }) + ); + } + } + + return merge(...streams); + } + const start = this.convertToTSDBTime(options.range.raw.from, false, options.timezone); const end = this.convertToTSDBTime(options.range.raw.to, true, options.timezone); const qs: any[] = []; @@ -124,13 +156,13 @@ export default class OpenTsDatasource extends DataSourceApi { - const start = this.convertToTSDBTime(options.rangeRaw.from, false, options.timezone); - const end = this.convertToTSDBTime(options.rangeRaw.to, true, options.timezone); + annotationEvent(options: DataQueryRequest, annotation: OpenTsdbQuery): Promise { + const start = this.convertToTSDBTime(options.range.raw.from, false, options.timezone); + const end = this.convertToTSDBTime(options.range.raw.to, true, options.timezone); const qs = []; const eventList: any[] = []; - qs.push({ aggregator: 'sum', metric: options.annotation.target }); + qs.push({ aggregator: 'sum', metric: annotation.target }); const queries = compact(qs); @@ -139,15 +171,15 @@ export default class OpenTsDatasource extends DataSourceApi { if (results.data[0]) { let annotationObject = results.data[0].annotations; - if (options.annotation.isGlobal) { + if (annotation.isGlobal) { annotationObject = results.data[0].globalAnnotations; } if (annotationObject) { - each(annotationObject, (annotation) => { + each(annotationObject, (ann) => { const event = { - text: annotation.description, - time: Math.floor(annotation.startTime) * 1000, - annotation: options.annotation, + text: ann.description, + time: Math.floor(ann.startTime) * 1000, + annotation: annotation, }; eventList.push(event); diff --git a/public/app/plugins/datasource/opentsdb/migrations.ts b/public/app/plugins/datasource/opentsdb/migrations.ts new file mode 100644 index 00000000000..90e5795c4ef --- /dev/null +++ b/public/app/plugins/datasource/opentsdb/migrations.ts @@ -0,0 +1,23 @@ +import { LegacyAnnotation } from './types'; + +// this becomes the target in the migrated annotations +const migrateLegacyAnnotation = (json: LegacyAnnotation) => { + // return the target annotation + const annotation: LegacyAnnotation = { + fromAnnotations: true, + target: json.target ?? '', + name: json.name ?? '', + isGlobal: json.isGlobal ?? false, + }; + + return annotation; +}; + +// eslint-ignore-next-line +export const prepareAnnotation = (json: any) => { + const resultingTarget = json.target && typeof json.target !== 'string' ? json.target : migrateLegacyAnnotation(json); + + json.target = resultingTarget; + + return json; +}; diff --git a/public/app/plugins/datasource/opentsdb/module.ts b/public/app/plugins/datasource/opentsdb/module.ts index f84df8875aa..39eac6b2eb9 100644 --- a/public/app/plugins/datasource/opentsdb/module.ts +++ b/public/app/plugins/datasource/opentsdb/module.ts @@ -4,11 +4,6 @@ import { ConfigEditor } from './components/ConfigEditor'; import OpenTsDatasource from './datasource'; import { OpenTsQueryCtrl } from './query_ctrl'; -class AnnotationsQueryCtrl { - static templateUrl = 'partials/annotations.editor.html'; -} - export const plugin = new DataSourcePlugin(OpenTsDatasource) .setQueryCtrl(OpenTsQueryCtrl) - .setConfigEditor(ConfigEditor) - .setAnnotationQueryCtrl(AnnotationsQueryCtrl); + .setConfigEditor(ConfigEditor); diff --git a/public/app/plugins/datasource/opentsdb/partials/annotations.editor.html b/public/app/plugins/datasource/opentsdb/partials/annotations.editor.html deleted file mode 100644 index 914672053ae..00000000000 --- a/public/app/plugins/datasource/opentsdb/partials/annotations.editor.html +++ /dev/null @@ -1,7 +0,0 @@ -
-
- OpenTSDB metrics query - -
- -
diff --git a/public/app/plugins/datasource/opentsdb/types.ts b/public/app/plugins/datasource/opentsdb/types.ts index 4a5cf58eb47..909feeb9cbe 100644 --- a/public/app/plugins/datasource/opentsdb/types.ts +++ b/public/app/plugins/datasource/opentsdb/types.ts @@ -2,6 +2,11 @@ import { DataQuery, DataSourceJsonData } from '@grafana/data'; export interface OpenTsdbQuery extends DataQuery { metric?: any; + // annotation attrs + fromAnnotations?: boolean; + isGlobal?: boolean; + target?: string; + name?: string; } export interface OpenTsdbOptions extends DataSourceJsonData { @@ -9,3 +14,10 @@ export interface OpenTsdbOptions extends DataSourceJsonData { tsdbResolution: number; lookupLimit: number; } + +export type LegacyAnnotation = { + fromAnnotations?: boolean; + isGlobal?: boolean; + target?: string; + name?: string; +};