Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(metrics): Export RDS Certificate Authority attributes #38

Merged
merged 2 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ It collect key metrics about:
| rds_allocated_storage_bytes | `aws_account_id`, `aws_region`, `dbidentifier` | Allocated storage |
| rds_api_call_total | `api`, `aws_account_id`, `aws_region` | Number of call to AWS API |
| rds_backup_retention_period_seconds | `aws_account_id`, `aws_region`, `dbidentifier` | Automatic DB snapshots retention period |
| rds_ca_certificate_valid_until | `aws_account_id`, `aws_region`, `dbidentifier` | Timestamp of the expiration of the Instance certificate |
chtitux marked this conversation as resolved.
Show resolved Hide resolved
| rds_cpu_usage_percent_average | `aws_account_id`, `aws_region`, `dbidentifier` | Instance CPU used |
| rds_database_connections_average | `aws_account_id`, `aws_region`, `dbidentifier` | The number of client network connections to the database instance |
| rds_dbload_average | `aws_account_id`, `aws_region`, `dbidentifier` | Number of active sessions for the DB engine |
Expand Down
37 changes: 34 additions & 3 deletions internal/app/exporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ type rdsCollector struct {
usageManualSnapshots *prometheus.Desc
exporterBuildInformation *prometheus.Desc
transactionLogsDiskUsage *prometheus.Desc
certificateValidTill *prometheus.Desc
}

