Apply data processing for the IT Service query on the backend

This commit is contained in:
Alexander Zobnin
2021-08-05 17:59:58 +03:00
parent 6c1722d2ef
commit 62f38df28a
2 changed files with 82 additions and 96 deletions

View File

@@ -313,22 +313,7 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
console.log(`Datasource::Performance Query Time (${this.name}): ${queryEnd - queryStart}`); console.log(`Datasource::Performance Query Time (${this.name}): ${queryEnd - queryStart}`);
} }
const frames = []; return this.handleBackendPostProcessingResponse(result, request, target);
for (const frameJSON of result) {
const frame = dataFrameFromJSON(frameJSON);
frame.refId = target.refId;
frames.push(frame);
}
const resp = { data: frames };
this.sortByRefId(resp);
this.applyFrontendFunctions(resp, request);
if (responseHandler.isConvertibleToWide(resp.data)) {
console.log('Converting response to the wide format');
resp.data = responseHandler.convertToWide(resp.data);
}
return resp.data;
} }
/** /**
@@ -345,6 +330,10 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
history = await this.zabbix.getHistoryTS(items, timeRange, options); history = await this.zabbix.getHistoryTS(items, timeRange, options);
} }
return await this.invokeDataProcessingQuery(history, target);
}
async invokeDataProcessingQuery(timeSeriesData, query) {
// Request backend for data processing // Request backend for data processing
const requestOptions: BackendSrvRequest = { const requestOptions: BackendSrvRequest = {
url: `/api/datasources/${this.datasourceId}/resources/db-connection-post`, url: `/api/datasources/${this.datasourceId}/resources/db-connection-post`,
@@ -354,8 +343,8 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
}, },
hideFromInspector: false, hideFromInspector: false,
data: { data: {
query: target, series: timeSeriesData,
series: history, query,
}, },
}; };
@@ -363,6 +352,25 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
return response.data; return response.data;
} }
handleBackendPostProcessingResponse(response, request, target) {
const frames = [];
for (const frameJSON of response) {
const frame = dataFrameFromJSON(frameJSON);
frame.refId = target.refId;
frames.push(frame);
}
const resp = { data: frames };
this.sortByRefId(resp);
this.applyFrontendFunctions(resp, request);
if (responseHandler.isConvertibleToWide(resp.data)) {
console.log('Converting response to the wide format');
resp.data = responseHandler.convertToWide(resp.data);
}
return resp.data;
}
getTrendValueType(target) { getTrendValueType(target) {
// Find trendValue() function and get specified trend value // Find trendValue() function and get specified trend value
const trendFunctions = _.map(metricFunctions.getCategories()['Trends'], 'name'); const trendFunctions = _.map(metricFunctions.getCategories()['Trends'], 'name');
@@ -395,62 +403,6 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
return response; return response;
} }
applyDataProcessingFunctions(timeseries_data, target) {
const transformFunctions = bindFunctionDefs(target.functions, 'Transform');
const aggregationFunctions = bindFunctionDefs(target.functions, 'Aggregate');
const filterFunctions = bindFunctionDefs(target.functions, 'Filter');
const aliasFunctions = bindFunctionDefs(target.functions, 'Alias');
// Apply transformation functions
timeseries_data = _.cloneDeep(_.map(timeseries_data, timeseries => {
timeseries.datapoints = utils.sequence(transformFunctions)(timeseries.datapoints);
return timeseries;
}));
// Apply filter functions
if (filterFunctions.length) {
timeseries_data = utils.sequence(filterFunctions)(timeseries_data);
}
// Apply aggregations
if (aggregationFunctions.length) {
let dp = _.map(timeseries_data, 'datapoints');
dp = utils.sequence(aggregationFunctions)(dp);
const aggFuncNames = _.map(metricFunctions.getCategories()['Aggregate'], 'name');
const lastAgg = _.findLast(target.functions, func => {
return _.includes(aggFuncNames, func.def.name);
});
timeseries_data = [{
target: lastAgg.text,
datapoints: dp
}];
}
// Apply alias functions
_.forEach(timeseries_data, utils.sequence(aliasFunctions).bind(this));
// Apply Time-related functions (timeShift(), etc)
// Find timeShift() function and get specified trend value
this.applyTimeShiftFunction(timeseries_data, target);
return timeseries_data;
}
applyTimeShiftFunction(timeseries_data, target) {
// Find timeShift() function and get specified interval
const timeShiftFunc = _.find(target.functions, (func) => {
return func.def.name === 'timeShift';
});
if (timeShiftFunc) {
const shift = timeShiftFunc.params[0];
_.forEach(timeseries_data, (series) => {
series.datapoints = dataProcessor.unShiftTimeSeries(shift, series.datapoints);
});
}
}
/** /**
* Query target data for Text * Query target data for Text
*/ */
@@ -491,33 +443,32 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
/** /**
* Query target data for IT Services * Query target data for IT Services
*/ */
queryITServiceData(target, timeRange, options) { async queryITServiceData(target, timeRange, request) {
// Don't show undefined and hidden targets // Don't show undefined and hidden targets
if (target.hide || (!target.itservice && !target.itServiceFilter) || !target.slaProperty) { if (target.hide || (!target.itservice && !target.itServiceFilter) || !target.slaProperty) {
return []; return [];
} }
let itServiceFilter; let itServiceFilter;
options.isOldVersion = target.itservice && !target.itServiceFilter; request.isOldVersion = target.itservice && !target.itServiceFilter;
if (options.isOldVersion) { if (request.isOldVersion) {
// Backward compatibility // Backward compatibility
itServiceFilter = '/.*/'; itServiceFilter = '/.*/';
} else { } else {
itServiceFilter = this.replaceTemplateVars(target.itServiceFilter, options.scopedVars); itServiceFilter = this.replaceTemplateVars(target.itServiceFilter, request.scopedVars);
} }
options.slaInterval = target.slaInterval; request.slaInterval = target.slaInterval;
return this.zabbix.getITServices(itServiceFilter) let itservices = await this.zabbix.getITServices(itServiceFilter);
.then(itservices => { if (request.isOldVersion) {
if (options.isOldVersion) { itservices = _.filter(itservices, { 'serviceid': target.itservice?.serviceid });
itservices = _.filter(itservices, { 'serviceid': target.itservice?.serviceid }); }
} const itservicesdp = await this.zabbix.getSLA(itservices, timeRange, target, request);
return this.zabbix.getSLA(itservices, timeRange, target, options); const backendRequest = responseHandler.itServiceResponseToTimeSeries(itservicesdp, target.slaInterval);
}) const processedResponse = await this.invokeDataProcessingQuery(backendRequest, target);
.then(itservicesdp => this.applyDataProcessingFunctions(itservicesdp, target)) return this.handleBackendPostProcessingResponse(processedResponse, request, target);
.then(result => result.map(s => responseHandler.seriesToDataFrame(s, target)));
} }
queryTriggersData(target, timeRange) { queryTriggersData(target, timeRange) {
@@ -596,7 +547,7 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
} }
if (target.options?.acknowledged === 0 || target.options?.acknowledged === 1) { if (target.options?.acknowledged === 0 || target.options?.acknowledged === 1) {
problemsOptions.acknowledged = target.options?.acknowledged ? true : false; problemsOptions.acknowledged = !!target.options?.acknowledged;
} }
if (target.options?.minSeverity) { if (target.options?.minSeverity) {
@@ -690,8 +641,9 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
* Find metrics from templated request. * Find metrics from templated request.
* *
* @param {string} query Query from Templating * @param {string} query Query from Templating
* @param options
* @return {string} Metric name - group, host, app or item or list * @return {string} Metric name - group, host, app or item or list
* of metrics in "{metric1,metcic2,...,metricN}" format. * of metrics in "{metric1, metric2,..., metricN}" format.
*/ */
metricFindQuery(query, options) { metricFindQuery(query, options) {
let resultPromise; let resultPromise;
@@ -947,12 +899,6 @@ function replaceTemplateVars(templateSrv, target, scopedVars) {
return replacedTarget; return replacedTarget;
} }
function filterEnabledTargets(targets) {
return _.filter(targets, target => {
return !(target.hide || !target.group || !target.host || !target.item);
});
}
export function base64StringToArrowTable(text: string) { export function base64StringToArrowTable(text: string) {
const b64 = atob(text); const b64 = atob(text);
const arr = Uint8Array.from(b64, (c) => { const arr = Uint8Array.from(b64, (c) => {

View File

@@ -153,6 +153,7 @@ export function seriesToDataFrame(timeseries, target: ZabbixMetricsQuery, valueM
return mutableFrame; return mutableFrame;
} }
// Converts DataResponse to the format which backend works with (for data processing)
export function dataResponseToTimeSeries(response: DataFrameJSON[], items) { export function dataResponseToTimeSeries(response: DataFrameJSON[], items) {
const series = []; const series = [];
if (response.length === 0) { if (response.length === 0) {
@@ -198,6 +199,44 @@ export function dataResponseToTimeSeries(response: DataFrameJSON[], items) {
return series; return series;
} }
export function itServiceResponseToTimeSeries(response: any, interval) {
const series = [];
if (response.length === 0) {
return [];
}
for (const s of response) {
const ts = [];
if (!s.datapoints) {
continue;
}
const dp = s.datapoints;
for (let i = 0; i < dp.length; i++) {
ts.push({ time: dp[i][1] / 1000, value: dp[i][0] });
}
let intervalS = utils.parseItemInterval(interval);
if (intervalS === 0) {
intervalS = null;
}
const timeSeriesData = {
ts: ts,
meta: {
name: s.target,
interval: intervalS,
item: {},
}
};
series.push(timeSeriesData);
}
return series;
}
export function isConvertibleToWide(data: DataFrame[]): boolean { export function isConvertibleToWide(data: DataFrame[]): boolean {
if (!data || data.length < 2) { if (!data || data.length < 2) {
return false; return false;
@@ -499,6 +538,7 @@ export default {
sortTimeseries, sortTimeseries,
seriesToDataFrame, seriesToDataFrame,
dataResponseToTimeSeries, dataResponseToTimeSeries,
itServiceResponseToTimeSeries,
isConvertibleToWide, isConvertibleToWide,
convertToWide, convertToWide,
alignFrames, alignFrames,