mirror of
https://github.com/grafana/grafana.git
synced 2026-07-30 00:08:10 -05:00
Merge branch 'master' of github.com:grafana/grafana
This commit is contained in:
@@ -181,25 +181,33 @@ func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) {
|
||||
|
||||
reqParam := &struct {
|
||||
Parameters struct {
|
||||
Namespace string `json:"namespace"`
|
||||
MetricName string `json:"metricName"`
|
||||
Dimensions []*cloudwatch.Dimension `json:"dimensions"`
|
||||
Statistics []*string `json:"statistics"`
|
||||
StartTime int64 `json:"startTime"`
|
||||
EndTime int64 `json:"endTime"`
|
||||
Period int64 `json:"period"`
|
||||
Namespace string `json:"namespace"`
|
||||
MetricName string `json:"metricName"`
|
||||
Dimensions []*cloudwatch.Dimension `json:"dimensions"`
|
||||
Statistics []*string `json:"statistics"`
|
||||
ExtendedStatistics []*string `json:"extendedStatistics"`
|
||||
StartTime int64 `json:"startTime"`
|
||||
EndTime int64 `json:"endTime"`
|
||||
Period int64 `json:"period"`
|
||||
} `json:"parameters"`
|
||||
}{}
|
||||
json.Unmarshal(req.Body, reqParam)
|
||||
|
||||
params := &cloudwatch.GetMetricStatisticsInput{
|
||||
Namespace: aws.String(reqParam.Parameters.Namespace),
|
||||
MetricName: aws.String(reqParam.Parameters.MetricName),
|
||||
Dimensions: reqParam.Parameters.Dimensions,
|
||||
Statistics: reqParam.Parameters.Statistics,
|
||||
StartTime: aws.Time(time.Unix(reqParam.Parameters.StartTime, 0)),
|
||||
EndTime: aws.Time(time.Unix(reqParam.Parameters.EndTime, 0)),
|
||||
Period: aws.Int64(reqParam.Parameters.Period),
|
||||
Namespace: aws.String(reqParam.Parameters.Namespace),
|
||||
MetricName: aws.String(reqParam.Parameters.MetricName),
|
||||
Dimensions: reqParam.Parameters.Dimensions,
|
||||
Statistics: reqParam.Parameters.Statistics,
|
||||
ExtendedStatistics: reqParam.Parameters.ExtendedStatistics,
|
||||
StartTime: aws.Time(time.Unix(reqParam.Parameters.StartTime, 0)),
|
||||
EndTime: aws.Time(time.Unix(reqParam.Parameters.EndTime, 0)),
|
||||
Period: aws.Int64(reqParam.Parameters.Period),
|
||||
}
|
||||
if len(reqParam.Parameters.Statistics) != 0 {
|
||||
params.Statistics = reqParam.Parameters.Statistics
|
||||
}
|
||||
if len(reqParam.Parameters.ExtendedStatistics) != 0 {
|
||||
params.ExtendedStatistics = reqParam.Parameters.ExtendedStatistics
|
||||
}
|
||||
|
||||
resp, err := svc.GetMetricStatistics(params)
|
||||
@@ -292,11 +300,12 @@ func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) {
|
||||
|
||||
reqParam := &struct {
|
||||
Parameters struct {
|
||||
Namespace string `json:"namespace"`
|
||||
MetricName string `json:"metricName"`
|
||||
Dimensions []*cloudwatch.Dimension `json:"dimensions"`
|
||||
Statistic string `json:"statistic"`
|
||||
Period int64 `json:"period"`
|
||||
Namespace string `json:"namespace"`
|
||||
MetricName string `json:"metricName"`
|
||||
Dimensions []*cloudwatch.Dimension `json:"dimensions"`
|
||||
Statistic string `json:"statistic"`
|
||||
ExtendedStatistic string `json:"extendedStatistic"`
|
||||
Period int64 `json:"period"`
|
||||
} `json:"parameters"`
|
||||
}{}
|
||||
json.Unmarshal(req.Body, reqParam)
|
||||
@@ -312,6 +321,9 @@ func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) {
|
||||
if reqParam.Parameters.Statistic != "" {
|
||||
params.Statistic = aws.String(reqParam.Parameters.Statistic)
|
||||
}
|
||||
if reqParam.Parameters.ExtendedStatistic != "" {
|
||||
params.ExtendedStatistic = aws.String(reqParam.Parameters.ExtendedStatistic)
|
||||
}
|
||||
|
||||
resp, err := svc.DescribeAlarmsForMetric(params)
|
||||
if err != nil {
|
||||
|
||||
@@ -52,6 +52,7 @@ func RenderToPng(params *RenderOpts) (string, error) {
|
||||
|
||||
cmdArgs := []string{
|
||||
"--ignore-ssl-errors=true",
|
||||
"--web-security=false",
|
||||
scriptPath,
|
||||
"url=" + url,
|
||||
"width=" + params.Width,
|
||||
|
||||
@@ -112,10 +112,18 @@ function (angular, _, kbn) {
|
||||
this._grafanaVariables[name] = value;
|
||||
};
|
||||
|
||||
this.variableExists = function(expression) {
|
||||
this.getVariableName = function(expression) {
|
||||
this._regex.lastIndex = 0;
|
||||
var match = this._regex.exec(expression);
|
||||
return match && (self._index[match[1] || match[2]] !== void 0);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
return match[1] || match[2];
|
||||
};
|
||||
|
||||
this.variableExists = function(expression) {
|
||||
var name = this.getVariableName(expression);
|
||||
return name && (self._index[name] !== void 0);
|
||||
};
|
||||
|
||||
this.highlightVariablesAsHtml = function(str) {
|
||||
|
||||
@@ -16,6 +16,13 @@ function (angular, _, moment, dateMath, kbn, CloudWatchAnnotationQuery) {
|
||||
this.supportMetrics = true;
|
||||
this.proxyUrl = instanceSettings.url;
|
||||
this.defaultRegion = instanceSettings.jsonData.defaultRegion;
|
||||
this.standardStatistics = [
|
||||
'Average',
|
||||
'Maximum',
|
||||
'Minimum',
|
||||
'Sum',
|
||||
'SampleCount'
|
||||
];
|
||||
|
||||
var self = this;
|
||||
this.query = function(options) {
|
||||
@@ -24,7 +31,7 @@ function (angular, _, moment, dateMath, kbn, CloudWatchAnnotationQuery) {
|
||||
|
||||
var queries = [];
|
||||
options = angular.copy(options);
|
||||
options.targets = this.expandTemplateVariable(options.targets, templateSrv);
|
||||
options.targets = this.expandTemplateVariable(options.targets, options.scopedVars, templateSrv);
|
||||
_.each(options.targets, function(target) {
|
||||
if (target.hide || !target.namespace || !target.metricName || _.isEmpty(target.statistics)) {
|
||||
return;
|
||||
@@ -98,6 +105,8 @@ function (angular, _, moment, dateMath, kbn, CloudWatchAnnotationQuery) {
|
||||
};
|
||||
|
||||
this.performTimeSeriesQuery = function(query, start, end) {
|
||||
var statistics = _.filter(query.statistics, function(s) { return _.includes(self.standardStatistics, s); });
|
||||
var extendedStatistics = _.reject(query.statistics, function(s) { return _.includes(self.standardStatistics, s); });
|
||||
return this.awsRequest({
|
||||
region: query.region,
|
||||
action: 'GetMetricStatistics',
|
||||
@@ -105,7 +114,8 @@ function (angular, _, moment, dateMath, kbn, CloudWatchAnnotationQuery) {
|
||||
namespace: query.namespace,
|
||||
metricName: query.metricName,
|
||||
dimensions: query.dimensions,
|
||||
statistics: query.statistics,
|
||||
statistics: statistics,
|
||||
extendedStatistics: extendedStatistics,
|
||||
startTime: start,
|
||||
endTime: end,
|
||||
period: query.period
|
||||
@@ -268,10 +278,19 @@ function (angular, _, moment, dateMath, kbn, CloudWatchAnnotationQuery) {
|
||||
};
|
||||
|
||||
this.performDescribeAlarmsForMetric = function(region, namespace, metricName, dimensions, statistic, period) {
|
||||
var s = _.includes(self.standardStatistics, statistic) ? statistic : '';
|
||||
var es = _.includes(self.standardStatistics, statistic) ? '' : statistic;
|
||||
return this.awsRequest({
|
||||
region: region,
|
||||
action: 'DescribeAlarmsForMetric',
|
||||
parameters: { namespace: namespace, metricName: metricName, dimensions: dimensions, statistic: statistic, period: period }
|
||||
parameters: {
|
||||
namespace: namespace,
|
||||
metricName: metricName,
|
||||
dimensions: dimensions,
|
||||
statistic: s,
|
||||
extendedStatistic: es,
|
||||
period: period
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -338,6 +357,7 @@ function (angular, _, moment, dateMath, kbn, CloudWatchAnnotationQuery) {
|
||||
var periodMs = options.period * 1000;
|
||||
|
||||
return _.map(options.statistics, function(stat) {
|
||||
var extended = !_.includes(self.standardStatistics, stat);
|
||||
var dps = [];
|
||||
var lastTimestamp = null;
|
||||
_.chain(md.Datapoints)
|
||||
@@ -350,7 +370,11 @@ function (angular, _, moment, dateMath, kbn, CloudWatchAnnotationQuery) {
|
||||
dps.push([null, lastTimestamp + periodMs]);
|
||||
}
|
||||
lastTimestamp = timestamp;
|
||||
dps.push([dp[stat], timestamp]);
|
||||
if (!extended) {
|
||||
dps.push([dp[stat], timestamp]);
|
||||
} else {
|
||||
dps.push([dp.ExtendedStatistics[stat], timestamp]);
|
||||
}
|
||||
})
|
||||
.value();
|
||||
|
||||
@@ -388,12 +412,12 @@ function (angular, _, moment, dateMath, kbn, CloudWatchAnnotationQuery) {
|
||||
return str.indexOf('$' + variableName) !== -1;
|
||||
};
|
||||
|
||||
this.expandTemplateVariable = function(targets, templateSrv) {
|
||||
this.expandTemplateVariable = function(targets, scopedVars, templateSrv) {
|
||||
var self = this;
|
||||
return _.chain(targets)
|
||||
.map(function(target) {
|
||||
var dimensionKey = _.findKey(target.dimensions, function(v) {
|
||||
return templateSrv.variableExists(v);
|
||||
return templateSrv.variableExists(v) && !_.has(scopedVars, templateSrv.getVariableName(v));
|
||||
});
|
||||
|
||||
if (dimensionKey) {
|
||||
|
||||
@@ -61,14 +61,13 @@ function (angular, _) {
|
||||
};
|
||||
|
||||
$scope.getStatSegments = function() {
|
||||
return $q.when([
|
||||
return $q.when(_.flatten([
|
||||
angular.copy($scope.removeStatSegment),
|
||||
uiSegmentSrv.getSegmentForValue('Average'),
|
||||
uiSegmentSrv.getSegmentForValue('Maximum'),
|
||||
uiSegmentSrv.getSegmentForValue('Minimum'),
|
||||
uiSegmentSrv.getSegmentForValue('Sum'),
|
||||
uiSegmentSrv.getSegmentForValue('SampleCount'),
|
||||
]);
|
||||
_.map($scope.datasource.standardStatistics, function(s) {
|
||||
return uiSegmentSrv.getSegmentForValue(s);
|
||||
}),
|
||||
uiSegmentSrv.getSegmentForValue('pNN.NN'),
|
||||
]));
|
||||
};
|
||||
|
||||
$scope.statSegmentChanged = function(segment, index) {
|
||||
|
||||
@@ -139,6 +139,7 @@ describe('CloudWatchDatasource', function() {
|
||||
]
|
||||
}
|
||||
],
|
||||
getVariableName: function (e) { return 'instance_id'; },
|
||||
variableExists: function (e) { return true; },
|
||||
containsVariable: function (str, variableName) { return str.indexOf('$' + variableName) !== -1; }
|
||||
};
|
||||
@@ -156,11 +157,72 @@ describe('CloudWatchDatasource', function() {
|
||||
}
|
||||
];
|
||||
|
||||
var result = ctx.ds.expandTemplateVariable(targets, templateSrv);
|
||||
var result = ctx.ds.expandTemplateVariable(targets, {}, templateSrv);
|
||||
expect(result[0].dimensions.InstanceId).to.be('i-34567890');
|
||||
});
|
||||
});
|
||||
|
||||
describe('When performing CloudWatch query for extended statistics', function() {
|
||||
var requestParams;
|
||||
|
||||
var query = {
|
||||
range: { from: 'now-1h', to: 'now' },
|
||||
targets: [
|
||||
{
|
||||
region: 'us-east-1',
|
||||
namespace: 'AWS/ApplicationELB',
|
||||
metricName: 'TargetResponseTime',
|
||||
dimensions: {
|
||||
LoadBalancer: 'lb',
|
||||
TargetGroup: 'tg'
|
||||
},
|
||||
statistics: ['p90.00'],
|
||||
period: 300
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var response = {
|
||||
Datapoints: [
|
||||
{
|
||||
ExtendedStatistics: {
|
||||
'p90.00': 1
|
||||
},
|
||||
Timestamp: 'Wed Dec 31 1969 16:00:00 GMT-0800 (PST)'
|
||||
},
|
||||
{
|
||||
ExtendedStatistics: {
|
||||
'p90.00': 2
|
||||
},
|
||||
Timestamp: 'Wed Dec 31 1969 16:05:00 GMT-0800 (PST)'
|
||||
},
|
||||
{
|
||||
ExtendedStatistics: {
|
||||
'p90.00': 5
|
||||
},
|
||||
Timestamp: 'Wed Dec 31 1969 16:15:00 GMT-0800 (PST)'
|
||||
}
|
||||
],
|
||||
Label: 'TargetResponseTime'
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
ctx.backendSrv.datasourceRequest = function(params) {
|
||||
requestParams = params;
|
||||
return ctx.$q.when({data: response});
|
||||
};
|
||||
});
|
||||
|
||||
it('should return series list', function(done) {
|
||||
ctx.ds.query(query).then(function(result) {
|
||||
expect(result.data[0].target).to.be('TargetResponseTime_p90.00');
|
||||
expect(result.data[0].datapoints[0][0]).to.be(response.Datapoints[0].ExtendedStatistics['p90.00']);
|
||||
done();
|
||||
});
|
||||
ctx.$rootScope.$apply();
|
||||
});
|
||||
});
|
||||
|
||||
function describeMetricFindQuery(query, func) {
|
||||
describe('metricFindQuery ' + query, () => {
|
||||
let scenario: any = {};
|
||||
|
||||
@@ -185,6 +185,7 @@ module.directive('grafanaGraph', function($rootScope, timeSrv) {
|
||||
|
||||
// Series could have different timeSteps,
|
||||
// let's find the smallest one so that bars are correctly rendered.
|
||||
// In addition, only take series which are rendered as bars for this.
|
||||
function getMinTimeStepOfSeries(data) {
|
||||
var min = Number.MAX_VALUE;
|
||||
|
||||
@@ -192,6 +193,15 @@ module.directive('grafanaGraph', function($rootScope, timeSrv) {
|
||||
if (!data[i].stats.timeStep) {
|
||||
continue;
|
||||
}
|
||||
if (panel.bars) {
|
||||
if (data[i].bars && data[i].bars.show === false) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (typeof data[i].bars === 'undefined' || typeof data[i].bars.show === 'undefined' || !data[i].bars.show) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (data[i].stats.timeStep < min) {
|
||||
min = data[i].stats.timeStep;
|
||||
|
||||
Reference in New Issue
Block a user