Browse Source

support cloudwatch high resolution query

Mitsuhiro Tanda 7 năm trước cách đây
mục cha
commit
18c54a9341

+ 33 - 8
pkg/tsdb/cloudwatch/cloudwatch.go

@@ -152,8 +152,6 @@ func (e *CloudWatchExecutor) executeQuery(ctx context.Context, parameters *simpl
 		MetricName: aws.String(query.MetricName),
 		Dimensions: query.Dimensions,
 		Period:     aws.Int64(int64(query.Period)),
-		StartTime:  aws.Time(startTime),
-		EndTime:    aws.Time(endTime),
 	}
 	if len(query.Statistics) > 0 {
 		params.Statistics = query.Statistics
@@ -162,15 +160,36 @@ func (e *CloudWatchExecutor) executeQuery(ctx context.Context, parameters *simpl
 		params.ExtendedStatistics = query.ExtendedStatistics
 	}
 
-	if setting.Env == setting.DEV {
-		plog.Debug("CloudWatch query", "raw query", params)
+	// 1 minutes resolutin metrics is stored for 15 days, 15 * 24 * 60 = 21600
+	if query.HighResolution && (((endTime.Unix() - startTime.Unix()) / int64(query.Period)) > 21600) {
+		return nil, errors.New("too long query period")
 	}
+	var resp *cloudwatch.GetMetricStatisticsOutput
+	for startTime.Before(endTime) {
+		params.StartTime = aws.Time(startTime)
+		if query.HighResolution {
+			startTime = startTime.Add(time.Duration(1440*query.Period) * time.Second)
+		} else {
+			startTime = endTime
+		}
+		params.EndTime = aws.Time(startTime)
 
-	resp, err := client.GetMetricStatisticsWithContext(ctx, params, request.WithResponseReadTimeout(10*time.Second))
-	if err != nil {
-		return nil, err
+		if setting.Env == setting.DEV {
+			plog.Debug("CloudWatch query", "raw query", params)
+		}
+
+		partResp, err := client.GetMetricStatisticsWithContext(ctx, params, request.WithResponseReadTimeout(10*time.Second))
+		if err != nil {
+			return nil, err
+		}
+		if resp != nil {
+			resp.Datapoints = append(resp.Datapoints, partResp.Datapoints...)
+		} else {
+			resp = partResp
+
+		}
+		metrics.M_Aws_CloudWatch_GetMetricStatistics.Inc()
 	}
-	metrics.M_Aws_CloudWatch_GetMetricStatistics.Inc()
 
 	queryRes, err := parseResponse(resp, query)
 	if err != nil {
@@ -274,6 +293,11 @@ func parseQuery(model *simplejson.Json) (*CloudWatchQuery, error) {
 		alias = "{{metric}}_{{stat}}"
 	}
 
+	highResolution, err := model.Get("highResolution").Bool()
+	if err != nil {
+		return nil, err
+	}
+
 	return &CloudWatchQuery{
 		Region:             region,
 		Namespace:          namespace,
@@ -283,6 +307,7 @@ func parseQuery(model *simplejson.Json) (*CloudWatchQuery, error) {
 		ExtendedStatistics: aws.StringSlice(extendedStatistics),
 		Period:             period,
 		Alias:              alias,
+		HighResolution:     highResolution,
 	}, nil
 }
 

+ 1 - 0
pkg/tsdb/cloudwatch/cloudwatch_test.go

@@ -31,6 +31,7 @@ func TestCloudWatch(t *testing.T) {
 						"p90.00"
 					],
 					"period": "60",
+					"highResolution": false,
 					"alias": "{{metric}}_{{stat}}"
 				}
 			`

+ 1 - 0
pkg/tsdb/cloudwatch/types.go

@@ -13,4 +13,5 @@ type CloudWatchQuery struct {
 	ExtendedStatistics []*string
 	Period             int
 	Alias              string
+	HighResolution     bool
 }

+ 1 - 1
public/app/plugins/datasource/cloudwatch/datasource.ts

@@ -106,7 +106,7 @@ export default class CloudWatchDatasource {
     if (period < 1) {
       period = 1;
     }
-    if (range / period >= 1440) {
+    if (!target.highResolution && range / period >= 1440) {
       period = Math.ceil(range / 1440 / periodUnit) * periodUnit;
     }
 

+ 5 - 0
public/app/plugins/datasource/cloudwatch/partials/query.parameter.html

@@ -54,6 +54,11 @@
 			</ul>
 		</info-popover>
 	</div>
+	<div class="gf-form">
+		<gf-form-switch class="gf-form" label="HighRes" label-class="width-5" checked="target.highResolution" on-change="onChange()">
+		</gf-form-switch>
+	</div>
+
 	<div class="gf-form gf-form--grow">
 		<div class="gf-form-label gf-form-label--grow"></div>
 	</div>

+ 1 - 0
public/app/plugins/datasource/cloudwatch/query_parameter_ctrl.ts

@@ -27,6 +27,7 @@ export class CloudWatchQueryParameterCtrl {
       target.dimensions = target.dimensions || {};
       target.period = target.period || '';
       target.region = target.region || 'default';
+      target.highResolution = target.highResolution || false;
 
       $scope.regionSegment = uiSegmentSrv.getSegmentForValue($scope.target.region, 'select region');
       $scope.namespaceSegment = uiSegmentSrv.getSegmentForValue($scope.target.namespace, 'select namespace');