Cloudwatch: Backend cleanup (#59663)
* cleanup cloudwatch.go * streamline interface naming * use utility func * rename test utils file * move util function to where they are used * move dtos to models * split integration tests from the rest * Update pkg/tsdb/cloudwatch/cloudwatch.go Co-authored-by: Isabella Siu <Isabella.siu@grafana.com> * refactor error codes aggregation * move error messages to models Co-authored-by: Isabella Siu <Isabella.siu@grafana.com>
This commit is contained in:
co-authored by
Isabella Siu
parent
ada0c771ef
commit
fde9a5d112
@@ -18,34 +18,18 @@ type RouteHandlerFunc func(pluginCtx backend.PluginContext, reqContextFactory Re
|
||||
type RequestContext struct {
|
||||
MetricsClientProvider MetricsClientProvider
|
||||
LogsAPIProvider CloudWatchLogsAPIProvider
|
||||
OAMClientProvider OAMClientProvider
|
||||
OAMAPIProvider OAMAPIProvider
|
||||
Settings CloudWatchSettings
|
||||
Features featuremgmt.FeatureToggles
|
||||
}
|
||||
|
||||
// Services
|
||||
type ListMetricsProvider interface {
|
||||
GetDimensionKeysByDimensionFilter(resources.DimensionKeysRequest) ([]resources.ResourceResponse[string], error)
|
||||
GetDimensionValuesByDimensionFilter(resources.DimensionValuesRequest) ([]resources.ResourceResponse[string], error)
|
||||
GetMetricsByNamespace(r resources.MetricsRequest) ([]resources.ResourceResponse[resources.Metric], error)
|
||||
}
|
||||
|
||||
type MetricsClientProvider interface {
|
||||
ListMetricsWithPageLimit(params *cloudwatch.ListMetricsInput) ([]resources.MetricResponse, error)
|
||||
}
|
||||
|
||||
type CloudWatchMetricsAPIProvider interface {
|
||||
ListMetricsPages(*cloudwatch.ListMetricsInput, func(*cloudwatch.ListMetricsOutput, bool) bool) error
|
||||
}
|
||||
|
||||
type CloudWatchLogsAPIProvider interface {
|
||||
DescribeLogGroups(*cloudwatchlogs.DescribeLogGroupsInput) (*cloudwatchlogs.DescribeLogGroupsOutput, error)
|
||||
}
|
||||
|
||||
type OAMClientProvider interface {
|
||||
ListSinks(*oam.ListSinksInput) (*oam.ListSinksOutput, error)
|
||||
ListAttachedLinks(*oam.ListAttachedLinksInput) (*oam.ListAttachedLinksOutput, error)
|
||||
}
|
||||
|
||||
type LogGroupsProvider interface {
|
||||
GetLogGroups(request resources.LogGroupsRequest) ([]resources.ResourceResponse[resources.LogGroup], error)
|
||||
}
|
||||
@@ -53,3 +37,22 @@ type LogGroupsProvider interface {
|
||||
type AccountsProvider interface {
|
||||
GetAccountsForCurrentUserOrRole() ([]resources.ResourceResponse[resources.Account], error)
|
||||
}
|
||||
|
||||
// Clients
|
||||
type MetricsClientProvider interface {
|
||||
ListMetricsWithPageLimit(params *cloudwatch.ListMetricsInput) ([]resources.MetricResponse, error)
|
||||
}
|
||||
|
||||
// APIs - instead of using the API defined in the services within the aws-sdk-go directly, specify a subset of the API with methods that are actually used in a service or a client
|
||||
type CloudWatchMetricsAPIProvider interface {
|
||||
ListMetricsPages(*cloudwatch.ListMetricsInput, func(*cloudwatch.ListMetricsOutput, bool) bool) error
|
||||
}
|
||||
|
||||
type CloudWatchLogsAPIProvider interface {
|
||||
DescribeLogGroups(*cloudwatchlogs.DescribeLogGroupsInput) (*cloudwatchlogs.DescribeLogGroupsOutput, error)
|
||||
}
|
||||
|
||||
type OAMAPIProvider interface {
|
||||
ListSinks(*oam.ListSinksInput) (*oam.ListSinksOutput, error)
|
||||
ListAttachedLinks(*oam.ListAttachedLinksInput) (*oam.ListAttachedLinksOutput, error)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log/logtest"
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/utils"
|
||||
)
|
||||
|
||||
func TestCloudWatchQuery(t *testing.T) {
|
||||
@@ -119,7 +120,7 @@ func TestCloudWatchQuery(t *testing.T) {
|
||||
Period: 300,
|
||||
Id: "id1",
|
||||
MatchExact: true,
|
||||
AccountId: pointer("123456789"),
|
||||
AccountId: utils.Pointer("123456789"),
|
||||
Label: "${PROP('Namespace')}",
|
||||
Dimensions: map[string][]string{
|
||||
"InstanceId": {"i-12345678"},
|
||||
@@ -141,7 +142,7 @@ func TestCloudWatchQuery(t *testing.T) {
|
||||
Region: "us-east-1",
|
||||
Statistic: "Average",
|
||||
Expression: "SEARCH(someexpression)",
|
||||
AccountId: pointer("123456789"),
|
||||
AccountId: utils.Pointer("123456789"),
|
||||
Period: 300,
|
||||
Id: "id1",
|
||||
MatchExact: true,
|
||||
@@ -1059,7 +1060,6 @@ func Test_ParseMetricDataQueries_migrate_alias_to_label(t *testing.T) {
|
||||
dynamicLabelsFeatureToggleEnabled: false,
|
||||
expectedLabel: "some label"},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
query := []backend.DataQuery{
|
||||
@@ -1195,5 +1195,3 @@ func Test_ParseMetricDataQueries_account_Id(t *testing.T) {
|
||||
assert.Nil(t, actual[0].AccountId)
|
||||
})
|
||||
}
|
||||
|
||||
func pointer[T any](arg T) *T { return &arg }
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package models
|
||||
|
||||
const (
|
||||
MaxMetricsExceeded = "MaxMetricsExceeded"
|
||||
MaxQueryTimeRangeExceeded = "MaxQueryTimeRangeExceeded"
|
||||
MaxQueryResultsExceeded = "MaxQueryResultsExceeded"
|
||||
MaxMatchingResultsExceeded = "MaxMatchingResultsExceeded"
|
||||
)
|
||||
|
||||
var ErrorMessages = map[string]string{
|
||||
MaxMetricsExceeded: "Maximum number of allowed metrics exceeded. Your search may have been limited",
|
||||
MaxQueryTimeRangeExceeded: "Max time window exceeded for query",
|
||||
MaxQueryResultsExceeded: "Only the first 500 time series can be returned by a query.",
|
||||
MaxMatchingResultsExceeded: "The query matched more than 10.000 metrics, results might not be accurate.",
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package models
|
||||
|
||||
import "github.com/aws/aws-sdk-go/service/cloudwatch"
|
||||
|
||||
// queryRowResponse represents the GetMetricData response for a query row in the query editor.
|
||||
type QueryRowResponse struct {
|
||||
partialDataSet map[string]*cloudwatch.MetricDataResult
|
||||
ErrorCodes map[string]bool
|
||||
HasArithmeticError bool
|
||||
ArithmeticErrorMessage string
|
||||
Metrics []*cloudwatch.MetricDataResult
|
||||
StatusCode string
|
||||
}
|
||||
|
||||
func NewQueryRowResponse(errors map[string]bool) QueryRowResponse {
|
||||
return QueryRowResponse{
|
||||
partialDataSet: make(map[string]*cloudwatch.MetricDataResult),
|
||||
ErrorCodes: errors,
|
||||
HasArithmeticError: false,
|
||||
ArithmeticErrorMessage: "",
|
||||
Metrics: []*cloudwatch.MetricDataResult{},
|
||||
}
|
||||
}
|
||||
|
||||
func (q *QueryRowResponse) AddMetricDataResult(mdr *cloudwatch.MetricDataResult) {
|
||||
if partialData, ok := q.partialDataSet[*mdr.Label]; ok {
|
||||
partialData.Timestamps = append(partialData.Timestamps, mdr.Timestamps...)
|
||||
partialData.Values = append(partialData.Values, mdr.Values...)
|
||||
q.StatusCode = *mdr.StatusCode
|
||||
if *mdr.StatusCode != "PartialData" {
|
||||
delete(q.partialDataSet, *mdr.Label)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
q.Metrics = append(q.Metrics, mdr)
|
||||
q.StatusCode = *mdr.StatusCode
|
||||
if *mdr.StatusCode == "PartialData" {
|
||||
q.partialDataSet[*mdr.Label] = mdr
|
||||
}
|
||||
}
|
||||
|
||||
func (q *QueryRowResponse) AddArithmeticError(message *string) {
|
||||
q.HasArithmeticError = true
|
||||
q.ArithmeticErrorMessage = *message
|
||||
}
|
||||
Reference in New Issue
Block a user