func NewCollector(logger slog.Logger, collectorConfiguration Configuration, awsAccountID string, awsRegion string, rdsClient rdsClient, ec2Client EC2Client, cloudWatchClient cloudWatchClient, servicequotasClient servicequotasClient) *rdsCollector {
Expand Down Expand Up @@ -126,7 +127,7 @@ func NewCollector(logger slog.Logger, collectorConfiguration Configuration, awsA
),
information: prometheus.NewDesc("rds_instance_info",
"RDS instance information",
[]string{"aws_account_id", "aws_region", "dbidentifier", "dbi_resource_id", "instance_class", "engine", "engine_version", "storage_type", "multi_az", "deletion_protection", "role", "source_dbidentifier", "pending_modified_values", "pending_maintenance", "performance_insights_enabled"}, nil,
[]string{"aws_account_id", "aws_region", "dbidentifier", "dbi_resource_id", "instance_class", "engine", "engine_version", "storage_type", "multi_az", "deletion_protection", "role", "source_dbidentifier", "pending_modified_values", "pending_maintenance", "performance_insights_enabled", "ca_certificate_identifier"}, nil,
),
maxAllocatedStorage: prometheus.NewDesc("rds_max_allocated_storage_bytes",
"Upper limit in gibibytes to which Amazon RDS can automatically scale the storage of the DB instance",
Expand Down Expand Up @@ -240,6 +241,10 @@ func NewCollector(logger slog.Logger, collectorConfiguration Configuration, awsA
"Disk space used by transaction logs (only on PostgreSQL)",
[]string{"aws_account_id", "aws_region", "dbidentifier"}, nil,
),
certificateValidTill: prometheus.NewDesc("rds_certificate_expiry_timestamp_seconds",
"Timestamp of the expiration of the Instance certificate",
[]string{"aws_account_id", "aws_region", "dbidentifier"}, nil,
),
quotaDBInstances: prometheus.NewDesc("rds_quota_max_dbinstances_average",
"Maximum number of RDS instances allowed in the AWS account",
[]string{"aws_account_id", "aws_region"}, nil,
Expand Down Expand Up @@ -415,13 +420,39 @@ func (c *rdsCollector) Collect(ch chan<- prometheus.Metric) {
// RDS metrics
ch <- prometheus.MustNewConstMetric(c.apiCall, prometheus.CounterValue, c.counters.rdsAPIcalls, c.awsAccountID, c.awsRegion, "rds")
for dbidentifier, instance := range c.metrics.rds.Instances {
ch <- prometheus.MustNewConstMetric(c.allocatedStorage, prometheus.GaugeValue, float64(instance.AllocatedStorage), c.awsAccountID, c.awsRegion, dbidentifier)
ch <- prometheus.MustNewConstMetric(c.information, prometheus.GaugeValue, 1, c.awsAccountID, c.awsRegion, dbidentifier, instance.DbiResourceID, instance.DBInstanceClass, instance.Engine, instance.EngineVersion, instance.StorageType, strconv.FormatBool(instance.MultiAZ), strconv.FormatBool(instance.DeletionProtection), instance.Role, instance.SourceDBInstanceIdentifier, strconv.FormatBool(instance.PendingModifiedValues), instance.PendingMaintenanceAction, strconv.FormatBool(instance.PerformanceInsightsEnabled))
ch <- prometheus.MustNewConstMetric(
c.allocatedStorage,
prometheus.GaugeValue,
float64(instance.AllocatedStorage),
c.awsAccountID, c.awsRegion, dbidentifier,
)
ch <- prometheus.MustNewConstMetric(
c.information,
prometheus.GaugeValue,
1,
c.awsAccountID,
c.awsRegion,
dbidentifier,
instance.DbiResourceID,
instance.DBInstanceClass,
instance.Engine,
instance.EngineVersion,
instance.StorageType,
strconv.FormatBool(instance.MultiAZ),
strconv.FormatBool(instance.DeletionProtection),
instance.Role,
instance.SourceDBInstanceIdentifier,
strconv.FormatBool(instance.PendingModifiedValues),
instance.PendingMaintenanceAction,
strconv.FormatBool(instance.PerformanceInsightsEnabled),
instance.CACertificateIdentifier,
)
ch <- prometheus.MustNewConstMetric(c.maxAllocatedStorage, prometheus.GaugeValue, float64(instance.MaxAllocatedStorage), c.awsAccountID, c.awsRegion, dbidentifier)
ch <- prometheus.MustNewConstMetric(c.maxIops, prometheus.GaugeValue, float64(instance.MaxIops), c.awsAccountID, c.awsRegion, dbidentifier)
ch <- prometheus.MustNewConstMetric(c.status, prometheus.GaugeValue, float64(instance.Status), c.awsAccountID, c.awsRegion, dbidentifier)
ch <- prometheus.MustNewConstMetric(c.storageThroughput, prometheus.GaugeValue, float64(instance.StorageThroughput), c.awsAccountID, c.awsRegion, dbidentifier)
ch <- prometheus.MustNewConstMetric(c.backupRetentionPeriod, prometheus.GaugeValue, float64(instance.BackupRetentionPeriod), c.awsAccountID, c.awsRegion, dbidentifier)
ch <- prometheus.MustNewConstMetric(c.certificateValidTill, prometheus.GaugeValue, float64(instance.CertificateValidTill.Unix()), c.awsAccountID, c.awsRegion, dbidentifier)

if instance.LogFilesSize != nil {
ch <- prometheus.MustNewConstMetric(c.logFilesSize, prometheus.GaugeValue, float64(*instance.LogFilesSize), c.awsAccountID, c.awsRegion, dbidentifier)
Expand Down
5 changes: 5 additions & 0 deletions internal/app/rds/rds.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"reflect"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
aws_rds "github.com/aws/aws-sdk-go-v2/service/rds"
Expand Down Expand Up @@ -48,6 +49,8 @@ type RdsInstanceMetrics struct {
IAMDatabaseAuthenticationEnabled bool
Role string
SourceDBInstanceIdentifier string
CACertificateIdentifier string
CertificateValidTill time.Time
}

const (
Expand Down Expand Up @@ -272,6 +275,8 @@ func (r *RDSFetcher) computeInstanceMetrics(dbInstance aws_rds_types.DBInstance,
Status: GetDBInstanceStatusCode(*dbInstance.DBInstanceStatus),
StorageThroughput: converter.MegaBytesToBytes(storageThroughput),
StorageType: *dbInstance.StorageType,
CACertificateIdentifier: *dbInstance.CACertificateIdentifier,
CertificateValidTill: *dbInstance.CertificateDetails.ValidTill,
}

return metrics, nil
Expand Down
15 changes: 15 additions & 0 deletions internal/app/rds/rds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"reflect"
"testing"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
aws_rds "github.com/aws/aws-sdk-go-v2/service/rds"
Expand Down Expand Up @@ -55,6 +56,16 @@ func randomString(length int) string {
return fmt.Sprintf("%x", buf)
}

func newRdsCertificateDetails() *aws_rds_types.CertificateDetails {
return &aws_rds_types.CertificateDetails{
CAIdentifier: aws.String("rds-ca-2019"),
ValidTill: aws.Time(time.Date(
2024, time.August, 22,
17, 8, 50, 0, time.UTC,
)),
}
}

func newRdsInstance() *aws_rds_types.DBInstance {
DBInstanceIdentifier := randomString(10)

Expand All @@ -75,6 +86,8 @@ func newRdsInstance() *aws_rds_types.DBInstance {
PerformanceInsightsEnabled: aws.Bool(true),
PubliclyAccessible: true,
StorageType: aws.String("gp3"),
CACertificateIdentifier: aws.String("rds-ca-2019"),
CertificateDetails: newRdsCertificateDetails(),
}
}

Expand Down Expand Up @@ -108,6 +121,8 @@ func TestGetMetrics(t *testing.T) {
assert.Equal(t, rdsInstance.PubliclyAccessible, m.PubliclyAccessible, "PubliclyAccessible mismatch")
assert.Equal(t, *rdsInstance.DbiResourceId, m.DbiResourceID, "DbiResourceId mismatch")
assert.Equal(t, *rdsInstance.DBInstanceClass, m.DBInstanceClass, "DBInstanceIdentifier mismatch")
assert.Equal(t, *rdsInstance.CACertificateIdentifier, m.CACertificateIdentifier, "CACertificateIdentifier mismatch")
assert.Equal(t, *rdsInstance.CertificateDetails.ValidTill, m.CertificateValidTill, "CertificateValidTill mismatch")
}

func TestGP2StorageType(t *testing.T) {
Expand Down
Loading