Skip to content

Commit

Permalink
feat: use VariableSupport
Browse files Browse the repository at this point in the history
  • Loading branch information
simPod committed Jun 26, 2024
1 parent bee87dd commit 75bdda6
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 26 deletions.
13 changes: 6 additions & 7 deletions src/Component/VariableQueryEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { getTemplateSrv } from '@grafana/runtime';
import { InlineField, InlineFieldRow, InlineSwitch, Input } from '@grafana/ui';
import React, { useState } from 'react';
import { VariableQuery } from '../types';
import { GenericOptions, GrafanaQuery, VariableQuery } from '../types';
import { QueryEditorProps } from '@grafana/data';
import { DataSource } from '../DataSource';

interface Props {
query: VariableQuery;
onChange: (query: VariableQuery, definition: string) => void;
}
export type Props = QueryEditorProps<DataSource, GrafanaQuery, GenericOptions, VariableQuery>;

export const VariableQueryEditor: React.FC<Props> = ({ onChange, query }) => {
export const VariableQueryEditor = ({ onChange, query, datasource, range }: Props) => {
const [variableQuery, setVariableQuery] = useState(query);
const saveQuery = () => {
onChange(variableQuery, `${variableQuery.query}` + `${variableQuery.format === 'json' ? ' (JSON)' : ''}`);
onChange(variableQuery);
};

const handleChange = (event: React.FormEvent<HTMLInputElement>) =>
Expand Down
26 changes: 11 additions & 15 deletions src/DataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
VariableOption,
VariableWithMultiSupport,
} from '@grafana/data';
import { BackendDataSourceResponse, FetchResponse, getTemplateSrv } from '@grafana/runtime';
import { FetchResponse, getTemplateSrv, TemplateSrv } from '@grafana/runtime';
import { isArray, isObject } from 'lodash';
import { lastValueFrom } from 'rxjs';
import { map } from 'rxjs/operators';
Expand All @@ -28,21 +28,27 @@ import {
} from './types';
import { match, P } from 'ts-pattern';
import { valueFromVariableWithMultiSupport } from './variable/valueFromVariableWithMultiSupport';
import { VariableSupport } from './variable/VariableSupport';
import { doFetch } from './doFetch';
import { MetricFindQuery } from './MetricFindQuery';

export class DataSource extends DataSourceApi<GrafanaQuery, GenericOptions> {
url: string;
withCredentials: boolean;
headers: any;
responseParser: ResponseParser;
defaultEditorMode: QueryEditorMode;
constructor(instanceSettings: DataSourceInstanceSettings<GenericOptions>) {
constructor(
instanceSettings: DataSourceInstanceSettings<GenericOptions>,
private readonly templateSrv: TemplateSrv = getTemplateSrv()
) {
super(instanceSettings);

this.responseParser = new ResponseParser();
this.defaultEditorMode = instanceSettings.jsonData?.defaultEditorMode ?? 'code';
this.url = instanceSettings.url === undefined ? '' : instanceSettings.url;

this.variables = new VariableSupport(this, this.templateSrv);
this.withCredentials = instanceSettings.withCredentials !== undefined;
this.headers = { 'Content-Type': 'application/json' };
if (typeof instanceSettings.basicAuth === 'string' && instanceSettings.basicAuth.length > 0) {
Expand Down Expand Up @@ -117,25 +123,15 @@ export class DataSource extends DataSourceApi<GrafanaQuery, GenericOptions> {
}

metricFindQuery(variableQuery: VariableQuery, options?: LegacyMetricFindQueryOptions): Promise<MetricFindValue[]> {
const interpolated =
const interpolated: string =
variableQuery.format === 'json'
? JSON.parse(getTemplateSrv().replace(variableQuery.query, undefined, 'json'))
: {
target: getTemplateSrv().replace(variableQuery.query, undefined, 'regex'),
};

const variableQueryData = {
payload: interpolated,
range: options?.range,
};

return lastValueFrom(
doFetch<BackendDataSourceResponse>(this, {
url: `${this.url}/variable`,
data: variableQueryData,
method: 'POST',
}).pipe(map((response) => this.responseParser.transformMetricFindResponse(response)))
);
let metricFindQuery = new MetricFindQuery(this, interpolated);
return metricFindQuery.process(options?.range);
}

listMetricPayloadOptions(
Expand Down
36 changes: 36 additions & 0 deletions src/MetricFindQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { getDefaultTimeRange, MetricFindValue, TimeRange } from '@grafana/data';

import { DataSource } from './DataSource';
import { lastValueFrom } from 'rxjs';
import { doFetch } from './doFetch';
import { BackendDataSourceResponse } from '@grafana/runtime';
import { map } from 'rxjs/operators';
import { ResponseParser } from './response_parser';

export class MetricFindQuery {
range: TimeRange;
responseParser: ResponseParser;

constructor(
private datasource: DataSource,
private query: string
) {
this.datasource = datasource;
this.query = query;
this.range = getDefaultTimeRange();
this.responseParser = new ResponseParser();
}

process(timeRange: TimeRange | undefined = getDefaultTimeRange()): Promise<MetricFindValue[]> {
return lastValueFrom(
doFetch<BackendDataSourceResponse>(this.datasource, {
url: `${this.datasource.url}/variable`,
data: {
payload: this.query,
range: timeRange,
},
method: 'POST',
}).pipe(map((response) => this.responseParser.transformMetricFindResponse(response)))
);
}
}
4 changes: 1 addition & 3 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ import { ConfigEditor } from './Component/ConfigEditor';
import { QueryEditorContainer } from './Component/QueryEditorContainer';
import { DataSource } from './DataSource';
import { GenericOptions, GrafanaQuery } from './types';
import { VariableQueryEditor } from './Component/VariableQueryEditor';

export const plugin = new DataSourcePlugin<DataSource, GrafanaQuery, GenericOptions>(DataSource)
.setConfigEditor(ConfigEditor)
.setQueryEditor(QueryEditorContainer)
.setVariableQueryEditor(VariableQueryEditor);
.setQueryEditor(QueryEditorContainer);
2 changes: 1 addition & 1 deletion src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface GenericOptions extends DataSourceJsonData {
defaultEditorMode?: QueryEditorMode;
}

export interface VariableQuery {
export interface VariableQuery extends DataQuery {
query: string;
format: 'string' | 'json';
}
Expand Down
56 changes: 56 additions & 0 deletions src/variable/VariableSupport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/variables.ts
import { from, Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';

import { CustomVariableSupport, DataQueryRequest, DataQueryResponse, rangeUtil } from '@grafana/data';
import { getTemplateSrv, TemplateSrv } from '@grafana/runtime';

import { DataSource } from '../DataSource';
import { VariableQueryEditor } from '../Component/VariableQueryEditor';
import { VariableQuery } from '../types';
import { MetricFindQuery } from '../MetricFindQuery';

export class VariableSupport extends CustomVariableSupport<DataSource> {
// export class VariableSupport extends DataSourceVariableSupport<DataSource> {
constructor(
private readonly datasource: DataSource,
private readonly templateSrv: TemplateSrv = getTemplateSrv()
) {
super();
}

editor = VariableQueryEditor;

query(request: DataQueryRequest<VariableQuery>): Observable<DataQueryResponse> {
const query = typeof request.targets[0] === 'string' ? request.targets[0] : request.targets[0];

if (!query) {
return of({ data: [] });
}

const scopedVars = {
...request.scopedVars,
__interval: { text: this.datasource.interval, value: this.datasource.interval },
__interval_ms:
this.datasource.interval === undefined
? undefined
: {
text: rangeUtil.intervalToMs(this.datasource.interval),
value: rangeUtil.intervalToMs(this.datasource.interval),
},
// ...this.datasource.getRangeScopedVars(request.range),
};

const interpolated: string =
query.format === 'json'
? JSON.parse(this.templateSrv.replace(query.query, scopedVars, 'json'))
: {
target: this.templateSrv.replace(query.query, scopedVars, 'regex'),
};

const metricFindQuery = new MetricFindQuery(this.datasource, interpolated);
const metricFindStream = from(metricFindQuery.process(request.range));

return metricFindStream.pipe(map((results) => ({ data: results })));
}
}

0 comments on commit 75bdda6

Please sign in to comment.