Merge branch 'master' into tests
This commit is contained in:
@@ -116,6 +116,22 @@ export default class DataProcessor {
|
||||
return sortByTime(new_timeseries);
|
||||
}
|
||||
|
||||
static limit(order, n, orderByFunc, timeseries) {
|
||||
let orderByCallback = DataProcessor.aggregationFunctions[orderByFunc];
|
||||
let sortByIteratee = (ts) => {
|
||||
let values = _.map(ts.datapoints, (point) => {
|
||||
return point[0];
|
||||
});
|
||||
return orderByCallback(values);
|
||||
};
|
||||
let sortedTimeseries = _.sortBy(timeseries, sortByIteratee);
|
||||
if (order === 'bottom') {
|
||||
return sortedTimeseries.slice(0, n);
|
||||
} else {
|
||||
return sortedTimeseries.slice(-n);
|
||||
}
|
||||
}
|
||||
|
||||
static AVERAGE(values) {
|
||||
var sum = 0;
|
||||
_.each(values, function(value) {
|
||||
@@ -151,6 +167,16 @@ export default class DataProcessor {
|
||||
});
|
||||
}
|
||||
|
||||
static delta(datapoints) {
|
||||
let newSeries = [];
|
||||
let deltaValue;
|
||||
for (var i = 1; i < datapoints.length; i++) {
|
||||
deltaValue = datapoints[i][0] - datapoints[i - 1][0];
|
||||
newSeries.push([deltaValue, datapoints[i][1]]);
|
||||
}
|
||||
return newSeries;
|
||||
}
|
||||
|
||||
static groupByWrapper(interval, groupFunc, datapoints) {
|
||||
var groupByCallback = DataProcessor.aggregationFunctions[groupFunc];
|
||||
return DataProcessor.groupBy(interval, groupByCallback, datapoints);
|
||||
@@ -181,12 +207,15 @@ export default class DataProcessor {
|
||||
return {
|
||||
groupBy: this.groupByWrapper,
|
||||
scale: this.scale,
|
||||
delta: this.delta,
|
||||
aggregateBy: this.aggregateByWrapper,
|
||||
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,
|
||||
top: _.partial(this.limit, 'top'),
|
||||
bottom: _.partial(this.limit, 'bottom'),
|
||||
setAlias: this.setAlias,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -92,7 +92,11 @@ export class ZabbixAPIDatasource {
|
||||
|
||||
_.forEach(target.functions, func => {
|
||||
func.params = _.map(func.params, param => {
|
||||
return this.templateSrv.replace(param, options.scopedVars);
|
||||
if (typeof param === 'number') {
|
||||
return +this.templateSrv.replace(param.toString(), options.scopedVars);
|
||||
} else {
|
||||
return this.templateSrv.replace(param, options.scopedVars);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -158,7 +162,7 @@ export class ZabbixAPIDatasource {
|
||||
// Find trendValue() function and get specified trend value
|
||||
var trendFunctions = _.map(metricFunctions.getCategories()['Trends'], 'name');
|
||||
var trendValueFunc = _.find(target.functions, func => {
|
||||
return _.contains(trendFunctions, func.def.name);
|
||||
return _.includes(trendFunctions, func.def.name);
|
||||
});
|
||||
var valueType = trendValueFunc ? trendValueFunc.params[0] : "avg";
|
||||
|
||||
@@ -181,6 +185,7 @@ export class ZabbixAPIDatasource {
|
||||
return getHistory.then(timeseries_data => {
|
||||
let transformFunctions = bindFunctionDefs(target.functions, 'Transform');
|
||||
let aggregationFunctions = bindFunctionDefs(target.functions, 'Aggregate');
|
||||
let filterFunctions = bindFunctionDefs(target.functions, 'Filter');
|
||||
let aliasFunctions = bindFunctionDefs(target.functions, 'Alias');
|
||||
|
||||
// Apply transformation functions
|
||||
@@ -189,6 +194,11 @@ export class ZabbixAPIDatasource {
|
||||
return timeseries;
|
||||
});
|
||||
|
||||
// Apply filter functions
|
||||
if (filterFunctions.length) {
|
||||
timeseries_data = sequence(filterFunctions)(timeseries_data);
|
||||
}
|
||||
|
||||
// Apply aggregations
|
||||
if (aggregationFunctions.length) {
|
||||
let dp = _.map(timeseries_data, 'datapoints');
|
||||
@@ -196,7 +206,7 @@ export class ZabbixAPIDatasource {
|
||||
|
||||
let aggFuncNames = _.map(metricFunctions.getCategories()['Aggregate'], 'name');
|
||||
let lastAgg = _.findLast(target.functions, func => {
|
||||
return _.contains(aggFuncNames, func.def.name);
|
||||
return _.includes(aggFuncNames, func.def.name);
|
||||
});
|
||||
|
||||
timeseries_data = [
|
||||
@@ -247,10 +257,9 @@ export class ZabbixAPIDatasource {
|
||||
* @return {object} Connection status and Zabbix API version
|
||||
*/
|
||||
testDatasource() {
|
||||
var self = this;
|
||||
return this.zabbixAPI.getVersion()
|
||||
.then(version => {
|
||||
return self.zabbixAPI.login()
|
||||
return this.zabbixAPI.login()
|
||||
.then(auth => {
|
||||
if (auth) {
|
||||
return {
|
||||
@@ -307,7 +316,7 @@ export class ZabbixAPIDatasource {
|
||||
}
|
||||
parts.push(part);
|
||||
});
|
||||
let template = _.object(['group', 'host', 'app', 'item'], parts);
|
||||
let template = _.zipObject(['group', 'host', 'app', 'item'], parts);
|
||||
|
||||
// Get items
|
||||
if (parts.length === 4) {
|
||||
@@ -351,11 +360,10 @@ export class ZabbixAPIDatasource {
|
||||
.buildTriggerQuery(this.replaceTemplateVars(annotation.group, {}),
|
||||
this.replaceTemplateVars(annotation.host, {}),
|
||||
this.replaceTemplateVars(annotation.application, {}));
|
||||
var self = this;
|
||||
|
||||
return buildQuery.then(query => {
|
||||
return self.zabbixAPI
|
||||
.getTriggers(query.groupids, query.hostids, query.applicationids,
|
||||
showTriggers, timeFrom, timeTo)
|
||||
return this.zabbixAPI
|
||||
.getTriggers(query.groupids, query.hostids, query.applicationids, showTriggers)
|
||||
.then(triggers => {
|
||||
|
||||
// Filter triggers by description
|
||||
@@ -375,10 +383,10 @@ export class ZabbixAPIDatasource {
|
||||
});
|
||||
|
||||
var objectids = _.map(triggers, 'triggerid');
|
||||
return self.zabbixAPI
|
||||
return this.zabbixAPI
|
||||
.getEvents(objectids, timeFrom, timeTo, showOkEvents)
|
||||
.then(events => {
|
||||
var indexedTriggers = _.indexBy(triggers, 'triggerid');
|
||||
var indexedTriggers = _.keyBy(triggers, 'triggerid');
|
||||
|
||||
// Hide acknowledged events if option enabled
|
||||
if (annotation.hideAcknowledged) {
|
||||
@@ -388,19 +396,20 @@ export class ZabbixAPIDatasource {
|
||||
}
|
||||
|
||||
return _.map(events, event => {
|
||||
var title ='';
|
||||
let tags;
|
||||
if (annotation.showHostname) {
|
||||
title += event.hosts[0].name + ': ';
|
||||
tags = _.map(event.hosts, 'name');
|
||||
}
|
||||
|
||||
// Show event type (OK or Problem)
|
||||
title += Number(event.value) ? 'Problem' : 'OK';
|
||||
let title = Number(event.value) ? 'Problem' : 'OK';
|
||||
|
||||
var formatted_acknowledges = utils.formatAcknowledges(event.acknowledges);
|
||||
let formatted_acknowledges = utils.formatAcknowledges(event.acknowledges);
|
||||
return {
|
||||
annotation: annotation,
|
||||
time: event.clock * 1000,
|
||||
title: title,
|
||||
tags: tags,
|
||||
text: indexedTriggers[event.objectid].description + formatted_acknowledges
|
||||
};
|
||||
});
|
||||
@@ -414,7 +423,7 @@ export class ZabbixAPIDatasource {
|
||||
function bindFunctionDefs(functionDefs, category) {
|
||||
var aggregationFunctions = _.map(metricFunctions.getCategories()[category], 'name');
|
||||
var aggFuncDefs = _.filter(functionDefs, function(func) {
|
||||
return _.contains(aggregationFunctions, func.def.name);
|
||||
return _.includes(aggregationFunctions, func.def.name);
|
||||
});
|
||||
|
||||
return _.map(aggFuncDefs, function(func) {
|
||||
@@ -423,13 +432,6 @@ function bindFunctionDefs(functionDefs, category) {
|
||||
});
|
||||
}
|
||||
|
||||
function filterFunctionDefs(funcs, category) {
|
||||
let filteredFuncs = _.map(metricFunctions.getCategories()[category]);
|
||||
return _.filter(funcs, func => {
|
||||
return _.contains(filteredFuncs, func.def.name);
|
||||
});
|
||||
}
|
||||
|
||||
function formatMetric(metricObj) {
|
||||
return {
|
||||
text: metricObj.name,
|
||||
@@ -447,7 +449,7 @@ function formatMetric(metricObj) {
|
||||
* template variables, for example
|
||||
* /CPU $cpu_item.*time/ where $cpu_item is system,user,iowait
|
||||
*/
|
||||
function zabbixTemplateFormat(value, variable) {
|
||||
function zabbixTemplateFormat(value) {
|
||||
if (typeof value === 'string') {
|
||||
return utils.escapeRegex(value);
|
||||
}
|
||||
@@ -456,7 +458,8 @@ function zabbixTemplateFormat(value, variable) {
|
||||
return '(' + escapedValues.join('|') + ')';
|
||||
}
|
||||
|
||||
/** If template variables are used in request, replace it using regex format
|
||||
/**
|
||||
* If template variables are used in request, replace it using regex format
|
||||
* and wrap with '/' for proper multi-value work. Example:
|
||||
* $variable selected as a, b, c
|
||||
* We use filter $variable
|
||||
@@ -494,3 +497,7 @@ function sequence(funcsArray) {
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
// Fix for backward compatibility with lodash 2.4
|
||||
if (!_.includes) {_.includes = _.contains;}
|
||||
if (!_.keyBy) {_.keyBy = _.indexBy;}
|
||||
|
||||
@@ -5,6 +5,7 @@ var index = [];
|
||||
var categories = {
|
||||
Transform: [],
|
||||
Aggregate: [],
|
||||
Filter: [],
|
||||
Trends: [],
|
||||
Alias: []
|
||||
};
|
||||
@@ -39,6 +40,13 @@ addFuncDef({
|
||||
defaultParams: [100],
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'delta',
|
||||
category: 'Transform',
|
||||
params: [],
|
||||
defaultParams: [],
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'sumSeries',
|
||||
category: 'Aggregate',
|
||||
@@ -92,6 +100,26 @@ addFuncDef({
|
||||
defaultParams: ['1m', 'avg'],
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'top',
|
||||
category: 'Filter',
|
||||
params: [
|
||||
{ name: 'number', type: 'int' },
|
||||
{ name: 'value', type: 'string', options: ['avg', 'min', 'max', 'median'] }
|
||||
],
|
||||
defaultParams: [5, 'avg'],
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'bottom',
|
||||
category: 'Filter',
|
||||
params: [
|
||||
{ name: 'number', type: 'int' },
|
||||
{ name: 'value', type: 'string', options: ['avg', 'min', 'max', 'median'] }
|
||||
],
|
||||
defaultParams: [5, 'avg'],
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'trendValue',
|
||||
category: 'Trends',
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {QueryCtrl} from 'app/plugins/sdk';
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
import * as utils from './utils';
|
||||
import * as metricFunctions from './metricFunctions';
|
||||
|
||||
@@ -230,13 +230,13 @@ angular.module('grafana.services').factory('QueryProcessor', function($q) {
|
||||
|
||||
// Group history by itemid
|
||||
var grouped_history = _.groupBy(history, 'itemid');
|
||||
var hosts = _.indexBy(_.flatten(_.map(items, 'hosts')), 'hostid');
|
||||
var hosts = _.uniq(_.flatten(_.map(items, 'hosts')),'hostid'); //uniq is needed to deduplicate
|
||||
|
||||
return _.map(grouped_history, function(hist, itemid) {
|
||||
var item = _.find(items, {'itemid': itemid});
|
||||
var alias = item.name;
|
||||
if (_.keys(hosts).length > 1 || addHostName) {
|
||||
var host = hosts[item.hostid];
|
||||
if (_.keys(hosts).length > 1 && addHostName) { //only when actual multi hosts selected
|
||||
var host = _.find(hosts, {'hostid': item.hostid});
|
||||
alias = host.name + ": " + alias;
|
||||
}
|
||||
return {
|
||||
@@ -335,12 +335,6 @@ function getByFilter(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 [
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
|
||||
|
||||
/**
|
||||
* Expand Zabbix item name
|
||||
*
|
||||
@@ -35,7 +34,7 @@ export function isTemplateVariable(str, templateVariables) {
|
||||
var variables = _.map(templateVariables, variable => {
|
||||
return '$' + variable.name;
|
||||
});
|
||||
return _.contains(variables, str);
|
||||
return _.includes(variables, str);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -93,3 +92,8 @@ export function convertToZabbixAPIUrl(url) {
|
||||
return url.replace(trimSlashPattern, "$1");
|
||||
}
|
||||
}
|
||||
|
||||
// Fix for backward compatibility with lodash 2.4
|
||||
if (!_.includes) {
|
||||
_.includes = _.contains;
|
||||
}
|
||||
|
||||
@@ -41,12 +41,12 @@ function ZabbixAPIService($q, alertSrv, zabbixAPICoreService) {
|
||||
request(method, params) {
|
||||
var self = this;
|
||||
|
||||
return this.zabbixAPICore.request(this.url, method, params, this.requestOptions, this.auth)
|
||||
.then(function(result) {
|
||||
return this.zabbixAPICore
|
||||
.request(this.url, method, params, this.requestOptions, this.auth)
|
||||
.then((result) => {
|
||||
return result;
|
||||
},
|
||||
// Handle API errors
|
||||
function(error) {
|
||||
}, (error) => {
|
||||
// Handle API errors
|
||||
if (isNotAuthorized(error.data)) {
|
||||
return self.loginOnce().then(
|
||||
function() {
|
||||
@@ -56,15 +56,18 @@ function ZabbixAPIService($q, alertSrv, zabbixAPICoreService) {
|
||||
function(error) {
|
||||
self.alertAPIError(error.data);
|
||||
});
|
||||
} else {
|
||||
this.alertSrv.set("Connection Error", error.data, 'error', 5000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
alertAPIError(message) {
|
||||
alertAPIError(message, timeout = 5000) {
|
||||
this.alertSrv.set(
|
||||
"Zabbix API Error",
|
||||
message,
|
||||
'error'
|
||||
'error',
|
||||
timeout
|
||||
);
|
||||
}
|
||||
|
||||
@@ -336,6 +339,7 @@ function ZabbixAPIService($q, alertSrv, zabbixAPICoreService) {
|
||||
applicationids: applicationids,
|
||||
expandDescription: true,
|
||||
expandData: true,
|
||||
expandComment: true,
|
||||
monitored: true,
|
||||
skipDependent: true,
|
||||
//only_true: true,
|
||||
|
||||
@@ -51,19 +51,23 @@ class ZabbixAPICoreService {
|
||||
requestOptions.headers.Authorization = options.basicAuth;
|
||||
}
|
||||
|
||||
this.backendSrv.datasourceRequest(requestOptions).then(function (response) {
|
||||
// General connection issues
|
||||
if (!response.data) {
|
||||
deferred.reject(response);
|
||||
}
|
||||
this.backendSrv.datasourceRequest(requestOptions)
|
||||
.then((response) => {
|
||||
// General connection issues
|
||||
if (!response.data) {
|
||||
deferred.reject(response);
|
||||
}
|
||||
|
||||
// Handle Zabbix API errors
|
||||
else if (response.data.error) {
|
||||
deferred.reject(response.data.error);
|
||||
}
|
||||
// Handle Zabbix API errors
|
||||
else if (response.data.error) {
|
||||
deferred.reject(response.data.error);
|
||||
}
|
||||
|
||||
deferred.resolve(response.data.result);
|
||||
}, (error) => {
|
||||
deferred.reject(error.err);
|
||||
});
|
||||
|
||||
deferred.resolve(response.data.result);
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
import * as utils from './utils';
|
||||
|
||||
// Use factory() instead service() for multiple datasources support.
|
||||
// Each datasource instance must initialize its own cache.
|
||||
@@ -117,7 +116,7 @@ angular.module('grafana.services').factory('ZabbixCachingProxy', function($q, $i
|
||||
var deferred = this.$q.defer();
|
||||
var historyStorage = this.storage.history;
|
||||
var full_history;
|
||||
var expired = _.filter(_.indexBy(items, 'itemid'), function(item, itemid) {
|
||||
var expired = _.filter(_.keyBy(items, 'itemid'), function(item, itemid) {
|
||||
return !historyStorage[itemid];
|
||||
});
|
||||
if (expired.length) {
|
||||
@@ -236,3 +235,6 @@ String.prototype.getHash = function() {
|
||||
}
|
||||
return hash;
|
||||
};
|
||||
|
||||
// Fix for backward compatibility with lodash 2.4
|
||||
if (!_.keyBy) {_.keyBy = _.indexBy;}
|
||||
|
||||
Reference in New Issue
Block a user