mirror of
https://github.com/grafana/grafana.git
synced 2025-02-20 11:48:34 -06:00
Backend Plugins: add a common implementation (#21408)
* add common backend * use const for range * likely not differnt * send the right orgId * Add DataSourceWithBackend to @grafana/runtime mock in root reducer test Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
This commit is contained in:
parent
d135f1229d
commit
a0d43de761
@ -3,3 +3,5 @@ export * from './config';
|
||||
export * from './types';
|
||||
export { loadPluginCss, SystemJS } from './utils/plugin';
|
||||
export { reportMetaAnalytics } from './utils/analytics';
|
||||
|
||||
export { DataSourceWithBackend } from './utils/DataSourceWithBackend';
|
||||
|
87
packages/grafana-runtime/src/utils/DataSourceWithBackend.ts
Normal file
87
packages/grafana-runtime/src/utils/DataSourceWithBackend.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import {
|
||||
DataSourceApi,
|
||||
DataQueryRequest,
|
||||
DataQueryResponse,
|
||||
DataSourceInstanceSettings,
|
||||
DataQuery,
|
||||
DataSourceJsonData,
|
||||
} from '@grafana/data';
|
||||
import { Observable, from } from 'rxjs';
|
||||
import { config } from '..';
|
||||
import { getBackendSrv } from '../services';
|
||||
|
||||
// Ideally internal (exported for consistency)
|
||||
const ExpressionDatasourceID = '__expr__';
|
||||
|
||||
export class DataSourceWithBackend<
|
||||
TQuery extends DataQuery = DataQuery,
|
||||
TOptions extends DataSourceJsonData = DataSourceJsonData
|
||||
> extends DataSourceApi<TQuery, TOptions> {
|
||||
constructor(instanceSettings: DataSourceInstanceSettings<TOptions>) {
|
||||
super(instanceSettings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ideally final -- any other implementation would be wrong!
|
||||
*/
|
||||
query(request: DataQueryRequest): Observable<DataQueryResponse> {
|
||||
const { targets, intervalMs, maxDataPoints, range } = request;
|
||||
|
||||
let expressionCount = 0;
|
||||
const orgId = config.bootData.user.orgId;
|
||||
const queries = targets.map(q => {
|
||||
if (q.datasource === ExpressionDatasourceID) {
|
||||
expressionCount++;
|
||||
return {
|
||||
...q,
|
||||
datasourceId: this.id,
|
||||
orgId,
|
||||
};
|
||||
}
|
||||
const dsName = q.datasource && q.datasource !== 'default' ? q.datasource : config.defaultDatasource;
|
||||
const ds = config.datasources[dsName];
|
||||
if (!ds) {
|
||||
throw new Error('Unknown Datasource: ' + q.datasource);
|
||||
}
|
||||
return {
|
||||
...q,
|
||||
datasourceId: ds.id,
|
||||
intervalMs,
|
||||
maxDataPoints,
|
||||
orgId,
|
||||
};
|
||||
});
|
||||
|
||||
const body: any = {
|
||||
expressionCount,
|
||||
queries,
|
||||
};
|
||||
if (range) {
|
||||
body.range = range;
|
||||
body.from = range.from.valueOf().toString();
|
||||
body.to = range.to.valueOf().toString();
|
||||
}
|
||||
|
||||
const req: Promise<DataQueryResponse> = getBackendSrv()
|
||||
.post('/api/ds/query', body)
|
||||
.then((rsp: any) => {
|
||||
return this.toDataQueryResponse(rsp);
|
||||
});
|
||||
return from(req);
|
||||
}
|
||||
|
||||
/**
|
||||
* This makes the arrow libary loading async.
|
||||
*/
|
||||
async toDataQueryResponse(rsp: any): Promise<DataQueryResponse> {
|
||||
const { resultsToDataFrames } = await import(
|
||||
/* webpackChunkName: "apache-arrow-util" */ '@grafana/data/src/dataframe/ArrowDataFrame'
|
||||
);
|
||||
return { data: resultsToDataFrames(rsp) };
|
||||
}
|
||||
|
||||
testDatasource() {
|
||||
// TODO, this will call the backend healthcheck endpoint
|
||||
return Promise.resolve({});
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ jest.mock('@grafana/runtime', () => ({
|
||||
user: {},
|
||||
},
|
||||
},
|
||||
DataSourceWithBackend: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('recursiveCleanState', () => {
|
||||
|
@ -1,20 +1,12 @@
|
||||
import {
|
||||
DataSourceApi,
|
||||
DataQueryRequest,
|
||||
DataQueryResponse,
|
||||
DataSourceInstanceSettings,
|
||||
DataSourcePluginMeta,
|
||||
} from '@grafana/data';
|
||||
import { DataSourceInstanceSettings, DataSourcePluginMeta } from '@grafana/data';
|
||||
import { ExpressionQuery, GELQueryType } from './types';
|
||||
import { ExpressionQueryEditor } from './ExpressionQueryEditor';
|
||||
import { Observable, from } from 'rxjs';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { getBackendSrv } from 'app/core/services/backend_srv';
|
||||
import { DataSourceWithBackend } from '@grafana/runtime';
|
||||
|
||||
/**
|
||||
* This is a singleton instance that just pretends to be a DataSource
|
||||
*/
|
||||
export class ExpressionDatasourceApi extends DataSourceApi<ExpressionQuery> {
|
||||
export class ExpressionDatasourceApi extends DataSourceWithBackend<ExpressionQuery> {
|
||||
constructor(instanceSettings: DataSourceInstanceSettings) {
|
||||
super(instanceSettings);
|
||||
}
|
||||
@ -23,61 +15,6 @@ export class ExpressionDatasourceApi extends DataSourceApi<ExpressionQuery> {
|
||||
return `Expression: ${query.type}`;
|
||||
}
|
||||
|
||||
query(request: DataQueryRequest): Observable<DataQueryResponse> {
|
||||
const { targets, intervalMs, maxDataPoints, range } = request;
|
||||
|
||||
let expressionCount = 0;
|
||||
const orgId = (window as any).grafanaBootData.user.orgId;
|
||||
const queries = targets.map(q => {
|
||||
if (q.datasource === ExpressionDatasourceID) {
|
||||
expressionCount++;
|
||||
return {
|
||||
...q,
|
||||
datasourceId: this.id,
|
||||
orgId,
|
||||
};
|
||||
}
|
||||
const dsName = q.datasource && q.datasource !== 'default' ? q.datasource : config.defaultDatasource;
|
||||
const ds = config.datasources[dsName];
|
||||
if (!ds) {
|
||||
throw new Error('Unknown Datasource: ' + q.datasource);
|
||||
}
|
||||
return {
|
||||
...q,
|
||||
datasourceId: ds.id,
|
||||
intervalMs,
|
||||
maxDataPoints,
|
||||
orgId,
|
||||
};
|
||||
});
|
||||
const req: Promise<DataQueryResponse> = getBackendSrv()
|
||||
.post('/api/ds/query', {
|
||||
from: range.from.valueOf().toString(),
|
||||
to: range.to.valueOf().toString(),
|
||||
queries: queries,
|
||||
range,
|
||||
expressionCount,
|
||||
})
|
||||
.then((rsp: any) => {
|
||||
return this.toDataQueryResponse(rsp);
|
||||
});
|
||||
return from(req);
|
||||
}
|
||||
|
||||
/**
|
||||
* This makes the arrow libary loading async.
|
||||
*/
|
||||
async toDataQueryResponse(rsp: any): Promise<DataQueryResponse> {
|
||||
const { resultsToDataFrames } = await import(
|
||||
/* webpackChunkName: "apache-arrow-util" */ '@grafana/data/src/dataframe/ArrowDataFrame'
|
||||
);
|
||||
return { data: resultsToDataFrames(rsp) };
|
||||
}
|
||||
|
||||
testDatasource() {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
|
||||
newQuery(): ExpressionQuery {
|
||||
return {
|
||||
refId: '--', // Replaced with query
|
||||
@ -87,7 +24,9 @@ export class ExpressionDatasourceApi extends DataSourceApi<ExpressionQuery> {
|
||||
}
|
||||
}
|
||||
|
||||
// MATCHES the constant in DataSourceWithBackend
|
||||
export const ExpressionDatasourceID = '__expr__';
|
||||
|
||||
export const expressionDatasource = new ExpressionDatasourceApi({
|
||||
id: -100,
|
||||
name: ExpressionDatasourceID,
|
||||
|
Loading…
Reference in New Issue
Block a user