|
|
|
|
@ -21,18 +21,26 @@ import ( |
|
|
|
|
"github.com/grafana/grafana/pkg/tsdb" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// Known AWS regions.
|
|
|
|
|
var knownRegions = []string{ |
|
|
|
|
"ap-east-1", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3", "ap-south-1", "ap-southeast-1", |
|
|
|
|
"ap-southeast-2", "ca-central-1", "cn-north-1", "cn-northwest-1", "eu-central-1", "eu-north-1", "eu-west-1", |
|
|
|
|
"eu-west-2", "eu-west-3", "me-south-1", "sa-east-1", "us-east-1", "us-east-2", "us-gov-east-1", "us-gov-west-1", |
|
|
|
|
"us-iso-east-1", "us-isob-east-1", "us-west-1", "us-west-2", |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type suggestData struct { |
|
|
|
|
Text string |
|
|
|
|
Value string |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type CustomMetricsCache struct { |
|
|
|
|
type customMetricsCache struct { |
|
|
|
|
Expire time.Time |
|
|
|
|
Cache []string |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var customMetricsMetricsMap = make(map[string]map[string]map[string]*CustomMetricsCache) |
|
|
|
|
var customMetricsDimensionsMap = make(map[string]map[string]map[string]*CustomMetricsCache) |
|
|
|
|
var customMetricsMetricsMap = make(map[string]map[string]map[string]*customMetricsCache) |
|
|
|
|
var customMetricsDimensionsMap = make(map[string]map[string]map[string]*customMetricsCache) |
|
|
|
|
var metricsMap = map[string][]string{ |
|
|
|
|
"AWS/ACMPrivateCA": {"CRLGenerated", "Failure", "MisconfiguredCRLBucket", "Success", "Time"}, |
|
|
|
|
"AWS/AmazonMQ": {"ConsumerCount", "CpuCreditBalance", "CpuUtilization", "CurrentConnectionsCount", "DequeueCount", "DispatchCount", "EnqueueCount", "EnqueueTime", "ExpiredCount", "HeapUsage", "InflightCount", "JournalFilesForFastRecovery", "JournalFilesForFullRecovery", "MemoryUsage", "NetworkIn", "NetworkOut", "OpenTransactionsCount", "ProducerCount", "QueueSize", "StorePercentUsage", "TotalConsumerCount", "TotalMessageCount", "TotalProducerCount"}, |
|
|
|
|
@ -222,7 +230,7 @@ var dimensionsMap = map[string][]string{ |
|
|
|
|
|
|
|
|
|
var regionCache sync.Map |
|
|
|
|
|
|
|
|
|
func (e *CloudWatchExecutor) executeMetricFindQuery(ctx context.Context, queryContext *tsdb.TsdbQuery) (*tsdb.Response, error) { |
|
|
|
|
func (e *cloudWatchExecutor) executeMetricFindQuery(ctx context.Context, queryContext *tsdb.TsdbQuery) (*tsdb.Response, error) { |
|
|
|
|
firstQuery := queryContext.Queries[0] |
|
|
|
|
|
|
|
|
|
parameters := firstQuery.Model |
|
|
|
|
@ -301,8 +309,9 @@ func parseMultiSelectValue(input string) []string { |
|
|
|
|
|
|
|
|
|
// Whenever this list is updated, the frontend list should also be updated.
|
|
|
|
|
// Please update the region list in public/app/plugins/datasource/cloudwatch/partials/config.html
|
|
|
|
|
func (e *CloudWatchExecutor) handleGetRegions(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
dsInfo := e.getDsInfo("default") |
|
|
|
|
func (e *cloudWatchExecutor) handleGetRegions(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
const region = "default" |
|
|
|
|
dsInfo := e.getDSInfo(region) |
|
|
|
|
profile := dsInfo.Profile |
|
|
|
|
if cache, ok := regionCache.Load(profile); ok { |
|
|
|
|
if cache2, ok2 := cache.([]suggestData); ok2 { |
|
|
|
|
@ -310,15 +319,11 @@ func (e *CloudWatchExecutor) handleGetRegions(ctx context.Context, parameters *s |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
regions := []string{ |
|
|
|
|
"ap-east-1", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3", "ap-south-1", "ap-southeast-1", "ap-southeast-2", "ca-central-1", |
|
|
|
|
"eu-central-1", "eu-north-1", "eu-west-1", "eu-west-2", "eu-west-3", "me-south-1", "sa-east-1", "us-east-1", "us-east-2", "us-west-1", "us-west-2", |
|
|
|
|
"cn-north-1", "cn-northwest-1", "us-gov-east-1", "us-gov-west-1", "us-isob-east-1", "us-iso-east-1", |
|
|
|
|
} |
|
|
|
|
err := e.ensureClientSession("default") |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
regions := knownRegions |
|
|
|
|
r, err := e.ec2Svc.DescribeRegions(&ec2.DescribeRegionsInput{}) |
|
|
|
|
if err != nil { |
|
|
|
|
// ignore error for backward compatibility
|
|
|
|
|
@ -350,7 +355,7 @@ func (e *CloudWatchExecutor) handleGetRegions(ctx context.Context, parameters *s |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *CloudWatchExecutor) handleGetNamespaces(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetNamespaces(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
keys := []string{} |
|
|
|
|
for key := range metricsMap { |
|
|
|
|
keys = append(keys, key) |
|
|
|
|
@ -369,7 +374,7 @@ func (e *CloudWatchExecutor) handleGetNamespaces(ctx context.Context, parameters |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *CloudWatchExecutor) handleGetMetrics(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetMetrics(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
region := parameters.Get("region").MustString() |
|
|
|
|
namespace := parameters.Get("namespace").MustString() |
|
|
|
|
|
|
|
|
|
@ -381,10 +386,10 @@ func (e *CloudWatchExecutor) handleGetMetrics(ctx context.Context, parameters *s |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
var err error |
|
|
|
|
dsInfo := e.getDsInfo(region) |
|
|
|
|
dsInfo := e.getDSInfo(region) |
|
|
|
|
dsInfo.Namespace = namespace |
|
|
|
|
|
|
|
|
|
if namespaceMetrics, err = getMetricsForCustomMetrics(dsInfo, getAllMetrics); err != nil { |
|
|
|
|
if namespaceMetrics, err = e.getMetricsForCustomMetrics(region, e.getAllMetrics); err != nil { |
|
|
|
|
return nil, errors.New("Unable to call AWS API") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -398,7 +403,7 @@ func (e *CloudWatchExecutor) handleGetMetrics(ctx context.Context, parameters *s |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *CloudWatchExecutor) handleGetDimensions(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetDimensions(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
region := parameters.Get("region").MustString() |
|
|
|
|
namespace := parameters.Get("namespace").MustString() |
|
|
|
|
|
|
|
|
|
@ -410,10 +415,10 @@ func (e *CloudWatchExecutor) handleGetDimensions(ctx context.Context, parameters |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
var err error |
|
|
|
|
dsInfo := e.getDsInfo(region) |
|
|
|
|
dsInfo := e.getDSInfo(region) |
|
|
|
|
dsInfo.Namespace = namespace |
|
|
|
|
|
|
|
|
|
if dimensionValues, err = getDimensionsForCustomMetrics(dsInfo, getAllMetrics); err != nil { |
|
|
|
|
if dimensionValues, err = e.getDimensionsForCustomMetrics(region, e.getAllMetrics); err != nil { |
|
|
|
|
return nil, errors.New("Unable to call AWS API") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -427,7 +432,7 @@ func (e *CloudWatchExecutor) handleGetDimensions(ctx context.Context, parameters |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *CloudWatchExecutor) handleGetDimensionValues(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetDimensionValues(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
region := parameters.Get("region").MustString() |
|
|
|
|
namespace := parameters.Get("namespace").MustString() |
|
|
|
|
metricName := parameters.Get("metricName").MustString() |
|
|
|
|
@ -478,9 +483,9 @@ func (e *CloudWatchExecutor) handleGetDimensionValues(ctx context.Context, param |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *CloudWatchExecutor) ensureClientSession(region string) error { |
|
|
|
|
func (e *cloudWatchExecutor) ensureClientSession(region string) error { |
|
|
|
|
if e.ec2Svc == nil { |
|
|
|
|
dsInfo := e.getDsInfo(region) |
|
|
|
|
dsInfo := e.getDSInfo(region) |
|
|
|
|
cfg, err := getAwsConfig(dsInfo) |
|
|
|
|
if err != nil { |
|
|
|
|
return fmt.Errorf("Failed to call ec2:getAwsConfig, %w", err) |
|
|
|
|
@ -494,7 +499,7 @@ func (e *CloudWatchExecutor) ensureClientSession(region string) error { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *CloudWatchExecutor) handleGetEbsVolumeIds(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetEbsVolumeIds(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
region := parameters.Get("region").MustString() |
|
|
|
|
instanceId := parameters.Get("instanceId").MustString() |
|
|
|
|
|
|
|
|
|
@ -521,7 +526,7 @@ func (e *CloudWatchExecutor) handleGetEbsVolumeIds(ctx context.Context, paramete |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *CloudWatchExecutor) handleGetEc2InstanceAttribute(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetEc2InstanceAttribute(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
region := parameters.Get("region").MustString() |
|
|
|
|
attributeName := parameters.Get("attributeName").MustString() |
|
|
|
|
filterJson := parameters.Get("filters").MustMap() |
|
|
|
|
@ -529,15 +534,15 @@ func (e *CloudWatchExecutor) handleGetEc2InstanceAttribute(ctx context.Context, |
|
|
|
|
var filters []*ec2.Filter |
|
|
|
|
for k, v := range filterJson { |
|
|
|
|
if vv, ok := v.([]interface{}); ok { |
|
|
|
|
var vvvvv []*string |
|
|
|
|
var values []*string |
|
|
|
|
for _, vvv := range vv { |
|
|
|
|
if vvvv, ok := vvv.(string); ok { |
|
|
|
|
vvvvv = append(vvvvv, &vvvv) |
|
|
|
|
values = append(values, &vvvv) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
filters = append(filters, &ec2.Filter{ |
|
|
|
|
Name: aws.String(k), |
|
|
|
|
Values: vvvvv, |
|
|
|
|
Values: values, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -605,9 +610,9 @@ func (e *CloudWatchExecutor) handleGetEc2InstanceAttribute(ctx context.Context, |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *CloudWatchExecutor) ensureRGTAClientSession(region string) error { |
|
|
|
|
func (e *cloudWatchExecutor) ensureRGTAClientSession(region string) error { |
|
|
|
|
if e.rgtaSvc == nil { |
|
|
|
|
dsInfo := e.getDsInfo(region) |
|
|
|
|
dsInfo := e.getDSInfo(region) |
|
|
|
|
cfg, err := getAwsConfig(dsInfo) |
|
|
|
|
if err != nil { |
|
|
|
|
return fmt.Errorf("Failed to call ec2:getAwsConfig, %w", err) |
|
|
|
|
@ -621,7 +626,7 @@ func (e *CloudWatchExecutor) ensureRGTAClientSession(region string) error { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *CloudWatchExecutor) handleGetResourceArns(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetResourceArns(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { |
|
|
|
|
region := parameters.Get("region").MustString() |
|
|
|
|
resourceType := parameters.Get("resourceType").MustString() |
|
|
|
|
filterJson := parameters.Get("tags").MustMap() |
|
|
|
|
@ -634,15 +639,15 @@ func (e *CloudWatchExecutor) handleGetResourceArns(ctx context.Context, paramete |
|
|
|
|
var filters []*resourcegroupstaggingapi.TagFilter |
|
|
|
|
for k, v := range filterJson { |
|
|
|
|
if vv, ok := v.([]interface{}); ok { |
|
|
|
|
var vvvvv []*string |
|
|
|
|
var values []*string |
|
|
|
|
for _, vvv := range vv { |
|
|
|
|
if vvvv, ok := vvv.(string); ok { |
|
|
|
|
vvvvv = append(vvvvv, &vvvv) |
|
|
|
|
values = append(values, &vvvv) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
filters = append(filters, &resourcegroupstaggingapi.TagFilter{ |
|
|
|
|
Key: aws.String(k), |
|
|
|
|
Values: vvvvv, |
|
|
|
|
Values: values, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -664,8 +669,8 @@ func (e *CloudWatchExecutor) handleGetResourceArns(ctx context.Context, paramete |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *CloudWatchExecutor) cloudwatchListMetrics(region string, namespace string, metricName string, dimensions []*cloudwatch.DimensionFilter) (*cloudwatch.ListMetricsOutput, error) { |
|
|
|
|
svc, err := e.getClient(region) |
|
|
|
|
func (e *cloudWatchExecutor) cloudwatchListMetrics(region string, namespace string, metricName string, dimensions []*cloudwatch.DimensionFilter) (*cloudwatch.ListMetricsOutput, error) { |
|
|
|
|
svc, err := e.getCWClient(region) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
@ -695,57 +700,50 @@ func (e *CloudWatchExecutor) cloudwatchListMetrics(region string, namespace stri |
|
|
|
|
return &resp, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *CloudWatchExecutor) ec2DescribeInstances(region string, filters []*ec2.Filter, instanceIds []*string) (*ec2.DescribeInstancesOutput, error) { |
|
|
|
|
func (e *cloudWatchExecutor) ec2DescribeInstances(region string, filters []*ec2.Filter, instanceIds []*string) (*ec2.DescribeInstancesOutput, error) { |
|
|
|
|
params := &ec2.DescribeInstancesInput{ |
|
|
|
|
Filters: filters, |
|
|
|
|
InstanceIds: instanceIds, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var resp ec2.DescribeInstancesOutput |
|
|
|
|
err := e.ec2Svc.DescribeInstancesPages(params, |
|
|
|
|
func(page *ec2.DescribeInstancesOutput, lastPage bool) bool { |
|
|
|
|
reservations, _ := awsutil.ValuesAtPath(page, "Reservations") |
|
|
|
|
for _, reservation := range reservations { |
|
|
|
|
resp.Reservations = append(resp.Reservations, reservation.(*ec2.Reservation)) |
|
|
|
|
} |
|
|
|
|
return !lastPage |
|
|
|
|
}) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, fmt.Errorf("Failed to call ec2:DescribeInstances, %w", err) |
|
|
|
|
if err := e.ec2Svc.DescribeInstancesPages(params, func(page *ec2.DescribeInstancesOutput, lastPage bool) bool { |
|
|
|
|
resp.Reservations = append(resp.Reservations, page.Reservations...) |
|
|
|
|
return !lastPage |
|
|
|
|
}); err != nil { |
|
|
|
|
return nil, fmt.Errorf("failed to call ec2:DescribeInstances, %w", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return &resp, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *CloudWatchExecutor) resourceGroupsGetResources(region string, filters []*resourcegroupstaggingapi.TagFilter, resourceTypes []*string) (*resourcegroupstaggingapi.GetResourcesOutput, error) { |
|
|
|
|
func (e *cloudWatchExecutor) resourceGroupsGetResources(region string, filters []*resourcegroupstaggingapi.TagFilter, |
|
|
|
|
resourceTypes []*string) (*resourcegroupstaggingapi.GetResourcesOutput, error) { |
|
|
|
|
params := &resourcegroupstaggingapi.GetResourcesInput{ |
|
|
|
|
ResourceTypeFilters: resourceTypes, |
|
|
|
|
TagFilters: filters, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var resp resourcegroupstaggingapi.GetResourcesOutput |
|
|
|
|
err := e.rgtaSvc.GetResourcesPages(params, |
|
|
|
|
if err := e.rgtaSvc.GetResourcesPages(params, |
|
|
|
|
func(page *resourcegroupstaggingapi.GetResourcesOutput, lastPage bool) bool { |
|
|
|
|
resources, _ := awsutil.ValuesAtPath(page, "ResourceTagMappingList") |
|
|
|
|
for _, resource := range resources { |
|
|
|
|
resp.ResourceTagMappingList = append(resp.ResourceTagMappingList, resource.(*resourcegroupstaggingapi.ResourceTagMapping)) |
|
|
|
|
} |
|
|
|
|
resp.ResourceTagMappingList = append(resp.ResourceTagMappingList, page.ResourceTagMappingList...) |
|
|
|
|
return !lastPage |
|
|
|
|
}) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, fmt.Errorf("Failed to call tags:GetResources, %w", err) |
|
|
|
|
}); err != nil { |
|
|
|
|
return nil, fmt.Errorf("failed to call tags:GetResources, %w", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return &resp, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func getAllMetrics(cwData *DatasourceInfo) (cloudwatch.ListMetricsOutput, error) { |
|
|
|
|
creds, err := getCredentials(cwData) |
|
|
|
|
func (e *cloudWatchExecutor) getAllMetrics(region string) (cloudwatch.ListMetricsOutput, error) { |
|
|
|
|
dsInfo := e.getDSInfo(region) |
|
|
|
|
creds, err := getCredentials(dsInfo) |
|
|
|
|
if err != nil { |
|
|
|
|
return cloudwatch.ListMetricsOutput{}, err |
|
|
|
|
} |
|
|
|
|
cfg := &aws.Config{ |
|
|
|
|
Region: aws.String(cwData.Region), |
|
|
|
|
Region: aws.String(dsInfo.Region), |
|
|
|
|
Credentials: creds, |
|
|
|
|
} |
|
|
|
|
sess, err := session.NewSession(cfg) |
|
|
|
|
@ -755,7 +753,7 @@ func getAllMetrics(cwData *DatasourceInfo) (cloudwatch.ListMetricsOutput, error) |
|
|
|
|
svc := cloudwatch.New(sess, cfg) |
|
|
|
|
|
|
|
|
|
params := &cloudwatch.ListMetricsInput{ |
|
|
|
|
Namespace: aws.String(cwData.Namespace), |
|
|
|
|
Namespace: aws.String(dsInfo.Namespace), |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var resp cloudwatch.ListMetricsOutput |
|
|
|
|
@ -776,25 +774,27 @@ func getAllMetrics(cwData *DatasourceInfo) (cloudwatch.ListMetricsOutput, error) |
|
|
|
|
|
|
|
|
|
var metricsCacheLock sync.Mutex |
|
|
|
|
|
|
|
|
|
func getMetricsForCustomMetrics(dsInfo *DatasourceInfo, getAllMetrics func(*DatasourceInfo) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { |
|
|
|
|
func (e *cloudWatchExecutor) getMetricsForCustomMetrics(region string, getAllMetrics func(string) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { |
|
|
|
|
metricsCacheLock.Lock() |
|
|
|
|
defer metricsCacheLock.Unlock() |
|
|
|
|
|
|
|
|
|
dsInfo := e.getDSInfo(region) |
|
|
|
|
|
|
|
|
|
if _, ok := customMetricsMetricsMap[dsInfo.Profile]; !ok { |
|
|
|
|
customMetricsMetricsMap[dsInfo.Profile] = make(map[string]map[string]*CustomMetricsCache) |
|
|
|
|
customMetricsMetricsMap[dsInfo.Profile] = make(map[string]map[string]*customMetricsCache) |
|
|
|
|
} |
|
|
|
|
if _, ok := customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region]; !ok { |
|
|
|
|
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region] = make(map[string]*CustomMetricsCache) |
|
|
|
|
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region] = make(map[string]*customMetricsCache) |
|
|
|
|
} |
|
|
|
|
if _, ok := customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace]; !ok { |
|
|
|
|
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace] = &CustomMetricsCache{} |
|
|
|
|
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace] = &customMetricsCache{} |
|
|
|
|
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire.After(time.Now()) { |
|
|
|
|
return customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil |
|
|
|
|
} |
|
|
|
|
result, err := getAllMetrics(dsInfo) |
|
|
|
|
result, err := getAllMetrics(region) |
|
|
|
|
if err != nil { |
|
|
|
|
return []string{}, err |
|
|
|
|
} |
|
|
|
|
@ -813,25 +813,27 @@ func getMetricsForCustomMetrics(dsInfo *DatasourceInfo, getAllMetrics func(*Data |
|
|
|
|
|
|
|
|
|
var dimensionsCacheLock sync.Mutex |
|
|
|
|
|
|
|
|
|
func getDimensionsForCustomMetrics(dsInfo *DatasourceInfo, getAllMetrics func(*DatasourceInfo) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { |
|
|
|
|
func (e *cloudWatchExecutor) getDimensionsForCustomMetrics(region string, getAllMetrics func(string) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { |
|
|
|
|
dimensionsCacheLock.Lock() |
|
|
|
|
defer dimensionsCacheLock.Unlock() |
|
|
|
|
|
|
|
|
|
dsInfo := e.getDSInfo(region) |
|
|
|
|
|
|
|
|
|
if _, ok := customMetricsDimensionsMap[dsInfo.Profile]; !ok { |
|
|
|
|
customMetricsDimensionsMap[dsInfo.Profile] = make(map[string]map[string]*CustomMetricsCache) |
|
|
|
|
customMetricsDimensionsMap[dsInfo.Profile] = make(map[string]map[string]*customMetricsCache) |
|
|
|
|
} |
|
|
|
|
if _, ok := customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region]; !ok { |
|
|
|
|
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region] = make(map[string]*CustomMetricsCache) |
|
|
|
|
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region] = make(map[string]*customMetricsCache) |
|
|
|
|
} |
|
|
|
|
if _, ok := customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace]; !ok { |
|
|
|
|
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace] = &CustomMetricsCache{} |
|
|
|
|
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace] = &customMetricsCache{} |
|
|
|
|
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire.After(time.Now()) { |
|
|
|
|
return customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil |
|
|
|
|
} |
|
|
|
|
result, err := getAllMetrics(dsInfo) |
|
|
|
|
result, err := getAllMetrics(region) |
|
|
|
|
if err != nil { |
|
|
|
|
return []string{}, err |
|
|
|
|
} |
|
|
|
|
|