CloudWatch: Update Period auto to take retention into account (#37424)

* now to get it to build

* modified names, added the 455 day case, and added a comment

* removed wireguard override i used for my local

* updated the docs
This commit is contained in:
Kai Hayashi 2021-09-01 07:44:47 +00:00 committed by GitHub
parent f2c4346cc4
commit 6e0f18b13a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 2 deletions

View File

@ -180,7 +180,7 @@ Please note that in the case you use the expression field to reference another q
A period is the length of time associated with a specific Amazon CloudWatch statistic. Periods are defined in numbers of seconds, and valid values for period are 1, 5, 10, 30, or any multiple of 60. A period is the length of time associated with a specific Amazon CloudWatch statistic. Periods are defined in numbers of seconds, and valid values for period are 1, 5, 10, 30, or any multiple of 60.
If the period field is left blank or set to `auto`, then it calculates automatically based on the time range. The formula used is `time range in seconds / 2000`, and then it snaps to the next higher value in an array of predefined periods `[60, 300, 900, 3600, 21600, 86400]`. By clicking `Show Query Preview` in the query editor, you can see what period Grafana used. If the period field is left blank or set to `auto`, then it calculates automatically based on the time range and [cloudwatch's retention policy](https://aws.amazon.com/about-aws/whats-new/2016/11/cloudwatch-extends-metrics-retention-and-new-user-interface/). The formula used is `time range in seconds / 2000`, and then it snaps to the next higher value in an array of predefined periods `[60, 300, 900, 3600, 21600, 86400]` after removing periods based on retention. By clicking `Show Query Preview` in the query editor, you can see what period Grafana used.
### Deep linking from Grafana panels to the CloudWatch console ### Deep linking from Grafana panels to the CloudWatch console

View File

@ -69,7 +69,7 @@ func parseRequestQuery(model *simplejson.Json, refId string, startTime time.Time
var period int var period int
if strings.ToLower(p) == "auto" || p == "" { if strings.ToLower(p) == "auto" || p == "" {
deltaInSeconds := endTime.Sub(startTime).Seconds() deltaInSeconds := endTime.Sub(startTime).Seconds()
periods := []int{60, 300, 900, 3600, 21600, 86400} periods := getRetainedPeriods(time.Since(startTime))
datapoints := int(math.Ceil(deltaInSeconds / 2000)) datapoints := int(math.Ceil(deltaInSeconds / 2000))
period = periods[len(periods)-1] period = periods[len(periods)-1]
for _, value := range periods { for _, value := range periods {
@ -123,6 +123,19 @@ func parseRequestQuery(model *simplejson.Json, refId string, startTime time.Time
}, nil }, nil
} }
func getRetainedPeriods(timeSince time.Duration) []int {
// See https://aws.amazon.com/about-aws/whats-new/2016/11/cloudwatch-extends-metrics-retention-and-new-user-interface/
if timeSince > time.Duration(455)*24*time.Hour {
return []int{21600, 86400}
} else if timeSince > time.Duration(63)*24*time.Hour {
return []int{3600, 21600, 86400}
} else if timeSince > time.Duration(15)*24*time.Hour {
return []int{300, 900, 3600, 21600, 86400}
} else {
return []int{60, 300, 900, 3600, 21600, 86400}
}
}
func parseStatistics(model *simplejson.Json) []string { func parseStatistics(model *simplejson.Json) []string {
var statistics []string var statistics []string
for _, s := range model.Get("statistics").MustArray() { for _, s := range model.Get("statistics").MustArray() {

View File

@ -208,5 +208,32 @@ func TestRequestParser(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 86400, res.Period) assert.Equal(t, 86400, res.Period)
}) })
t.Run("Time range is 2 days, but 16 days ago", func(t *testing.T) {
query.Set("period", "auto")
to := time.Now().AddDate(0, 0, -14)
from := to.AddDate(0, 0, -2)
res, err := parseRequestQuery(query, "ref1", from, to)
require.NoError(t, err)
assert.Equal(t, 300, res.Period)
})
t.Run("Time range is 2 days, but 90 days ago", func(t *testing.T) {
query.Set("period", "auto")
to := time.Now().AddDate(0, 0, -88)
from := to.AddDate(0, 0, -2)
res, err := parseRequestQuery(query, "ref1", from, to)
require.NoError(t, err)
assert.Equal(t, 3600, res.Period)
})
t.Run("Time range is 2 days, but 456 days ago", func(t *testing.T) {
query.Set("period", "auto")
to := time.Now().AddDate(0, 0, -454)
from := to.AddDate(0, 0, -2)
res, err := parseRequestQuery(query, "ref1", from, to)
require.NoError(t, err)
assert.Equal(t, 21600, res.Period)
})
}) })
} }