ankane/pghero · warning · PgHero::NotEnabled

System stats not enabled

Error message

System stats not enabled

What it means

PgHero raises this from PgHero::Methods::System#rds_stats when system_stats_enabled? is false, i.e. system_stats_provider is nil because neither aws_db_instance_identifier nor gcp_database_id is configured for the database in config/pghero.yml. rds_stats fetches CloudWatch metrics (AWS/RDS namespace) via Aws::CloudWatch::Client, so without an RDS instance identifier PgHero refuses the call rather than querying CloudWatch blindly.

Source

Thrown at lib/pghero/methods/system.rb:74

          resp = client.get_metric_statistics(
            namespace: "AWS/RDS",
            metric_name: metric_name,
            dimensions: [{name: "DBInstanceIdentifier", value: aws_db_instance_identifier}],
            start_time: start_time.iso8601,
            end_time: end_time.iso8601,
            period: period,
            statistics: ["Average"]
          )
          data = {}
          resp[:datapoints].sort_by { |d| d[:timestamp] }.each do |d|
            data[d[:timestamp]] = d[:average]
          end

          add_missing_data(data, start_time, end_time, period) if series

          data
        else
          raise NotEnabled, "System stats not enabled"
        end
      end

      private

      def gcp_stats(metric_name, duration: nil, period: nil, offset: nil, series: false)
        # TODO DRY with RDS stats
        duration = (duration || 1.hour).to_i
        period = (period || 1.minute).to_i
        offset = (offset || 0).to_i
        end_time = Time.at(((Time.now - offset).to_f / period).ceil * period)
        start_time = end_time - duration

        # validate input since we need to interpolate below
        raise Error, "Invalid metric name" unless /\A[a-z\/_]+\z/i.match?(metric_name)
        raise Error, "Invalid database id" unless /\A[a-z0-9\-:]+\z/i.match?(gcp_database_id)

        # we handle three situations:

View on GitHub (pinned to 7edb57986f)

Solutions

  1. In config/pghero.yml, set the database's aws: block: db_instance_identifier (PgHero's key is aws_db_instance_identifier via `aws: db_instance_identifier: ...`), aws_region, and optionally aws_access_key_id/aws_secret_access_key (otherwise IAM instance profile is used).
  2. Add the `aws-cloudwatch` gem to the Gemfile so Aws::CloudWatch::Client can be loaded.
  3. If not on RDS but on Cloud SQL, configure gcp_database_id instead so the provider becomes :gcp and calls route to gcp_stats rather than rds_stats.
  4. Guard with `PgHero.system_stats_enabled?` (and system_stats_provider == :aws) or rescue PgHero::NotEnabled.

Example fix

# before - raises PgHero::NotEnabled: System stats not enabled
PgHero.cpu_usage(duration: 1.hour)

# after
# Gemfile: gem "aws-cloudwatch"
# config/pghero.yml:
#   databases:
#     main:
#       aws:
#         db_instance_identifier: my-prod-instance
#         region: us-east-1
usage = PgHero.cpu_usage(duration: 1.hour) if PgHero.system_stats_provider == :aws
Defensive patterns

Strategy: validation

Validate before calling

return unless PgHero.system_stats_enabled? && PgHero.system_stats_provider == :aws
cpu = PgHero.rds_stats("CPUUtilization", duration: 1.hour)

Type guard

def rds_stats_available?
  PgHero.system_stats_provider == :aws
end

Try / catch

begin
  PgHero.rds_stats(metric, duration: 1.hour)
rescue PgHero::NotEnabled
  Rails.logger.info("Configure aws db_instance_identifier in pghero.yml for RDS stats")
  {}
end

Prevention

When it happens

Trigger: Calling PgHero.rds_stats("CPUUtilization", ...) directly, or reaching it through cpu_usage/connection_stats/replication_lag_stats/read_iops_stats/write_iops_stats/free_space_stats when the AWS identifier is missing; typical when pghero.yml has no aws: section or the database entry uses DATABASE_URL without aws_db_instance_identifier.

Common situations: Self-hosted or non-RDS Postgres where system stats are simply unsupported; pghero.yml deployed with the aws keys commented out; per-database config listing a second database without its own aws settings; missing aws-cloudwatch gem surfacing later as a different failure after the config is fixed.

Related errors


AI-assisted analysis of ankane/pghero@7edb57986f (2026-08-21). Data as JSON: /api/errors/fa3aaabd357b4553. Report an issue: GitHub.