CloudWatch: Add macro for resolving period in SEARCH expressions (#60435)

* interpolate macro in the backend

* refactor logger in cloudwatch query

* revert added metrics

* add docs

* apply pr feedback

* fix broken test

* fix spelling
This commit is contained in:
Erik Sundell
2023-01-02 09:08:31 +01:00
committed by GitHub
parent 09c759b36c
commit 6e89421544
8 changed files with 159 additions and 56 deletions
+29 -13
View File
@@ -44,6 +44,7 @@ const (
const defaultRegion = "default"
type CloudWatchQuery struct {
logger log.Logger
RefId string
Region string
Id string
@@ -65,7 +66,7 @@ type CloudWatchQuery struct {
AccountId *string
}
func (q *CloudWatchQuery) GetGMDAPIMode(logger log.Logger) GMDApiMode {
func (q *CloudWatchQuery) GetGetMetricDataAPIMode() GMDApiMode {
if q.MetricQueryType == MetricQueryTypeSearch && q.MetricEditorMode == MetricEditorModeBuilder {
if q.IsInferredSearchExpression() {
return GMDApiModeInferredSearchExpression
@@ -77,7 +78,7 @@ func (q *CloudWatchQuery) GetGMDAPIMode(logger log.Logger) GMDApiMode {
return GMDApiModeSQLExpression
}
logger.Warn("could not resolve CloudWatch metric query type. Falling back to metric stat.", "query", q)
q.logger.Warn("could not resolve CloudWatch metric query type. Falling back to metric stat.", "query", q)
return GMDApiModeMetricStat
}
@@ -229,7 +230,7 @@ type metricsDataQuery struct {
// ParseMetricDataQueries decodes the metric data queries json, validates, sets default values and returns an array of CloudWatchQueries.
// The CloudWatchQuery has a 1 to 1 mapping to a query editor row
func ParseMetricDataQueries(dataQueries []backend.DataQuery, startTime time.Time, endTime time.Time, defaultRegion string, dynamicLabelsEnabled,
func ParseMetricDataQueries(dataQueries []backend.DataQuery, startTime time.Time, endTime time.Time, defaultRegion string, logger log.Logger, dynamicLabelsEnabled,
crossAccountQueryingEnabled bool) ([]*CloudWatchQuery, error) {
var metricDataQueries = make(map[string]metricsDataQuery)
for _, query := range dataQueries {
@@ -250,6 +251,7 @@ func ParseMetricDataQueries(dataQueries []backend.DataQuery, startTime time.Time
var result []*CloudWatchQuery
for refId, mdq := range metricDataQueries {
cwQuery := &CloudWatchQuery{
logger: logger,
Alias: mdq.Alias,
RefId: refId,
Id: mdq.Id,
@@ -266,6 +268,8 @@ func ParseMetricDataQueries(dataQueries []backend.DataQuery, startTime time.Time
return nil, &QueryError{Err: err, RefID: refId}
}
cwQuery.applyMacros(startTime, endTime)
cwQuery.migrateLegacyQuery(mdq, dynamicLabelsEnabled)
result = append(result, cwQuery)
@@ -274,6 +278,12 @@ func ParseMetricDataQueries(dataQueries []backend.DataQuery, startTime time.Time
return result, nil
}
func (q *CloudWatchQuery) applyMacros(startTime, endTime time.Time) {
if q.GetGetMetricDataAPIMode() == GMDApiModeMathExpression {
q.Expression = strings.ReplaceAll(q.Expression, "$__period_auto", strconv.Itoa(calculatePeriodBasedOnTimeRange(startTime, endTime)))
}
}
func (q *CloudWatchQuery) migrateLegacyQuery(query metricsDataQuery, dynamicLabelsEnabled bool) {
q.Statistic = getStatistic(query)
q.Label = getLabel(query, dynamicLabelsEnabled)
@@ -396,21 +406,27 @@ func getLabel(query metricsDataQuery, dynamicLabelsEnabled bool) string {
return result
}
func calculatePeriodBasedOnTimeRange(startTime, endTime time.Time) int {
deltaInSeconds := endTime.Sub(startTime).Seconds()
periods := getRetainedPeriods(time.Since(startTime))
datapoints := int(math.Ceil(deltaInSeconds / 2000))
period := periods[len(periods)-1]
for _, value := range periods {
if datapoints <= value {
period = value
break
}
}
return period
}
func getPeriod(query metricsDataQuery, startTime, endTime time.Time) (int, error) {
periodString := query.Period
var period int
var err error
if strings.ToLower(periodString) == "auto" || periodString == "" {
deltaInSeconds := endTime.Sub(startTime).Seconds()
periods := getRetainedPeriods(time.Since(startTime))
datapoints := int(math.Ceil(deltaInSeconds / 2000))
period = periods[len(periods)-1]
for _, value := range periods {
if datapoints <= value {
period = value
break
}
}
period = calculatePeriodBasedOnTimeRange(startTime, endTime)
} else {
period, err = strconv.Atoi(periodString)
if err != nil {