Add support for annotations

DevelopersAdd support for annotations

This guide explains how to add support for annotations to an existing data source plugin.

This guide assumes that you’re already familiar with how to Build a data source plugin.

Data sources in Grafana can support Annotations by handling annotation queries.

Handling annotation queries is similar to how you’d handle a metrics query. The difference is that instead of returning data frames, an annotation query returns annotation events.

Add annotations support to your data source

To add logs support to an existing data source, you need to:

  • Enable annotations support
  • Override the annotationQuery method
  • Construct annotation events

Enable annotations support

Tell Grafana that your data source plugin can return annotations events by adding "annotations": true to the plugin.json file.

{
  "annotations": true
}

Override the annotationQuery method

In DataSource.ts, override the annotationQuery method from DataSourceApi.

async annotationQuery(options: AnnotationQueryRequest<MyQuery>): Promise<AnnotationEvent[]> {
  return [];
}

Construct annotation events

Return an array of AnnotationEvent.

async annotationQuery(options: AnnotationQueryRequest<MyQuery>): Promise<AnnotationEvent[]> {
  const events: AnnotationEvent[] = [];

  const date = new Date();

  const event: AnnotationEvent = {
    time: date.valueOf(),
    text: 'foo',
    tags: ['bar'],
  };

  events.push(event);

  return events;
}

Region annotations

Region annotations have a start and end time. This can for example be used to annotate maintenance windows or downtime.

To return a region annotation, set the timeEnd, and isRegion properties.

const regionEvent: AnnotationEvent = {
  time: startDate.valueOf(),
  timeEnd: endDate.valueOf(),
  isRegion: true,
  text: 'foo',
  tags: ['bar'],
};

Build a annotation query editor

Let users write custom annotation queries to only display the annotation events they care about, by adding a query editor.

Note: Annotation query editors have yet to receive support for React. The instructions here are given for Angular. Fortunately, you can run Angular even in a plugin otherwise written using React. This section will be updated once React support for annotation queries editors is available.

  1. Create a file called AnnotationQueryEditor.ts in the plugin root directory, with the following content.

    export class AnnotationQueryEditor {
      static templateUrl = 'partials/annotations.editor.html';
    
      annotation: any;
    
      constructor() {
        this.annotation.rawQuery = this.annotation.rawQuery || '';
      }
    }
    
  2. Create a directory called partials in the plugin root directory.

  3. Create a file called annotations.editor.html in the partials directory you just created, with the following content.

    <div class="gf-form-group">
      <div class="gf-form-inline">
        <div class="gf-form gf-form--grow">
          <input
           class="gf-form-input"
           placeholder="query expression"
           ng-model="ctrl.annotation.queryText"
           ></input>
        </div>
      </div>
    </div>
    
  4. In your data source query—the one that extends DataQuery—add the queryText property. The name of the property needs to correspond to the text in ng-model, e.g. ctrl.annotation.<propertyName>.

    export interface MyQuery extends DataQuery {
      // ...
      queryText?: string;
    }
    
  5. In module.ts, add the annotation query editor to the plugin.

    import { AnnotationQueryEditor } from './AnnotationQueryEditor';
    
    export const plugin = new DataSourcePlugin<DataSource, MyQuery, MyDataSourceOptions>(DataSource)
      .setConfigEditor(ConfigEditor)
      .setQueryEditor(QueryEditor)
      .setAnnotationQueryCtrl(AnnotationQueryEditor);
    

The queryText property is now available on the options object in the annotationQuery method:

async annotationQuery(options: AnnotationQueryRequest<MyQuery>): Promise<AnnotationEvent[]> {
  const expression = options.annotation.queryText;

  // ...
}