From 6729de0e489c99358fe2dc6e55e0542c85f572aa Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Mon, 13 Apr 2020 15:13:54 +0300 Subject: [PATCH] Add series-specific variables for using in alias functions, #619 --- .../{dataProcessor.js => dataProcessor.ts} | 79 +++++++++++-------- src/datasource-zabbix/datasource.js | 2 +- src/datasource-zabbix/responseHandler.ts | 21 ++++- .../zabbix_api/zabbixAPIConnector.js | 2 +- 4 files changed, 64 insertions(+), 40 deletions(-) rename src/datasource-zabbix/{dataProcessor.js => dataProcessor.ts} (65%) diff --git a/src/datasource-zabbix/dataProcessor.js b/src/datasource-zabbix/dataProcessor.ts similarity index 65% rename from src/datasource-zabbix/dataProcessor.js rename to src/datasource-zabbix/dataProcessor.ts index a8ecdb6..5df0af0 100644 --- a/src/datasource-zabbix/dataProcessor.js +++ b/src/datasource-zabbix/dataProcessor.ts @@ -1,35 +1,37 @@ import _ from 'lodash'; +// Available in 7.0 +// import { getTemplateSrv } from '@grafana/runtime'; import * as utils from './utils'; import ts, { groupBy_perf as groupBy } from './timeseries'; -let SUM = ts.SUM; -let COUNT = ts.COUNT; -let AVERAGE = ts.AVERAGE; -let MIN = ts.MIN; -let MAX = ts.MAX; -let MEDIAN = ts.MEDIAN; -let PERCENTILE = ts.PERCENTILE; +const SUM = ts.SUM; +const COUNT = ts.COUNT; +const AVERAGE = ts.AVERAGE; +const MIN = ts.MIN; +const MAX = ts.MAX; +const MEDIAN = ts.MEDIAN; +const PERCENTILE = ts.PERCENTILE; -let downsampleSeries = ts.downsample; -let groupBy_exported = (interval, groupFunc, datapoints) => groupBy(datapoints, interval, groupFunc); -let sumSeries = ts.sumSeries; -let delta = ts.delta; -let rate = ts.rate; -let scale = (factor, datapoints) => ts.scale_perf(datapoints, factor); -let offset = (delta, datapoints) => ts.offset(datapoints, delta); -let simpleMovingAverage = (n, datapoints) => ts.simpleMovingAverage(datapoints, n); -let expMovingAverage = (a, datapoints) => ts.expMovingAverage(datapoints, a); -let percentile = (interval, n, datapoints) => groupBy(datapoints, interval, _.partial(PERCENTILE, n)); +const downsampleSeries = ts.downsample; +const groupBy_exported = (interval, groupFunc, datapoints) => groupBy(datapoints, interval, groupFunc); +const sumSeries = ts.sumSeries; +const delta = ts.delta; +const rate = ts.rate; +const scale = (factor, datapoints) => ts.scale_perf(datapoints, factor); +const offset = (delta, datapoints) => ts.offset(datapoints, delta); +const simpleMovingAverage = (n, datapoints) => ts.simpleMovingAverage(datapoints, n); +const expMovingAverage = (a, datapoints) => ts.expMovingAverage(datapoints, a); +const percentile = (interval, n, datapoints) => groupBy(datapoints, interval, _.partial(PERCENTILE, n)); function limit(order, n, orderByFunc, timeseries) { - let orderByCallback = aggregationFunctions[orderByFunc]; - let sortByIteratee = (ts) => { - let values = _.map(ts.datapoints, (point) => { + const orderByCallback = aggregationFunctions[orderByFunc]; + const sortByIteratee = (ts) => { + const values = _.map(ts.datapoints, (point) => { return point[0]; }); return orderByCallback(values); }; - let sortedTimeseries = _.sortBy(timeseries, sortByIteratee); + const sortedTimeseries = _.sortBy(timeseries, sortByIteratee); if (order === 'bottom') { return sortedTimeseries.slice(0, n); } else { @@ -64,13 +66,17 @@ function transformNull(n, datapoints) { }); } -function sortSeries(direction, timeseries) { - return _.orderBy(timeseries, [function (ts) { +function sortSeries(direction, timeseries: any[]) { + return _.orderBy(timeseries, [ts => { return ts.target.toLowerCase(); }], direction); } function setAlias(alias, timeseries) { + // TODO: use getTemplateSrv() when available (since 7.0) + if (this.templateSrv && timeseries && timeseries.scopedVars) { + alias = this.templateSrv.replace(alias, timeseries.scopedVars); + } timeseries.target = alias; return timeseries; } @@ -84,6 +90,10 @@ function replaceAlias(regexp, newAlias, timeseries) { } let alias = timeseries.target.replace(pattern, newAlias); + // TODO: use getTemplateSrv() when available (since 7.0) + if (this.templateSrv && timeseries && timeseries.scopedVars) { + alias = this.templateSrv.replace(alias, timeseries.scopedVars); + } timeseries.target = alias; return timeseries; } @@ -94,14 +104,13 @@ function setAliasByRegex(alias, timeseries) { } function extractText(str, pattern) { - var extractPattern = new RegExp(pattern); - var extractedValue = extractPattern.exec(str); - extractedValue = extractedValue[0]; - return extractedValue; + const extractPattern = new RegExp(pattern); + const extractedValue = extractPattern.exec(str); + return extractedValue[0]; } function groupByWrapper(interval, groupFunc, datapoints) { - var groupByCallback = aggregationFunctions[groupFunc]; + const groupByCallback = aggregationFunctions[groupFunc]; return groupBy(datapoints, interval, groupByCallback); } @@ -110,12 +119,12 @@ function aggregateByWrapper(interval, aggregateFunc, datapoints) { const flattenedPoints = ts.flattenDatapoints(datapoints); // groupBy_perf works with sorted series only const sortedPoints = ts.sortByTime(flattenedPoints); - let groupByCallback = aggregationFunctions[aggregateFunc]; + const groupByCallback = aggregationFunctions[aggregateFunc]; return groupBy(sortedPoints, interval, groupByCallback); } function aggregateWrapper(groupByCallback, interval, datapoints) { - var flattenedPoints = ts.flattenDatapoints(datapoints); + const flattenedPoints = ts.flattenDatapoints(datapoints); // groupBy_perf works with sorted series only const sortedPoints = ts.sortByTime(flattenedPoints); return groupBy(sortedPoints, interval, groupByCallback); @@ -125,19 +134,19 @@ function percentileAgg(interval, n, datapoints) { const flattenedPoints = ts.flattenDatapoints(datapoints); // groupBy_perf works with sorted series only const sortedPoints = ts.sortByTime(flattenedPoints); - let groupByCallback = _.partial(PERCENTILE, n); + const groupByCallback = _.partial(PERCENTILE, n); return groupBy(sortedPoints, interval, groupByCallback); } function timeShift(interval, range) { - let shift = utils.parseTimeShiftInterval(interval) / 1000; + const shift = utils.parseTimeShiftInterval(interval) / 1000; return _.map(range, time => { return time - shift; }); } function unShiftTimeSeries(interval, datapoints) { - let unshift = utils.parseTimeShiftInterval(interval); + const unshift = utils.parseTimeShiftInterval(interval); return _.map(datapoints, dp => { return [ dp[0], @@ -146,7 +155,7 @@ function unShiftTimeSeries(interval, datapoints) { }); } -let metricFunctions = { +const metricFunctions = { groupBy: groupByWrapper, scale: scale, offset: offset, @@ -177,7 +186,7 @@ let metricFunctions = { replaceAlias: replaceAlias }; -let aggregationFunctions = { +const aggregationFunctions = { avg: AVERAGE, min: MIN, max: MAX, diff --git a/src/datasource-zabbix/datasource.js b/src/datasource-zabbix/datasource.js index a97c564..cd70e96 100644 --- a/src/datasource-zabbix/datasource.js +++ b/src/datasource-zabbix/datasource.js @@ -253,7 +253,7 @@ export class ZabbixDatasource { } // Apply alias functions - _.forEach(timeseries_data, utils.sequence(aliasFunctions)); + _.forEach(timeseries_data, utils.sequence(aliasFunctions).bind(this)); // Apply Time-related functions (timeShift(), etc) // Find timeShift() function and get specified trend value diff --git a/src/datasource-zabbix/responseHandler.ts b/src/datasource-zabbix/responseHandler.ts index be472d8..ccb6576 100644 --- a/src/datasource-zabbix/responseHandler.ts +++ b/src/datasource-zabbix/responseHandler.ts @@ -29,14 +29,29 @@ function convertHistory(history, items, addHostName, convertPointCallback) { return _.map(grouped_history, (hist, itemid) => { const item = _.find(items, {'itemid': itemid}) as any; let alias = item.name; - if (_.keys(hosts).length > 1 && addHostName) { //only when actual multi hosts selected + + // Add scopedVars for using in alias functions + const scopedVars: any = { + '__zbx_item': { value: item.name }, + '__zbx_item_name': { value: item.name }, + '__zbx_item_key': { value: item.key_ }, + }; + + if (_.keys(hosts).length > 0) { const host = _.find(hosts, {'hostid': item.hostid}); - alias = host.name + ": " + alias; + scopedVars['__zbx_host'] = { value: host.host }; + scopedVars['__zbx_host_name'] = { value: host.name }; + + // Only add host when multiple hosts selected + if (_.keys(hosts).length > 1 && addHostName) { + alias = host.name + ": " + alias; + } } return { target: alias, - datapoints: _.map(hist, convertPointCallback) + datapoints: _.map(hist, convertPointCallback), + scopedVars, }; }); } diff --git a/src/datasource-zabbix/zabbix/connectors/zabbix_api/zabbixAPIConnector.js b/src/datasource-zabbix/zabbix/connectors/zabbix_api/zabbixAPIConnector.js index 57a2a84..792a477 100644 --- a/src/datasource-zabbix/zabbix/connectors/zabbix_api/zabbixAPIConnector.js +++ b/src/datasource-zabbix/zabbix/connectors/zabbix_api/zabbixAPIConnector.js @@ -153,7 +153,7 @@ export class ZabbixAPIConnector { sortfield: 'name', webitems: true, filter: {}, - selectHosts: ['hostid', 'name'] + selectHosts: ['hostid', 'name', 'host'] }; if (hostids) { params.hostids = hostids;