Services refactor - using ES6 modules.
This commit is contained in:
@@ -19,9 +19,11 @@ module.exports = function(grunt) {
|
|||||||
'!**/module.js',
|
'!**/module.js',
|
||||||
'!**/query.controller.js',
|
'!**/query.controller.js',
|
||||||
'!**/utils.js',
|
'!**/utils.js',
|
||||||
|
'!**/DataProcessor.js',
|
||||||
'!**/zabbixAPICore.service.js',
|
'!**/zabbixAPICore.service.js',
|
||||||
'!**/zabbixAPI.service.js',
|
'!**/zabbixAPI.service.js',
|
||||||
//'!**/dataProcessing.service.js',
|
'!**/queryProcessor.service.js',
|
||||||
|
'!**/zabbixCache.service.js',
|
||||||
'!**/metricFunctions.js',
|
'!**/metricFunctions.js',
|
||||||
'!**/*.scss'
|
'!**/*.scss'
|
||||||
],
|
],
|
||||||
@@ -57,9 +59,11 @@ module.exports = function(grunt) {
|
|||||||
'**/**/datasource.js',
|
'**/**/datasource.js',
|
||||||
'**/**/query.controller.js',
|
'**/**/query.controller.js',
|
||||||
'**/**/utils.js',
|
'**/**/utils.js',
|
||||||
|
'**/**/DataProcessor.js',
|
||||||
'**/**/zabbixAPICore.service.js',
|
'**/**/zabbixAPICore.service.js',
|
||||||
'**/**/zabbixAPI.service.js',
|
'**/**/zabbixAPI.service.js',
|
||||||
//'**/**/dataProcessing.service.js',
|
'**/**/queryProcessor.service.js',
|
||||||
|
'**/**/zabbixCache.service.js',
|
||||||
'**/**/metricFunctions.js'
|
'**/**/metricFunctions.js'
|
||||||
],
|
],
|
||||||
dest: 'dist/'
|
dest: 'dist/'
|
||||||
|
|||||||
234
src/datasource-zabbix/DataProcessor.js
Normal file
234
src/datasource-zabbix/DataProcessor.js
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
|
import * as utils from './utils';
|
||||||
|
|
||||||
|
export default class DataProcessor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downsample datapoints series
|
||||||
|
*/
|
||||||
|
static downsampleSeries(datapoints, time_to, ms_interval, func) {
|
||||||
|
var downsampledSeries = [];
|
||||||
|
var timeWindow = {
|
||||||
|
from: time_to * 1000 - ms_interval,
|
||||||
|
to: time_to * 1000
|
||||||
|
};
|
||||||
|
|
||||||
|
var points_sum = 0;
|
||||||
|
var points_num = 0;
|
||||||
|
var value_avg = 0;
|
||||||
|
var frame = [];
|
||||||
|
|
||||||
|
for (var i = datapoints.length - 1; i >= 0; i -= 1) {
|
||||||
|
if (timeWindow.from < datapoints[i][1] && datapoints[i][1] <= timeWindow.to) {
|
||||||
|
points_sum += datapoints[i][0];
|
||||||
|
points_num++;
|
||||||
|
frame.push(datapoints[i][0]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value_avg = points_num ? points_sum / points_num : 0;
|
||||||
|
|
||||||
|
if (func === "max") {
|
||||||
|
downsampledSeries.push([_.max(frame), timeWindow.to]);
|
||||||
|
}
|
||||||
|
else if (func === "min") {
|
||||||
|
downsampledSeries.push([_.min(frame), timeWindow.to]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// avg by default
|
||||||
|
else {
|
||||||
|
downsampledSeries.push([value_avg, timeWindow.to]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shift time window
|
||||||
|
timeWindow.to = timeWindow.from;
|
||||||
|
timeWindow.from -= ms_interval;
|
||||||
|
|
||||||
|
points_sum = 0;
|
||||||
|
points_num = 0;
|
||||||
|
frame = [];
|
||||||
|
|
||||||
|
// Process point again
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return downsampledSeries.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group points by given time interval
|
||||||
|
* datapoints: [[<value>, <unixtime>], ...]
|
||||||
|
*/
|
||||||
|
static groupBy(interval, groupByCallback, datapoints) {
|
||||||
|
var ms_interval = utils.parseInterval(interval);
|
||||||
|
|
||||||
|
// Calculate frame timestamps
|
||||||
|
var frames = _.groupBy(datapoints, function(point) {
|
||||||
|
// Calculate time for group of points
|
||||||
|
return Math.floor(point[1] / ms_interval) * ms_interval;
|
||||||
|
});
|
||||||
|
|
||||||
|
// frame: { '<unixtime>': [[<value>, <unixtime>], ...] }
|
||||||
|
// return [{ '<unixtime>': <value> }, { '<unixtime>': <value> }, ...]
|
||||||
|
var grouped = _.mapValues(frames, function(frame) {
|
||||||
|
var points = _.map(frame, function(point) {
|
||||||
|
return point[0];
|
||||||
|
});
|
||||||
|
return groupByCallback(points);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Convert points to Grafana format
|
||||||
|
return sortByTime(_.map(grouped, function(value, timestamp) {
|
||||||
|
return [Number(value), Number(timestamp)];
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
static sumSeries(timeseries) {
|
||||||
|
|
||||||
|
// Calculate new points for interpolation
|
||||||
|
var new_timestamps = _.uniq(_.map(_.flatten(timeseries, true), function(point) {
|
||||||
|
return point[1];
|
||||||
|
}));
|
||||||
|
new_timestamps = _.sortBy(new_timestamps);
|
||||||
|
|
||||||
|
var interpolated_timeseries = _.map(timeseries, function(series) {
|
||||||
|
var timestamps = _.map(series, function(point) {
|
||||||
|
return point[1];
|
||||||
|
});
|
||||||
|
var new_points = _.map(_.difference(new_timestamps, timestamps), function(timestamp) {
|
||||||
|
return [null, timestamp];
|
||||||
|
});
|
||||||
|
var new_series = series.concat(new_points);
|
||||||
|
return sortByTime(new_series);
|
||||||
|
});
|
||||||
|
|
||||||
|
_.each(interpolated_timeseries, interpolateSeries);
|
||||||
|
|
||||||
|
var new_timeseries = [];
|
||||||
|
var sum;
|
||||||
|
for (var i = new_timestamps.length - 1; i >= 0; i--) {
|
||||||
|
sum = 0;
|
||||||
|
for (var j = interpolated_timeseries.length - 1; j >= 0; j--) {
|
||||||
|
sum += interpolated_timeseries[j][i][0];
|
||||||
|
}
|
||||||
|
new_timeseries.push([sum, new_timestamps[i]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortByTime(new_timeseries);
|
||||||
|
}
|
||||||
|
|
||||||
|
static AVERAGE(values) {
|
||||||
|
var sum = 0;
|
||||||
|
_.each(values, function(value) {
|
||||||
|
sum += value;
|
||||||
|
});
|
||||||
|
return sum / values.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MIN(values) {
|
||||||
|
return _.min(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MAX(values) {
|
||||||
|
return _.max(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MEDIAN(values) {
|
||||||
|
var sorted = _.sortBy(values);
|
||||||
|
return sorted[Math.floor(sorted.length / 2)];
|
||||||
|
}
|
||||||
|
|
||||||
|
static setAlias(alias, timeseries) {
|
||||||
|
timeseries.target = alias;
|
||||||
|
return timeseries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static groupByWrapper(interval, groupFunc, datapoints) {
|
||||||
|
var groupByCallback = DataProcessor.aggregationFunctions[groupFunc];
|
||||||
|
return DataProcessor.groupBy(interval, groupByCallback, datapoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
static aggregateWrapper(groupByCallback, interval, datapoints) {
|
||||||
|
var flattenedPoints = _.flatten(datapoints, true);
|
||||||
|
return DataProcessor.groupBy(interval, groupByCallback, flattenedPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
static get aggregationFunctions() {
|
||||||
|
return {
|
||||||
|
avg: this.AVERAGE,
|
||||||
|
min: this.MIN,
|
||||||
|
max: this.MAX,
|
||||||
|
median: this.MEDIAN
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static get metricFunctions() {
|
||||||
|
return {
|
||||||
|
groupBy: this.groupByWrapper,
|
||||||
|
average: _.partial(this.aggregateWrapper, this.AVERAGE),
|
||||||
|
min: _.partial(this.aggregateWrapper, this.MIN),
|
||||||
|
max: _.partial(this.aggregateWrapper, this.MAX),
|
||||||
|
median: _.partial(this.aggregateWrapper, this.MEDIAN),
|
||||||
|
sumSeries: this.sumSeries,
|
||||||
|
setAlias: this.setAlias,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortByTime(series) {
|
||||||
|
return _.sortBy(series, function(point) {
|
||||||
|
return point[1];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interpolate series with gaps
|
||||||
|
*/
|
||||||
|
function interpolateSeries(series) {
|
||||||
|
var left, right;
|
||||||
|
|
||||||
|
// Interpolate series
|
||||||
|
for (var i = series.length - 1; i >= 0; i--) {
|
||||||
|
if (!series[i][0]) {
|
||||||
|
left = findNearestLeft(series, series[i]);
|
||||||
|
right = findNearestRight(series, series[i]);
|
||||||
|
if (!left) {
|
||||||
|
left = right;
|
||||||
|
}
|
||||||
|
if (!right) {
|
||||||
|
right = left;
|
||||||
|
}
|
||||||
|
series[i][0] = linearInterpolation(series[i][1], left, right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return series;
|
||||||
|
}
|
||||||
|
|
||||||
|
function linearInterpolation(timestamp, left, right) {
|
||||||
|
if (left[1] === right[1]) {
|
||||||
|
return (left[0] + right[0]) / 2;
|
||||||
|
} else {
|
||||||
|
return (left[0] + (right[0] - left[0]) / (right[1] - left[1]) * (timestamp - left[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findNearestRight(series, point) {
|
||||||
|
var point_index = _.indexOf(series, point);
|
||||||
|
var nearestRight;
|
||||||
|
for (var i = point_index; i < series.length; i++) {
|
||||||
|
if (series[i][0]) {
|
||||||
|
return series[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nearestRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findNearestLeft(series, point) {
|
||||||
|
var point_index = _.indexOf(series, point);
|
||||||
|
var nearestLeft;
|
||||||
|
for (var i = point_index; i > 0; i--) {
|
||||||
|
if (series[i][0]) {
|
||||||
|
return series[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nearestLeft;
|
||||||
|
}
|
||||||
@@ -1,241 +0,0 @@
|
|||||||
define([
|
|
||||||
'angular',
|
|
||||||
'lodash',
|
|
||||||
'moment',
|
|
||||||
'./utils'
|
|
||||||
],
|
|
||||||
function (angular, _, moment, utils) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var module = angular.module('grafana.services');
|
|
||||||
|
|
||||||
module.service('DataProcessingService', function() {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Downsample datapoints series
|
|
||||||
*/
|
|
||||||
this.downsampleSeries = function(datapoints, time_to, ms_interval, func) {
|
|
||||||
var downsampledSeries = [];
|
|
||||||
var timeWindow = {
|
|
||||||
from: time_to * 1000 - ms_interval,
|
|
||||||
to: time_to * 1000
|
|
||||||
};
|
|
||||||
|
|
||||||
var points_sum = 0;
|
|
||||||
var points_num = 0;
|
|
||||||
var value_avg = 0;
|
|
||||||
var frame = [];
|
|
||||||
|
|
||||||
for (var i = datapoints.length - 1; i >= 0; i -= 1) {
|
|
||||||
if (timeWindow.from < datapoints[i][1] && datapoints[i][1] <= timeWindow.to) {
|
|
||||||
points_sum += datapoints[i][0];
|
|
||||||
points_num++;
|
|
||||||
frame.push(datapoints[i][0]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
value_avg = points_num ? points_sum / points_num : 0;
|
|
||||||
|
|
||||||
if (func === "max") {
|
|
||||||
downsampledSeries.push([_.max(frame), timeWindow.to]);
|
|
||||||
}
|
|
||||||
else if (func === "min") {
|
|
||||||
downsampledSeries.push([_.min(frame), timeWindow.to]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// avg by default
|
|
||||||
else {
|
|
||||||
downsampledSeries.push([value_avg, timeWindow.to]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shift time window
|
|
||||||
timeWindow.to = timeWindow.from;
|
|
||||||
timeWindow.from -= ms_interval;
|
|
||||||
|
|
||||||
points_sum = 0;
|
|
||||||
points_num = 0;
|
|
||||||
frame = [];
|
|
||||||
|
|
||||||
// Process point again
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return downsampledSeries.reverse();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Group points by given time interval
|
|
||||||
* datapoints: [[<value>, <unixtime>], ...]
|
|
||||||
*/
|
|
||||||
this.groupBy = function(interval, groupByCallback, datapoints) {
|
|
||||||
var ms_interval = utils.parseInterval(interval);
|
|
||||||
|
|
||||||
// Calculate frame timestamps
|
|
||||||
var frames = _.groupBy(datapoints, function(point) {
|
|
||||||
// Calculate time for group of points
|
|
||||||
return Math.floor(point[1] / ms_interval) * ms_interval;
|
|
||||||
});
|
|
||||||
|
|
||||||
// frame: { '<unixtime>': [[<value>, <unixtime>], ...] }
|
|
||||||
// return [{ '<unixtime>': <value> }, { '<unixtime>': <value> }, ...]
|
|
||||||
var grouped = _.mapValues(frames, function(frame) {
|
|
||||||
var points = _.map(frame, function(point) {
|
|
||||||
return point[0];
|
|
||||||
});
|
|
||||||
return groupByCallback(points);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Convert points to Grafana format
|
|
||||||
return sortByTime(_.map(grouped, function(value, timestamp) {
|
|
||||||
return [Number(value), Number(timestamp)];
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
this.sumSeries = function(timeseries) {
|
|
||||||
|
|
||||||
// Calculate new points for interpolation
|
|
||||||
var new_timestamps = _.uniq(_.map(_.flatten(timeseries, true), function(point) {
|
|
||||||
return point[1];
|
|
||||||
}));
|
|
||||||
new_timestamps = _.sortBy(new_timestamps);
|
|
||||||
|
|
||||||
var interpolated_timeseries = _.map(timeseries, function(series) {
|
|
||||||
var timestamps = _.map(series, function(point) {
|
|
||||||
return point[1];
|
|
||||||
});
|
|
||||||
var new_points = _.map(_.difference(new_timestamps, timestamps), function(timestamp) {
|
|
||||||
return [null, timestamp];
|
|
||||||
});
|
|
||||||
var new_series = series.concat(new_points);
|
|
||||||
return sortByTime(new_series);
|
|
||||||
});
|
|
||||||
|
|
||||||
_.each(interpolated_timeseries, interpolateSeries);
|
|
||||||
|
|
||||||
var new_timeseries = [];
|
|
||||||
var sum;
|
|
||||||
for (var i = new_timestamps.length - 1; i >= 0; i--) {
|
|
||||||
sum = 0;
|
|
||||||
for (var j = interpolated_timeseries.length - 1; j >= 0; j--) {
|
|
||||||
sum += interpolated_timeseries[j][i][0];
|
|
||||||
}
|
|
||||||
new_timeseries.push([sum, new_timestamps[i]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sortByTime(new_timeseries);
|
|
||||||
};
|
|
||||||
|
|
||||||
function sortByTime(series) {
|
|
||||||
return _.sortBy(series, function(point) {
|
|
||||||
return point[1];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interpolate series with gaps
|
|
||||||
*/
|
|
||||||
function interpolateSeries(series) {
|
|
||||||
var left, right;
|
|
||||||
|
|
||||||
// Interpolate series
|
|
||||||
for (var i = series.length - 1; i >= 0; i--) {
|
|
||||||
if (!series[i][0]) {
|
|
||||||
left = findNearestLeft(series, series[i]);
|
|
||||||
right = findNearestRight(series, series[i]);
|
|
||||||
if (!left) {
|
|
||||||
left = right;
|
|
||||||
}
|
|
||||||
if (!right) {
|
|
||||||
right = left;
|
|
||||||
}
|
|
||||||
series[i][0] = linearInterpolation(series[i][1], left, right);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return series;
|
|
||||||
}
|
|
||||||
|
|
||||||
function linearInterpolation(timestamp, left, right) {
|
|
||||||
if (left[1] === right[1]) {
|
|
||||||
return (left[0] + right[0]) / 2;
|
|
||||||
} else {
|
|
||||||
return (left[0] + (right[0] - left[0]) / (right[1] - left[1]) * (timestamp - left[1]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function findNearestRight(series, point) {
|
|
||||||
var point_index = _.indexOf(series, point);
|
|
||||||
var nearestRight;
|
|
||||||
for (var i = point_index; i < series.length; i++) {
|
|
||||||
if (series[i][0]) {
|
|
||||||
return series[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nearestRight;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findNearestLeft(series, point) {
|
|
||||||
var point_index = _.indexOf(series, point);
|
|
||||||
var nearestLeft;
|
|
||||||
for (var i = point_index; i > 0; i--) {
|
|
||||||
if (series[i][0]) {
|
|
||||||
return series[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nearestLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.AVERAGE = function(values) {
|
|
||||||
var sum = 0;
|
|
||||||
_.each(values, function(value) {
|
|
||||||
sum += value;
|
|
||||||
});
|
|
||||||
return sum / values.length;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.MIN = function(values) {
|
|
||||||
return _.min(values);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.MAX = function(values) {
|
|
||||||
return _.max(values);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.MEDIAN = function(values) {
|
|
||||||
var sorted = _.sortBy(values);
|
|
||||||
return sorted[Math.floor(sorted.length / 2)];
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setAlias = function(alias, timeseries) {
|
|
||||||
timeseries.target = alias;
|
|
||||||
return timeseries;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.aggregationFunctions = {
|
|
||||||
avg: this.AVERAGE,
|
|
||||||
min: this.MIN,
|
|
||||||
max: this.MAX,
|
|
||||||
median: this.MEDIAN
|
|
||||||
};
|
|
||||||
|
|
||||||
this.groupByWrapper = function(interval, groupFunc, datapoints) {
|
|
||||||
var groupByCallback = self.aggregationFunctions[groupFunc];
|
|
||||||
return self.groupBy(interval, groupByCallback, datapoints);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.aggregateWrapper = function(groupByCallback, interval, datapoints) {
|
|
||||||
var flattenedPoints = _.flatten(datapoints, true);
|
|
||||||
return self.groupBy(interval, groupByCallback, flattenedPoints);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.metricFunctions = {
|
|
||||||
groupBy: this.groupByWrapper,
|
|
||||||
average: _.partial(this.aggregateWrapper, this.AVERAGE),
|
|
||||||
min: _.partial(this.aggregateWrapper, this.MIN),
|
|
||||||
max: _.partial(this.aggregateWrapper, this.MAX),
|
|
||||||
median: _.partial(this.aggregateWrapper, this.MEDIAN),
|
|
||||||
sumSeries: this.sumSeries,
|
|
||||||
setAlias: this.setAlias,
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -3,15 +3,15 @@ import _ from 'lodash';
|
|||||||
import * as dateMath from 'app/core/utils/datemath';
|
import * as dateMath from 'app/core/utils/datemath';
|
||||||
import * as utils from './utils';
|
import * as utils from './utils';
|
||||||
import * as metricFunctions from './metricFunctions';
|
import * as metricFunctions from './metricFunctions';
|
||||||
|
import DataProcessor from './DataProcessor';
|
||||||
import './zabbixAPI.service.js';
|
import './zabbixAPI.service.js';
|
||||||
import './zabbixCache.service.js';
|
import './zabbixCache.service.js';
|
||||||
import './queryProcessor.service.js';
|
import './queryProcessor.service.js';
|
||||||
import './dataProcessing.service';
|
|
||||||
|
|
||||||
export class ZabbixAPIDatasource {
|
export class ZabbixAPIDatasource {
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor(instanceSettings, $q, templateSrv, alertSrv, zabbixAPIService, ZabbixCachingProxy, QueryProcessor, DataProcessingService) {
|
constructor(instanceSettings, $q, templateSrv, alertSrv, zabbixAPIService, ZabbixCachingProxy, QueryProcessor) {
|
||||||
|
|
||||||
// General data source settings
|
// General data source settings
|
||||||
this.name = instanceSettings.name;
|
this.name = instanceSettings.name;
|
||||||
@@ -45,7 +45,6 @@ export class ZabbixAPIDatasource {
|
|||||||
this.q = $q;
|
this.q = $q;
|
||||||
this.templateSrv = templateSrv;
|
this.templateSrv = templateSrv;
|
||||||
this.alertSrv = alertSrv;
|
this.alertSrv = alertSrv;
|
||||||
this.DataProcessingService = DataProcessingService;
|
|
||||||
|
|
||||||
console.log(this.zabbixCache);
|
console.log(this.zabbixCache);
|
||||||
}
|
}
|
||||||
@@ -159,7 +158,7 @@ export class ZabbixAPIDatasource {
|
|||||||
timeseries_data = _.map(timeseries_data, function (timeseries) {
|
timeseries_data = _.map(timeseries_data, function (timeseries) {
|
||||||
|
|
||||||
// Filter only transform functions
|
// Filter only transform functions
|
||||||
var transformFunctions = bindFunctionDefs(target.functions, 'Transform', self.DataProcessingService);
|
var transformFunctions = bindFunctionDefs(target.functions, 'Transform', DataProcessor);
|
||||||
|
|
||||||
// Metric data processing
|
// Metric data processing
|
||||||
var dp = timeseries.datapoints;
|
var dp = timeseries.datapoints;
|
||||||
@@ -172,7 +171,7 @@ export class ZabbixAPIDatasource {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Aggregations
|
// Aggregations
|
||||||
var aggregationFunctions = bindFunctionDefs(target.functions, 'Aggregate', self.DataProcessingService);
|
var aggregationFunctions = bindFunctionDefs(target.functions, 'Aggregate', DataProcessor);
|
||||||
var dp = _.map(timeseries_data, 'datapoints');
|
var dp = _.map(timeseries_data, 'datapoints');
|
||||||
if (aggregationFunctions.length) {
|
if (aggregationFunctions.length) {
|
||||||
for (var i = 0; i < aggregationFunctions.length; i++) {
|
for (var i = 0; i < aggregationFunctions.length; i++) {
|
||||||
@@ -189,7 +188,7 @@ export class ZabbixAPIDatasource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply alias functions
|
// Apply alias functions
|
||||||
var aliasFunctions = bindFunctionDefs(target.functions, 'Alias', self.DataProcessingService);
|
var aliasFunctions = bindFunctionDefs(target.functions, 'Alias', DataProcessor);
|
||||||
for (var j = 0; j < aliasFunctions.length; j++) {
|
for (var j = 0; j < aliasFunctions.length; j++) {
|
||||||
_.each(timeseries_data, aliasFunctions[j]);
|
_.each(timeseries_data, aliasFunctions[j]);
|
||||||
}
|
}
|
||||||
@@ -255,9 +254,9 @@ export class ZabbixAPIDatasource {
|
|||||||
|
|
||||||
// Series downsampling
|
// Series downsampling
|
||||||
var data = _.map(timeseries_data, function(timeseries) {
|
var data = _.map(timeseries_data, function(timeseries) {
|
||||||
var DPS = self.DataProcessingService;
|
|
||||||
if (timeseries.datapoints.length > options.maxDataPoints) {
|
if (timeseries.datapoints.length > options.maxDataPoints) {
|
||||||
timeseries.datapoints = DPS.groupBy(options.interval, DPS.AVERAGE, timeseries.datapoints);
|
timeseries.datapoints =
|
||||||
|
DataProcessor.groupBy(options.interval, DataProcessor.AVERAGE, timeseries.datapoints);
|
||||||
}
|
}
|
||||||
return timeseries;
|
return timeseries;
|
||||||
});
|
});
|
||||||
@@ -409,7 +408,7 @@ export class ZabbixAPIDatasource {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function bindFunctionDefs(functionDefs, category, DataProcessingService) {
|
function bindFunctionDefs(functionDefs, category, DataProcessor) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var aggregationFunctions = _.map(metricFunctions.getCategories()[category], 'name');
|
var aggregationFunctions = _.map(metricFunctions.getCategories()[category], 'name');
|
||||||
var aggFuncDefs = _.filter(functionDefs, function(func) {
|
var aggFuncDefs = _.filter(functionDefs, function(func) {
|
||||||
@@ -418,7 +417,7 @@ function bindFunctionDefs(functionDefs, category, DataProcessingService) {
|
|||||||
|
|
||||||
return _.map(aggFuncDefs, function(func) {
|
return _.map(aggFuncDefs, function(func) {
|
||||||
var funcInstance = metricFunctions.createFuncInstance(func.def, func.params);
|
var funcInstance = metricFunctions.createFuncInstance(func.def, func.params);
|
||||||
return funcInstance.bindFunction(DataProcessingService.metricFunctions);
|
return funcInstance.bindFunction(DataProcessor.metricFunctions);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,363 +1,361 @@
|
|||||||
define([
|
import angular from 'angular';
|
||||||
'angular',
|
import _ from 'lodash';
|
||||||
'lodash',
|
import * as utils from './utils';
|
||||||
'./utils'
|
|
||||||
],
|
|
||||||
function (angular, _, utils) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var module = angular.module('grafana.services');
|
/** @ngInject */
|
||||||
|
angular.module('grafana.services').factory('QueryProcessor', function($q) {
|
||||||
module.factory('QueryProcessor', function($q) {
|
|
||||||
|
|
||||||
function QueryProcessor(zabbixCacheInstance) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
|
class QueryProcessor {
|
||||||
|
constructor(zabbixCacheInstance) {
|
||||||
this.cache = zabbixCacheInstance;
|
this.cache = zabbixCacheInstance;
|
||||||
|
this.$q = $q;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build query in asynchronous manner
|
* Build query in asynchronous manner
|
||||||
*/
|
*/
|
||||||
this.build = function (groupFilter, hostFilter, appFilter, itemFilter) {
|
build(groupFilter, hostFilter, appFilter, itemFilter) {
|
||||||
if (this.cache._initialized) {
|
var self = this;
|
||||||
return $q.when(self.buildFromCache(groupFilter, hostFilter, appFilter, itemFilter));
|
if (this.cache._initialized) {
|
||||||
} else {
|
return this.$q.when(self.buildFromCache(groupFilter, hostFilter, appFilter, itemFilter));
|
||||||
return this.cache.refresh().then(function() {
|
} else {
|
||||||
return self.buildFromCache(groupFilter, hostFilter, appFilter, itemFilter);
|
return this.cache.refresh().then(function() {
|
||||||
});
|
return self.buildFromCache(groupFilter, hostFilter, appFilter, itemFilter);
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build trigger query in asynchronous manner
|
|
||||||
*/
|
|
||||||
this.buildTriggerQuery = function (groupFilter, hostFilter, appFilter) {
|
|
||||||
if (this.cache._initialized) {
|
|
||||||
return $q.when(self.buildTriggerQueryFromCache(groupFilter, hostFilter, appFilter));
|
|
||||||
} else {
|
|
||||||
return this.cache.refresh().then(function() {
|
|
||||||
return self.buildTriggerQueryFromCache(groupFilter, hostFilter, appFilter);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.filterGroups = function(groupFilter) {
|
|
||||||
return this.cache.getGroups().then(function(groupList) {
|
|
||||||
return groupList;
|
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get list of host belonging to given groups.
|
* Build trigger query in asynchronous manner
|
||||||
* @return list of hosts
|
*/
|
||||||
*/
|
buildTriggerQuery(groupFilter, hostFilter, appFilter) {
|
||||||
this.filterHosts = function(groupFilter) {
|
var self = this;
|
||||||
return this.cache.getGroups().then(function(groups) {
|
if (this.cache._initialized) {
|
||||||
groups = findByFilter(groups, groupFilter);
|
return this.$q.when(self.buildTriggerQueryFromCache(groupFilter, hostFilter, appFilter));
|
||||||
var hostids = _.flatten(_.map(groups, 'hosts'));
|
} else {
|
||||||
if (hostids.length) {
|
return this.cache.refresh().then(function() {
|
||||||
return self.cache.getIndexedHosts().then(function(hosts) {
|
return self.buildTriggerQueryFromCache(groupFilter, hostFilter, appFilter);
|
||||||
return _.map(hostids, function(hostid) {
|
});
|
||||||
return hosts[hostid];
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
filterGroups(groupFilter) {
|
||||||
|
return this.cache.getGroups().then(function(groupList) {
|
||||||
|
return groupList;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of host belonging to given groups.
|
||||||
|
* @return list of hosts
|
||||||
|
*/
|
||||||
|
filterHosts(groupFilter) {
|
||||||
|
var self = this;
|
||||||
|
return this.cache.getGroups().then(function(groups) {
|
||||||
|
groups = findByFilter(groups, groupFilter);
|
||||||
|
var hostids = _.flatten(_.map(groups, 'hosts'));
|
||||||
|
if (hostids.length) {
|
||||||
|
return self.cache.getIndexedHosts().then(function(hosts) {
|
||||||
|
return _.map(hostids, function(hostid) {
|
||||||
|
return hosts[hostid];
|
||||||
});
|
});
|
||||||
} else {
|
});
|
||||||
return [];
|
} else {
|
||||||
}
|
return [];
|
||||||
});
|
}
|
||||||
};
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get list of applications belonging to given groups and hosts.
|
* Get list of applications belonging to given groups and hosts.
|
||||||
* @return list of applications belonging to given hosts
|
* @return list of applications belonging to given hosts
|
||||||
*/
|
*/
|
||||||
this.filterApplications = function(groupFilter, hostFilter) {
|
filterApplications(groupFilter, hostFilter) {
|
||||||
var promises = [
|
var promises = [
|
||||||
this.filterHosts(groupFilter),
|
this.filterHosts(groupFilter),
|
||||||
this.cache.getApplications()
|
this.cache.getApplications()
|
||||||
];
|
];
|
||||||
|
|
||||||
return $q.all(promises).then(function(results) {
|
return this.$q.all(promises).then(function(results) {
|
||||||
var hostList = results[0];
|
var hostList = results[0];
|
||||||
var applicationList = results[1];
|
var applicationList = results[1];
|
||||||
|
|
||||||
var hosts = findByFilter(hostList, hostFilter);
|
var hosts = findByFilter(hostList, hostFilter);
|
||||||
|
if (hosts) {
|
||||||
|
var hostsids = _.map(hosts, 'hostid');
|
||||||
|
return _.filter(applicationList, function (appObj) {
|
||||||
|
return _.intersection(hostsids, appObj.hosts).length;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
filterItems(groupFilter, hostFilter, appFilter, itemType, showDisabledItems) {
|
||||||
|
var hosts;
|
||||||
|
var apps;
|
||||||
|
var items;
|
||||||
|
|
||||||
|
var promises = [
|
||||||
|
this.filterHosts(groupFilter),
|
||||||
|
this.filterApplications(groupFilter, hostFilter),
|
||||||
|
this.cache.getIndexedHosts(),
|
||||||
|
this.cache.getIndexedApplications()
|
||||||
|
];
|
||||||
|
|
||||||
|
return this.$q.all(promises).then(function(results) {
|
||||||
|
var hostList = results[0];
|
||||||
|
var applicationList = results[1];
|
||||||
|
var idx_hosts = results[2];
|
||||||
|
var idx_apps = results[3];
|
||||||
|
|
||||||
|
// Filter hosts
|
||||||
|
hosts = findByFilter(hostList, hostFilter);
|
||||||
|
idx_hosts = getFromIndex(idx_hosts, _.map(hosts, 'hostid'));
|
||||||
|
|
||||||
|
// Filter applications
|
||||||
|
if (appFilter === "") {
|
||||||
|
// Get all items
|
||||||
|
apps = undefined;
|
||||||
if (hosts) {
|
if (hosts) {
|
||||||
var hostsids = _.map(hosts, 'hostid');
|
// Get all items in given hosts
|
||||||
return _.filter(applicationList, function (appObj) {
|
|
||||||
return _.intersection(hostsids, appObj.hosts).length;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.filterItems = function (groupFilter, hostFilter, appFilter, itemType, showDisabledItems) {
|
|
||||||
var hosts;
|
|
||||||
var apps;
|
|
||||||
var items;
|
|
||||||
|
|
||||||
var promises = [
|
|
||||||
this.filterHosts(groupFilter),
|
|
||||||
this.filterApplications(groupFilter, hostFilter),
|
|
||||||
this.cache.getIndexedHosts(),
|
|
||||||
this.cache.getIndexedApplications()
|
|
||||||
];
|
|
||||||
|
|
||||||
return $q.all(promises).then(function(results) {
|
|
||||||
var hostList = results[0];
|
|
||||||
var applicationList = results[1];
|
|
||||||
var idx_hosts = results[2];
|
|
||||||
var idx_apps = results[3];
|
|
||||||
|
|
||||||
// Filter hosts
|
|
||||||
hosts = findByFilter(hostList, hostFilter);
|
|
||||||
idx_hosts = getFromIndex(idx_hosts, _.map(hosts, 'hostid'));
|
|
||||||
|
|
||||||
// Filter applications
|
|
||||||
if (appFilter === "") {
|
|
||||||
// Get all items
|
|
||||||
apps = undefined;
|
|
||||||
if (hosts) {
|
|
||||||
// Get all items in given hosts
|
|
||||||
items = _.flatten(_.map(idx_hosts, function(host) {
|
|
||||||
return _.values(host.idx_items);
|
|
||||||
}), true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
apps = findByFilter(applicationList, appFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apps) {
|
|
||||||
// Get ids for finded applications
|
|
||||||
var appids = _.flatten(_.map(apps, 'applicationids'));
|
|
||||||
appids = _.flatten(_.map(_.map(hosts, 'applications'), function(apps) {
|
|
||||||
return _.intersection(apps, appids);
|
|
||||||
}));
|
|
||||||
|
|
||||||
// For each finded host get list of items in finded applications
|
|
||||||
items = _.flatten(_.map(idx_hosts, function(host) {
|
items = _.flatten(_.map(idx_hosts, function(host) {
|
||||||
var host_apps = _.intersection(appids, host.applications);
|
return _.values(host.idx_items);
|
||||||
var host_itemids = _.flatten(_.map(getFromIndex(idx_apps, host_apps), 'itemids'));
|
|
||||||
return _.values(getFromIndex(host.idx_items, host_itemids));
|
|
||||||
}), true);
|
}), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!showDisabledItems) {
|
|
||||||
items = _.filter(items, {'status': '0'});
|
|
||||||
}
|
|
||||||
|
|
||||||
return items;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build query - convert target filters to array of Zabbix items
|
|
||||||
*/
|
|
||||||
this.buildFromCache = function (groupFilter, hostFilter, appFilter, itemFilter) {
|
|
||||||
return this.filterItems(groupFilter, hostFilter, appFilter).then(function(items) {
|
|
||||||
if (items.length) {
|
|
||||||
if (utils.isRegex(itemFilter)) {
|
|
||||||
return findByFilter(items, itemFilter);
|
|
||||||
} else {
|
|
||||||
return _.filter(items, {'name': itemFilter});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build query - convert target filters to array of Zabbix items
|
|
||||||
*/
|
|
||||||
this.buildTriggerQueryFromCache = function (groupFilter, hostFilter, appFilter) {
|
|
||||||
var promises = [
|
|
||||||
this.cache.getGroups().then(function(groups) {
|
|
||||||
return _.filter(groups, function(group) {
|
|
||||||
if (utils.isRegex(groupFilter)) {
|
|
||||||
return utils.buildRegex(groupFilter).test(group.name);
|
|
||||||
} else {
|
|
||||||
return group.name === groupFilter;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
this.filterHosts(groupFilter).then(function(hosts) {
|
|
||||||
return _.filter(hosts, function(host) {
|
|
||||||
if (utils.isRegex(hostFilter)) {
|
|
||||||
return utils.buildRegex(hostFilter).test(host.name);
|
|
||||||
} else {
|
|
||||||
return host.name === hostFilter;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
this.filterApplications(groupFilter, hostFilter).then(function(apps) {
|
|
||||||
return _.filter(apps, function(app) {
|
|
||||||
if (utils.isRegex(appFilter)) {
|
|
||||||
return utils.buildRegex(appFilter).test(app.name);
|
|
||||||
} else {
|
|
||||||
return app.name === appFilter;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
return $q.all(promises).then(function(results) {
|
|
||||||
var filteredGroups = results[0];
|
|
||||||
var filteredHosts = results[1];
|
|
||||||
var filteredApps = results[2];
|
|
||||||
var query = {};
|
|
||||||
|
|
||||||
if (appFilter) {
|
|
||||||
query.applicationids = _.flatten(_.map(filteredApps, 'applicationids'));
|
|
||||||
}
|
|
||||||
if (hostFilter) {
|
|
||||||
query.hostids = _.map(filteredHosts, 'hostid');
|
|
||||||
}
|
|
||||||
if (groupFilter) {
|
|
||||||
query.groupids = _.map(filteredGroups, 'groupid');
|
|
||||||
}
|
|
||||||
|
|
||||||
return query;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert Zabbix API history.get response to Grafana format
|
|
||||||
*
|
|
||||||
* @return {Array} Array of timeseries in Grafana format
|
|
||||||
* {
|
|
||||||
* target: "Metric name",
|
|
||||||
* datapoints: [[<value>, <unixtime>], ...]
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
this.convertHistory = function(history, addHostName, convertPointCallback) {
|
|
||||||
/**
|
|
||||||
* Response should be in the format:
|
|
||||||
* data: [
|
|
||||||
* {
|
|
||||||
* target: "Metric name",
|
|
||||||
* datapoints: [[<value>, <unixtime>], ...]
|
|
||||||
* }, ...
|
|
||||||
* ]
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Group history by itemid
|
|
||||||
var grouped_history = _.groupBy(history, 'itemid');
|
|
||||||
|
|
||||||
return _.map(grouped_history, function(hist, itemid) {
|
|
||||||
var item = self.cache.getItem(itemid);
|
|
||||||
var alias = item.name;
|
|
||||||
if (addHostName) {
|
|
||||||
var host = self.cache.getHost(item.hostid);
|
|
||||||
alias = host.name + ": " + alias;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
target: alias,
|
|
||||||
datapoints: _.map(hist, convertPointCallback)
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.handleHistory = function(history, addHostName) {
|
|
||||||
return this.convertHistory(history, addHostName, convertHistoryPoint);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.handleTrends = function(history, addHostName, valueType) {
|
|
||||||
var convertPointCallback = _.partial(convertTrendPoint, valueType);
|
|
||||||
return this.convertHistory(history, addHostName, convertPointCallback);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.handleSLAResponse = function (itservice, slaProperty, slaObject) {
|
|
||||||
var targetSLA = slaObject[itservice.serviceid].sla[0];
|
|
||||||
if (slaProperty.property === 'status') {
|
|
||||||
var targetStatus = parseInt(slaObject[itservice.serviceid].status);
|
|
||||||
return {
|
|
||||||
target: itservice.name + ' ' + slaProperty.name,
|
|
||||||
datapoints: [
|
|
||||||
[targetStatus, targetSLA.to * 1000]
|
|
||||||
]
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
return {
|
apps = findByFilter(applicationList, appFilter);
|
||||||
target: itservice.name + ' ' + slaProperty.name,
|
|
||||||
datapoints: [
|
|
||||||
[targetSLA[slaProperty.property], targetSLA.from * 1000],
|
|
||||||
[targetSLA[slaProperty.property], targetSLA.to * 1000]
|
|
||||||
]
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
if (apps) {
|
||||||
|
// Get ids for finded applications
|
||||||
|
var appids = _.flatten(_.map(apps, 'applicationids'));
|
||||||
|
appids = _.flatten(_.map(_.map(hosts, 'applications'), function(apps) {
|
||||||
|
return _.intersection(apps, appids);
|
||||||
|
}));
|
||||||
|
|
||||||
|
// For each finded host get list of items in finded applications
|
||||||
|
items = _.flatten(_.map(idx_hosts, function(host) {
|
||||||
|
var host_apps = _.intersection(appids, host.applications);
|
||||||
|
var host_itemids = _.flatten(_.map(getFromIndex(idx_apps, host_apps), 'itemids'));
|
||||||
|
return _.values(getFromIndex(host.idx_items, host_itemids));
|
||||||
|
}), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!showDisabledItems) {
|
||||||
|
items = _.filter(items, {'status': '0'});
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return QueryProcessor;
|
/**
|
||||||
});
|
* Build query - convert target filters to array of Zabbix items
|
||||||
|
*/
|
||||||
|
buildFromCache(groupFilter, hostFilter, appFilter, itemFilter) {
|
||||||
|
return this.filterItems(groupFilter, hostFilter, appFilter).then(function(items) {
|
||||||
|
if (items.length) {
|
||||||
|
if (utils.isRegex(itemFilter)) {
|
||||||
|
return findByFilter(items, itemFilter);
|
||||||
|
} else {
|
||||||
|
return _.filter(items, {'name': itemFilter});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find group, host, app or item by given name.
|
* Build query - convert target filters to array of Zabbix items
|
||||||
* @param list list of groups, apps or other
|
*/
|
||||||
* @param name visible name
|
buildTriggerQueryFromCache(groupFilter, hostFilter, appFilter) {
|
||||||
* @return array with finded element or undefined
|
var promises = [
|
||||||
*/
|
this.cache.getGroups().then(function(groups) {
|
||||||
function findByName(list, name) {
|
return _.filter(groups, function(group) {
|
||||||
var finded = _.find(list, {'name': name});
|
if (utils.isRegex(groupFilter)) {
|
||||||
if (finded) {
|
return utils.buildRegex(groupFilter).test(group.name);
|
||||||
return [finded];
|
} else {
|
||||||
} else {
|
return group.name === groupFilter;
|
||||||
return undefined;
|
}
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
this.filterHosts(groupFilter).then(function(hosts) {
|
||||||
|
return _.filter(hosts, function(host) {
|
||||||
|
if (utils.isRegex(hostFilter)) {
|
||||||
|
return utils.buildRegex(hostFilter).test(host.name);
|
||||||
|
} else {
|
||||||
|
return host.name === hostFilter;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
this.filterApplications(groupFilter, hostFilter).then(function(apps) {
|
||||||
|
return _.filter(apps, function(app) {
|
||||||
|
if (utils.isRegex(appFilter)) {
|
||||||
|
return utils.buildRegex(appFilter).test(app.name);
|
||||||
|
} else {
|
||||||
|
return app.name === appFilter;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
return this.$q.all(promises).then(function(results) {
|
||||||
|
var filteredGroups = results[0];
|
||||||
|
var filteredHosts = results[1];
|
||||||
|
var filteredApps = results[2];
|
||||||
|
var query = {};
|
||||||
|
|
||||||
|
if (appFilter) {
|
||||||
|
query.applicationids = _.flatten(_.map(filteredApps, 'applicationids'));
|
||||||
|
}
|
||||||
|
if (hostFilter) {
|
||||||
|
query.hostids = _.map(filteredHosts, 'hostid');
|
||||||
|
}
|
||||||
|
if (groupFilter) {
|
||||||
|
query.groupids = _.map(filteredGroups, 'groupid');
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert Zabbix API history.get response to Grafana format
|
||||||
|
*
|
||||||
|
* @return {Array} Array of timeseries in Grafana format
|
||||||
|
* {
|
||||||
|
* target: "Metric name",
|
||||||
|
* datapoints: [[<value>, <unixtime>], ...]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
convertHistory(history, addHostName, convertPointCallback) {
|
||||||
|
/**
|
||||||
|
* Response should be in the format:
|
||||||
|
* data: [
|
||||||
|
* {
|
||||||
|
* target: "Metric name",
|
||||||
|
* datapoints: [[<value>, <unixtime>], ...]
|
||||||
|
* }, ...
|
||||||
|
* ]
|
||||||
|
*/
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
// Group history by itemid
|
||||||
|
var grouped_history = _.groupBy(history, 'itemid');
|
||||||
|
|
||||||
|
return _.map(grouped_history, function(hist, itemid) {
|
||||||
|
var item = self.cache.getItem(itemid);
|
||||||
|
var alias = item.name;
|
||||||
|
if (addHostName) {
|
||||||
|
var host = self.cache.getHost(item.hostid);
|
||||||
|
alias = host.name + ": " + alias;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
target: alias,
|
||||||
|
datapoints: _.map(hist, convertPointCallback)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleHistory(history, addHostName) {
|
||||||
|
return this.convertHistory(history, addHostName, convertHistoryPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTrends(history, addHostName, valueType) {
|
||||||
|
var convertPointCallback = _.partial(convertTrendPoint, valueType);
|
||||||
|
return this.convertHistory(history, addHostName, convertPointCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSLAResponse(itservice, slaProperty, slaObject) {
|
||||||
|
var targetSLA = slaObject[itservice.serviceid].sla[0];
|
||||||
|
if (slaProperty.property === 'status') {
|
||||||
|
var targetStatus = parseInt(slaObject[itservice.serviceid].status);
|
||||||
|
return {
|
||||||
|
target: itservice.name + ' ' + slaProperty.name,
|
||||||
|
datapoints: [
|
||||||
|
[targetStatus, targetSLA.to * 1000]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
target: itservice.name + ' ' + slaProperty.name,
|
||||||
|
datapoints: [
|
||||||
|
[targetSLA[slaProperty.property], targetSLA.from * 1000],
|
||||||
|
[targetSLA[slaProperty.property], targetSLA.to * 1000]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function findByRegex(list, regex) {
|
return QueryProcessor;
|
||||||
var filterPattern = utils.buildRegex(regex);
|
|
||||||
return _.filter(list, function (zbx_obj) {
|
|
||||||
return filterPattern.test(zbx_obj.name);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function findByFilter(list, filter) {
|
|
||||||
if (utils.isRegex(filter)) {
|
|
||||||
return findByRegex(list, filter);
|
|
||||||
} else {
|
|
||||||
return findByName(list, filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFromIndex(index, objids) {
|
|
||||||
return _.map(objids, function(id) {
|
|
||||||
return index[id];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertHistoryPoint(point) {
|
|
||||||
// Value must be a number for properly work
|
|
||||||
return [
|
|
||||||
Number(point.value),
|
|
||||||
point.clock * 1000
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertTrendPoint(valueType, point) {
|
|
||||||
var value;
|
|
||||||
switch (valueType) {
|
|
||||||
case "min":
|
|
||||||
value = point.value_min;
|
|
||||||
break;
|
|
||||||
case "max":
|
|
||||||
value = point.value_max;
|
|
||||||
break;
|
|
||||||
case "avg":
|
|
||||||
value = point.value_avg;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
value = point.value_avg;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
Number(value),
|
|
||||||
point.clock * 1000
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find group, host, app or item by given name.
|
||||||
|
* @param list list of groups, apps or other
|
||||||
|
* @param name visible name
|
||||||
|
* @return array with finded element or undefined
|
||||||
|
*/
|
||||||
|
function findByName(list, name) {
|
||||||
|
var finded = _.find(list, {'name': name});
|
||||||
|
if (finded) {
|
||||||
|
return [finded];
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findByRegex(list, regex) {
|
||||||
|
var filterPattern = utils.buildRegex(regex);
|
||||||
|
return _.filter(list, function (zbx_obj) {
|
||||||
|
return filterPattern.test(zbx_obj.name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function findByFilter(list, filter) {
|
||||||
|
if (utils.isRegex(filter)) {
|
||||||
|
return findByRegex(list, filter);
|
||||||
|
} else {
|
||||||
|
return findByName(list, filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFromIndex(index, objids) {
|
||||||
|
return _.map(objids, function(id) {
|
||||||
|
return index[id];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertHistoryPoint(point) {
|
||||||
|
// Value must be a number for properly work
|
||||||
|
return [
|
||||||
|
Number(point.value),
|
||||||
|
point.clock * 1000
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertTrendPoint(valueType, point) {
|
||||||
|
var value;
|
||||||
|
switch (valueType) {
|
||||||
|
case "min":
|
||||||
|
value = point.value_min;
|
||||||
|
break;
|
||||||
|
case "max":
|
||||||
|
value = point.value_max;
|
||||||
|
break;
|
||||||
|
case "avg":
|
||||||
|
value = point.value_avg;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
value = point.value_avg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
Number(value),
|
||||||
|
point.clock * 1000
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,27 +1,25 @@
|
|||||||
define([
|
import angular from 'angular';
|
||||||
'angular',
|
import _ from 'lodash';
|
||||||
'lodash',
|
import * as utils from './utils';
|
||||||
'./utils'
|
|
||||||
],
|
|
||||||
function (angular, _, utils) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var module = angular.module('grafana.services');
|
// Use factory() instead service() for multiple datasources support.
|
||||||
|
// Each datasource instance must initialize its own cache.
|
||||||
|
|
||||||
// Use factory() instead service() for multiple datasources support.
|
/** @ngInject */
|
||||||
// Each datasource instance must initialize its own cache.
|
angular.module('grafana.services').factory('ZabbixCachingProxy', function($q, $interval) {
|
||||||
module.factory('ZabbixCachingProxy', function($q, $interval) {
|
|
||||||
|
|
||||||
function ZabbixCachingProxy(zabbixAPI, ttl) {
|
class ZabbixCachingProxy {
|
||||||
|
constructor(zabbixAPI, ttl) {
|
||||||
this.zabbixAPI = zabbixAPI;
|
this.zabbixAPI = zabbixAPI;
|
||||||
this.ttl = ttl;
|
this.ttl = ttl;
|
||||||
|
|
||||||
|
this.$q = $q;
|
||||||
|
|
||||||
// Internal objects for data storing
|
// Internal objects for data storing
|
||||||
this._groups = undefined;
|
this._groups = undefined;
|
||||||
this._hosts = undefined;
|
this._hosts = undefined;
|
||||||
this._applications = undefined;
|
this._applications = undefined;
|
||||||
this._items = undefined;
|
this._items = undefined;
|
||||||
this._hostsExtend = undefined;
|
|
||||||
this.storage = {
|
this.storage = {
|
||||||
history: {},
|
history: {},
|
||||||
trends: {}
|
trends: {}
|
||||||
@@ -34,7 +32,7 @@ function (angular, _, utils) {
|
|||||||
this.historyPromises = {};
|
this.historyPromises = {};
|
||||||
|
|
||||||
// Wrap _refresh() method to call it once.
|
// Wrap _refresh() method to call it once.
|
||||||
this.refresh = callOnce(p._refresh, this.refreshPromise);
|
this.refresh = callOnce(this._refresh, this.refreshPromise);
|
||||||
|
|
||||||
// Update cache periodically
|
// Update cache periodically
|
||||||
$interval(_.bind(this.refresh, this), this.ttl);
|
$interval(_.bind(this.refresh, this), this.ttl);
|
||||||
@@ -44,9 +42,7 @@ function (angular, _, utils) {
|
|||||||
this.historyPromises);
|
this.historyPromises);
|
||||||
}
|
}
|
||||||
|
|
||||||
var p = ZabbixCachingProxy.prototype;
|
_refresh() {
|
||||||
|
|
||||||
p._refresh = function() {
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var promises = [
|
var promises = [
|
||||||
this.zabbixAPI.getGroups(),
|
this.zabbixAPI.getGroups(),
|
||||||
@@ -56,7 +52,7 @@ function (angular, _, utils) {
|
|||||||
this.zabbixAPI.getHostsExtend()
|
this.zabbixAPI.getHostsExtend()
|
||||||
];
|
];
|
||||||
|
|
||||||
return $q.all(promises).then(function(results) {
|
return this.$q.all(promises).then(function(results) {
|
||||||
if (results.length) {
|
if (results.length) {
|
||||||
self._groups = convertGroups(results[0]);
|
self._groups = convertGroups(results[0]);
|
||||||
self._hosts = convertHosts(results[1]);
|
self._hosts = convertHosts(results[1]);
|
||||||
@@ -67,94 +63,76 @@ function (angular, _, utils) {
|
|||||||
}
|
}
|
||||||
self._initialized = true;
|
self._initialized = true;
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
p.getGroups = function() {
|
getGroups() {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (this._groups) {
|
if (this._groups) {
|
||||||
return $q.when(self._groups);
|
return this.$q.when(self._groups);
|
||||||
} else {
|
} else {
|
||||||
return this.refresh().then(function() {
|
return this.refresh().then(function() {
|
||||||
return self._groups;
|
return self._groups;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
p.getHosts = function() {
|
getHosts() {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (this._hosts) {
|
if (this._hosts) {
|
||||||
return $q.when(self._hosts);
|
return this.$q.when(self._hosts);
|
||||||
} else {
|
} else {
|
||||||
return this.refresh().then(function() {
|
return this.refresh().then(function() {
|
||||||
return self._hosts;
|
return self._hosts;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
p.getIndexedHosts = function() {
|
getIndexedHosts() {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (this._idx_hosts) {
|
if (this._idx_hosts) {
|
||||||
return $q.when(self._idx_hosts);
|
return this.$q.when(self._idx_hosts);
|
||||||
} else {
|
} else {
|
||||||
return this.refresh().then(function() {
|
return this.refresh().then(function() {
|
||||||
return self._idx_hosts;
|
return self._idx_hosts;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
p.getIndexedApplications = function() {
|
getIndexedApplications() {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (this._idx_apps) {
|
if (this._idx_apps) {
|
||||||
return $q.when(self._idx_apps);
|
return this.$q.when(self._idx_apps);
|
||||||
} else {
|
} else {
|
||||||
return this.refresh().then(function() {
|
return this.refresh().then(function() {
|
||||||
return self._idx_apps;
|
return self._idx_apps;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
p.getApplications = function() {
|
getApplications() {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (this._applications) {
|
if (this._applications) {
|
||||||
return $q.when(self._applications);
|
return this.$q.when(self._applications);
|
||||||
} else {
|
} else {
|
||||||
return this.refresh().then(function() {
|
return this.refresh().then(function() {
|
||||||
return self._applications;
|
return self._applications;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
p.getItems = function(type) {
|
getItems(type) {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (this._items) {
|
if (this._items) {
|
||||||
return $q.when(filterItems(self._items, type));
|
return this.$q.when(filterItems(self._items, type));
|
||||||
} else {
|
} else {
|
||||||
return this.refresh().then(function() {
|
return this.refresh().then(function() {
|
||||||
return filterItems(self._items, type);
|
return filterItems(self._items, type);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
function filterItems(items, type) {
|
|
||||||
switch (type) {
|
|
||||||
case 'num':
|
|
||||||
return _.filter(items, function(item) {
|
|
||||||
return (item.value_type === '0' ||
|
|
||||||
item.value_type === '3');
|
|
||||||
});
|
|
||||||
case 'text':
|
|
||||||
return _.filter(items, function(item) {
|
|
||||||
return (item.value_type === '1' ||
|
|
||||||
item.value_type === '2' ||
|
|
||||||
item.value_type === '4');
|
|
||||||
});
|
|
||||||
default:
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p.getHistoryFromCache = function(items, time_from, time_till) {
|
getHistoryFromCache(items, time_from, time_till) {
|
||||||
var deferred = $q.defer();
|
var deferred = this.$q.defer();
|
||||||
var historyStorage = this.storage.history;
|
var historyStorage = this.storage.history;
|
||||||
var full_history;
|
var full_history;
|
||||||
var expired = _.filter(_.indexBy(items, 'itemid'), function(item, itemid) {
|
var expired = _.filter(_.indexBy(items, 'itemid'), function(item, itemid) {
|
||||||
@@ -182,161 +160,177 @@ function (angular, _, utils) {
|
|||||||
deferred.resolve(_.flatten(full_history, true));
|
deferred.resolve(_.flatten(full_history, true));
|
||||||
}
|
}
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
};
|
}
|
||||||
|
|
||||||
p.getHistoryFromAPI = function(items, time_from, time_till) {
|
getHistoryFromAPI(items, time_from, time_till) {
|
||||||
return this.zabbixAPI.getHistory(items, time_from, time_till);
|
return this.zabbixAPI.getHistory(items, time_from, time_till);
|
||||||
};
|
}
|
||||||
|
|
||||||
p.getHost = function(hostid) {
|
getHost(hostid) {
|
||||||
return _.find(this._hosts, {'hostid': hostid});
|
return _.find(this._hosts, {'hostid': hostid});
|
||||||
};
|
}
|
||||||
|
|
||||||
p.getItem = function(itemid) {
|
getItem(itemid) {
|
||||||
return _.find(this._items, {'itemid': itemid});
|
return _.find(this._items, {'itemid': itemid});
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert host.get response to cache format
|
|
||||||
* host.groups - array of group ids
|
|
||||||
*/
|
|
||||||
function convertHosts(hosts) {
|
|
||||||
return _.forEach(hosts, function(host) {
|
|
||||||
host.groups = _.map(host.groups, 'groupid');
|
|
||||||
return host;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function convertGroups(groups) {
|
function callHistoryOnce(func, promiseKeeper) {
|
||||||
return _.forEach(groups, function(group) {
|
return function() {
|
||||||
group.hosts = _.map(group.hosts, 'hostid');
|
var itemids = _.map(arguments[0], 'itemid');
|
||||||
return group;
|
var stamp = itemids.join() + arguments[1] + arguments[2];
|
||||||
});
|
var hash = stamp.getHash();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
var deferred = $q.defer();
|
||||||
* Group Zabbix applications by name
|
if (!promiseKeeper[hash]) {
|
||||||
* host.hosts - array of host ids
|
promiseKeeper[hash] = deferred.promise;
|
||||||
*/
|
func.apply(this, arguments).then(function(result) {
|
||||||
function convertApplications(applications) {
|
deferred.resolve(result);
|
||||||
return _.map(_.groupBy(applications, 'name'), function(value, key) {
|
promiseKeeper[hash] = null;
|
||||||
//console.log(value);
|
|
||||||
// Hack for supporting different apis (2.2 vs 2.4 vs 3.0)
|
|
||||||
var hostField = 'host';
|
|
||||||
if (value[0] && value[0]['hosts']) {
|
|
||||||
// For Zabbix 2.2
|
|
||||||
hostField = 'hosts';
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: key,
|
|
||||||
applicationids: _.map(value, 'applicationid'),
|
|
||||||
itemids: _.uniq(_.map(_.flatten(value, 'items'), 'itemid')),
|
|
||||||
hosts: _.uniq(_.map(_.flatten(value, hostField), 'hostid'))
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function indexHosts(hosts) {
|
|
||||||
return _.indexBy(_.map(hosts, function(host) {
|
|
||||||
|
|
||||||
// Expand item names
|
|
||||||
host.items = _.forEach(host.items, function(item) {
|
|
||||||
item.item = item.name;
|
|
||||||
item.name = utils.expandItemName(item.item, item.key_);
|
|
||||||
return item;
|
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
host.applications = _.map(host.applications, 'applicationid');
|
return promiseKeeper[hash];
|
||||||
host.idx_items = indexItems(host.items);
|
|
||||||
host.items = _.map(host.items, 'itemid');
|
|
||||||
return host;
|
|
||||||
}), 'hostid');
|
|
||||||
}
|
|
||||||
|
|
||||||
function indexApps(applications) {
|
|
||||||
return _.indexBy(_.map(applications, function(app) {
|
|
||||||
return {
|
|
||||||
name: app.name,
|
|
||||||
applicationid: app.applicationid,
|
|
||||||
host: _.first(_.map(app.hosts, 'hostid')),
|
|
||||||
itemids: _.map(app.items, 'itemid')
|
|
||||||
};
|
|
||||||
}), 'applicationid');
|
|
||||||
}
|
|
||||||
|
|
||||||
function indexItems(items) {
|
|
||||||
return _.indexBy(_.map(items, function(item) {
|
|
||||||
return item;
|
|
||||||
}), 'itemid');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert item.get response to cache format
|
|
||||||
* item.applications - array of application ids
|
|
||||||
* item.item - original item name returned by api (ie "CPU $2 time")
|
|
||||||
* item.name - expanded name (ie "CPU system time")
|
|
||||||
*/
|
|
||||||
function convertItems(items) {
|
|
||||||
return _.forEach(items, function(item) {
|
|
||||||
item.applications = _.map(item.applications, 'applicationid');
|
|
||||||
item.item = item.name;
|
|
||||||
item.name = utils.expandItemName(item.item, item.key_);
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
String.prototype.getHash = function() {
|
|
||||||
var hash = 0, i, chr, len;
|
|
||||||
if (this.length === 0) {
|
|
||||||
return hash;
|
|
||||||
}
|
}
|
||||||
for (i = 0, len = this.length; i < len; i++) {
|
return deferred.promise;
|
||||||
chr = this.charCodeAt(i);
|
|
||||||
hash = ((hash << 5) - hash) + chr;
|
|
||||||
hash |= 0; // Convert to 32bit integer
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function callHistoryOnce(func, promiseKeeper) {
|
function callOnce(func, promiseKeeper) {
|
||||||
return function() {
|
return function() {
|
||||||
var itemids = _.map(arguments[0], 'itemid');
|
var deferred = $q.defer();
|
||||||
var stamp = itemids.join() + arguments[1] + arguments[2];
|
if (!promiseKeeper) {
|
||||||
var hash = stamp.getHash();
|
promiseKeeper = deferred.promise;
|
||||||
|
func.apply(this, arguments).then(function(result) {
|
||||||
var deferred = $q.defer();
|
deferred.resolve(result);
|
||||||
if (!promiseKeeper[hash]) {
|
promiseKeeper = null;
|
||||||
promiseKeeper[hash] = deferred.promise;
|
});
|
||||||
func.apply(this, arguments).then(function(result) {
|
} else {
|
||||||
deferred.resolve(result);
|
return promiseKeeper;
|
||||||
promiseKeeper[hash] = null;
|
}
|
||||||
});
|
return deferred.promise;
|
||||||
} else {
|
};
|
||||||
return promiseKeeper[hash];
|
}
|
||||||
}
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function callOnce(func, promiseKeeper) {
|
|
||||||
return function() {
|
|
||||||
var deferred = $q.defer();
|
|
||||||
if (!promiseKeeper) {
|
|
||||||
promiseKeeper = deferred.promise;
|
|
||||||
func.apply(this, arguments).then(function(result) {
|
|
||||||
deferred.resolve(result);
|
|
||||||
promiseKeeper = null;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return promiseKeeper;
|
|
||||||
}
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return ZabbixCachingProxy;
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
return ZabbixCachingProxy;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert host.get response to cache format
|
||||||
|
* host.groups - array of group ids
|
||||||
|
*/
|
||||||
|
function convertHosts(hosts) {
|
||||||
|
return _.forEach(hosts, function(host) {
|
||||||
|
host.groups = _.map(host.groups, 'groupid');
|
||||||
|
return host;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertGroups(groups) {
|
||||||
|
return _.forEach(groups, function(group) {
|
||||||
|
group.hosts = _.map(group.hosts, 'hostid');
|
||||||
|
return group;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group Zabbix applications by name
|
||||||
|
* host.hosts - array of host ids
|
||||||
|
*/
|
||||||
|
function convertApplications(applications) {
|
||||||
|
return _.map(_.groupBy(applications, 'name'), function(value, key) {
|
||||||
|
//console.log(value);
|
||||||
|
// Hack for supporting different apis (2.2 vs 2.4 vs 3.0)
|
||||||
|
var hostField = 'host';
|
||||||
|
if (value[0] && value[0]['hosts']) {
|
||||||
|
// For Zabbix 2.2
|
||||||
|
hostField = 'hosts';
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: key,
|
||||||
|
applicationids: _.map(value, 'applicationid'),
|
||||||
|
itemids: _.uniq(_.map(_.flatten(value, 'items'), 'itemid')),
|
||||||
|
hosts: _.uniq(_.map(_.flatten(value, hostField), 'hostid'))
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function indexHosts(hosts) {
|
||||||
|
return _.indexBy(_.map(hosts, function(host) {
|
||||||
|
|
||||||
|
// Expand item names
|
||||||
|
host.items = _.forEach(host.items, function(item) {
|
||||||
|
item.item = item.name;
|
||||||
|
item.name = utils.expandItemName(item.item, item.key_);
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
|
||||||
|
host.applications = _.map(host.applications, 'applicationid');
|
||||||
|
host.idx_items = indexItems(host.items);
|
||||||
|
host.items = _.map(host.items, 'itemid');
|
||||||
|
return host;
|
||||||
|
}), 'hostid');
|
||||||
|
}
|
||||||
|
|
||||||
|
function indexApps(applications) {
|
||||||
|
return _.indexBy(_.map(applications, function(app) {
|
||||||
|
return {
|
||||||
|
name: app.name,
|
||||||
|
applicationid: app.applicationid,
|
||||||
|
host: _.first(_.map(app.hosts, 'hostid')),
|
||||||
|
itemids: _.map(app.items, 'itemid')
|
||||||
|
};
|
||||||
|
}), 'applicationid');
|
||||||
|
}
|
||||||
|
|
||||||
|
function indexItems(items) {
|
||||||
|
return _.indexBy(_.map(items, function(item) {
|
||||||
|
return item;
|
||||||
|
}), 'itemid');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert item.get response to cache format
|
||||||
|
* item.applications - array of application ids
|
||||||
|
* item.item - original item name returned by api (ie "CPU $2 time")
|
||||||
|
* item.name - expanded name (ie "CPU system time")
|
||||||
|
*/
|
||||||
|
function convertItems(items) {
|
||||||
|
return _.forEach(items, function(item) {
|
||||||
|
item.applications = _.map(item.applications, 'applicationid');
|
||||||
|
item.item = item.name;
|
||||||
|
item.name = utils.expandItemName(item.item, item.key_);
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterItems(items, type) {
|
||||||
|
switch (type) {
|
||||||
|
case 'num':
|
||||||
|
return _.filter(items, function(item) {
|
||||||
|
return (item.value_type === '0' ||
|
||||||
|
item.value_type === '3');
|
||||||
|
});
|
||||||
|
case 'text':
|
||||||
|
return _.filter(items, function(item) {
|
||||||
|
return (item.value_type === '1' ||
|
||||||
|
item.value_type === '2' ||
|
||||||
|
item.value_type === '4');
|
||||||
|
});
|
||||||
|
default:
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String.prototype.getHash = function() {
|
||||||
|
var hash = 0, i, chr, len;
|
||||||
|
if (this.length === 0) {
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
for (i = 0, len = this.length; i < len; i++) {
|
||||||
|
chr = this.charCodeAt(i);
|
||||||
|
hash = ((hash << 5) - hash) + chr;
|
||||||
|
hash |= 0; // Convert to 32bit integer
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user