package console import ( "context" "errors" "log" "strings" "time" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/cloudwatch" "github.com/aws/aws-sdk-go-v2/service/cloudwatch/types" "github.com/carlosframework/platform/internal/rootaws" ) // The AWS adapter of the eligible-capacity metric (region HA spec 2 §4, // §25): CloudWatch, Carlos/Region EligibleBoxes, keyed by the placement // code, in each region's own CloudWatch, where the region-host module's // alarm reads it. Armed by CARLOS_REGION_METRICS=cloudwatch on the // console. The platform box's role needs cloudwatch:PutMetricData on the // Carlos/Region namespace: plan 2c grants it. const ( capacityNamespace = "Carlos/Region" capacityMetric = "EligibleBoxes" ) // capacityData is the exact PutMetricData input for one region's count. func capacityData(c regionCapacity, now time.Time) *cloudwatch.PutMetricDataInput { return &cloudwatch.PutMetricDataInput{Namespace: aws.String(capacityNamespace), MetricData: []types.MetricDatum{{ MetricName: aws.String(capacityMetric), Dimensions: []types.Dimension{{Name: aws.String("Region"), Value: aws.String(c.Placement)}}, Timestamp: aws.Time(now), Unit: types.StandardUnitCount, Value: aws.Float64(float64(c.Eligible)), }}} } // cloudWatchCapacity publishes each count to its region's CloudWatch. type cloudWatchCapacity struct { put func(ctx context.Context, awsRegion string, in *cloudwatch.PutMetricDataInput) error now func() time.Time } func (c cloudWatchCapacity) PublishCapacity(ctx context.Context, counts []regionCapacity) error { var errs []error for _, n := range counts { errs = append(errs, c.put(ctx, n.AWSRegion, capacityData(n, c.now()))) } return errors.Join(errs...) } // capacityPublisherFromEnv is the console's publisher: CloudWatch when // CARLOS_REGION_METRICS is "cloudwatch", and nil otherwise, or when the // AWS configuration cannot be loaded (logged). func capacityPublisherFromEnv(ctx context.Context, getenv func(string) string) capacityPublisher { if strings.TrimSpace(getenv("CARLOS_REGION_METRICS")) != "cloudwatch" { return nil } cfg, err := rootaws.LoadDefaultConfig(ctx) if err != nil { log.Printf("console: eligible-capacity metric disabled: load aws config: %v", err) return nil } return cloudWatchCapacity{now: time.Now, put: func(ctx context.Context, awsRegion string, in *cloudwatch.PutMetricDataInput) error { _, err := cloudwatch.NewFromConfig(cfg, func(o *cloudwatch.Options) { o.Region = awsRegion }).PutMetricData(ctx, in) return err }} }