Mix backend and frontend queries from one panel
This commit is contained in:
@@ -15,7 +15,7 @@ import problemsHandler from './problemsHandler';
|
|||||||
import { Zabbix } from './zabbix/zabbix';
|
import { Zabbix } from './zabbix/zabbix';
|
||||||
import { ZabbixAPIError } from './zabbix/connectors/zabbix_api/zabbixAPIConnector';
|
import { ZabbixAPIError } from './zabbix/connectors/zabbix_api/zabbixAPIConnector';
|
||||||
import { ZabbixMetricsQuery, ZabbixDSOptions, VariableQueryTypes, ShowProblemTypes, ProblemDTO } from './types';
|
import { ZabbixMetricsQuery, ZabbixDSOptions, VariableQueryTypes, ShowProblemTypes, ProblemDTO } from './types';
|
||||||
import { getBackendSrv, getTemplateSrv, toDataQueryResponse } from '@grafana/runtime';
|
import { getBackendSrv, getTemplateSrv, toDataQueryError, toDataQueryResponse } from '@grafana/runtime';
|
||||||
import { DataFrame, DataQueryRequest, DataQueryResponse, DataSourceApi, DataSourceInstanceSettings, FieldType, isDataFrame, LoadingState } from '@grafana/data';
|
import { DataFrame, DataQueryRequest, DataQueryResponse, DataSourceApi, DataSourceInstanceSettings, FieldType, isDataFrame, LoadingState } from '@grafana/data';
|
||||||
|
|
||||||
export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDSOptions> {
|
export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDSOptions> {
|
||||||
@@ -101,18 +101,19 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
|
|||||||
*/
|
*/
|
||||||
query(request: DataQueryRequest<any>): Promise<DataQueryResponse> | Observable<DataQueryResponse> {
|
query(request: DataQueryRequest<any>): Promise<DataQueryResponse> | Observable<DataQueryResponse> {
|
||||||
// Migrate old targets
|
// Migrate old targets
|
||||||
request.targets = request.targets.map(t => {
|
const requestTargets = request.targets.map(t => {
|
||||||
// Prevent changes of original object
|
// Prevent changes of original object
|
||||||
const target = _.cloneDeep(t);
|
const target = _.cloneDeep(t);
|
||||||
return migrations.migrate(target);
|
return migrations.migrate(target);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isBackendQuery(request)) {
|
const backendResponsePromise = this.backendQuery({...request, targets: requestTargets});
|
||||||
return this.backendQuery(request);
|
// if (isBackendQuery(request)) {
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Create request for each target
|
// Create request for each target
|
||||||
const promises = _.map(request.targets, target => {
|
const frontendTargets = requestTargets.filter(t => !isBackendTarget(t));
|
||||||
|
const promises = _.map(frontendTargets, target => {
|
||||||
// Don't request for hidden targets
|
// Don't request for hidden targets
|
||||||
if (target.hide) {
|
if (target.hide) {
|
||||||
return [];
|
return [];
|
||||||
@@ -172,7 +173,7 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Data for panel (all targets)
|
// Data for panel (all targets)
|
||||||
return Promise.all(_.flatten(promises))
|
const frontendResponsePromise: Promise<DataQueryResponse> = Promise.all(_.flatten(promises))
|
||||||
.then(_.flatten)
|
.then(_.flatten)
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data && data.length > 0 && isDataFrame(data[0]) && !utils.isProblemsDataFrame(data[0])) {
|
if (data && data.length > 0 && isDataFrame(data[0]) && !utils.isProblemsDataFrame(data[0])) {
|
||||||
@@ -182,19 +183,28 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
|
|||||||
data = responseHandler.convertToWide(data);
|
data = responseHandler.convertToWide(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data;
|
return { data };
|
||||||
}).then(data => {
|
});
|
||||||
|
|
||||||
|
return Promise.all([backendResponsePromise, frontendResponsePromise])
|
||||||
|
.then(rsp => {
|
||||||
|
// Merge backend and frontend queries results
|
||||||
|
const [backendRes, frontendRes] = rsp;
|
||||||
|
if (frontendRes.data) {
|
||||||
|
backendRes.data = backendRes.data.concat(frontendRes.data);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data,
|
data: backendRes.data,
|
||||||
state: LoadingState.Done,
|
state: LoadingState.Done,
|
||||||
key: request.requestId,
|
key: request.requestId,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
backendQuery(request: DataQueryRequest<any>): Observable<DataQueryResponse> {
|
async backendQuery(request: DataQueryRequest<any>): Promise<DataQueryResponse> {
|
||||||
const { intervalMs, maxDataPoints, range, requestId } = request;
|
const { intervalMs, maxDataPoints, range, requestId } = request;
|
||||||
const targets = request.targets;
|
const targets = request.targets.filter(isBackendTarget);
|
||||||
|
|
||||||
// Add range variables
|
// Add range variables
|
||||||
request.scopedVars = Object.assign({}, request.scopedVars, utils.getRangeScopedVars(request.range));
|
request.scopedVars = Object.assign({}, request.scopedVars, utils.getRangeScopedVars(request.range));
|
||||||
@@ -224,7 +234,7 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
|
|||||||
|
|
||||||
// Return early if no queries exist
|
// Return early if no queries exist
|
||||||
if (!queries.length) {
|
if (!queries.length) {
|
||||||
return of({ data: [] });
|
return Promise.resolve({ data: [] });
|
||||||
}
|
}
|
||||||
|
|
||||||
const body: any = { queries };
|
const body: any = { queries };
|
||||||
@@ -235,15 +245,18 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
|
|||||||
body.to = range.to.valueOf().toString();
|
body.to = range.to.valueOf().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return getBackendSrv()
|
let rsp: any;
|
||||||
.fetch({
|
try {
|
||||||
|
rsp = await getBackendSrv().fetch({
|
||||||
url: '/api/ds/query',
|
url: '/api/ds/query',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: body,
|
data: body,
|
||||||
requestId,
|
requestId,
|
||||||
})
|
}).toPromise();
|
||||||
.pipe(
|
} catch (err) {
|
||||||
map((rsp: any) => {
|
return toDataQueryResponse(err);
|
||||||
|
}
|
||||||
|
|
||||||
const resp = toDataQueryResponse(rsp);
|
const resp = toDataQueryResponse(rsp);
|
||||||
this.sortByRefId(resp);
|
this.sortByRefId(resp);
|
||||||
this.applyFrontendFunctions(resp, request);
|
this.applyFrontendFunctions(resp, request);
|
||||||
@@ -251,48 +264,8 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
|
|||||||
console.log('Converting response to the wide format');
|
console.log('Converting response to the wide format');
|
||||||
resp.data = responseHandler.convertToWide(resp.data);
|
resp.data = responseHandler.convertToWide(resp.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp;
|
return resp;
|
||||||
}),
|
|
||||||
catchError((err) => {
|
|
||||||
return of(toDataQueryResponse(err));
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
doTsdbRequest(options) {
|
|
||||||
const tsdbRequestData: any = {
|
|
||||||
queries: options.targets.map(target => {
|
|
||||||
target.datasourceId = this.datasourceId;
|
|
||||||
target.queryType = 'zabbixAPI';
|
|
||||||
return target;
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (options.range) {
|
|
||||||
tsdbRequestData.from = options.range.from.valueOf().toString();
|
|
||||||
tsdbRequestData.to = options.range.to.valueOf().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return getBackendSrv().post('/api/ds/query', tsdbRequestData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {Promise<TSDBResponse>}
|
|
||||||
*/
|
|
||||||
doTSDBConnectionTest() {
|
|
||||||
/**
|
|
||||||
* @type {{ queries: ZabbixConnectionTestQuery[] }}
|
|
||||||
*/
|
|
||||||
const tsdbRequestData = {
|
|
||||||
queries: [
|
|
||||||
{
|
|
||||||
datasourceId: this.datasourceId,
|
|
||||||
queryType: 'connectionTest'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
return getBackendSrv().post('/api/tsdb/query', tsdbRequestData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -972,8 +945,10 @@ function getRequestTarget(request: DataQueryRequest<any>, refId: string): any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isBackendQuery(request: DataQueryRequest<any>): boolean {
|
function isBackendQuery(request: DataQueryRequest<any>): boolean {
|
||||||
return request.targets.every(q =>
|
return request.targets.every(isBackendTarget);
|
||||||
q.queryType === c.MODE_METRICS ||
|
}
|
||||||
q.queryType === c.MODE_ITEMID
|
|
||||||
);
|
function isBackendTarget(target: any): boolean {
|
||||||
|
return target.queryType === c.MODE_METRICS ||
|
||||||
|
target.queryType === c.MODE_ITEMID;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,9 @@ function migrateQueryType(target) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// queryType is a string in query model
|
// queryType is a string in query model
|
||||||
target.queryType = (target.queryType as number).toString();
|
if (typeof target.queryType === 'number') {
|
||||||
|
target.queryType = (target.queryType as number)?.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function migrateSLA(target) {
|
function migrateSLA(target) {
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export class ZabbixAPIConnector {
|
|||||||
requestOptions.headers.Authorization = this.requestOptions.basicAuth;
|
requestOptions.headers.Authorization = this.requestOptions.basicAuth;
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await getBackendSrv().datasourceRequest(requestOptions);
|
const response = await getBackendSrv().fetch<any>(requestOptions).toPromise();
|
||||||
return response?.data?.result;
|
return response?.data?.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user