ankane/pghero · error · PgHero::Error
Invalid metric name
Error message
Invalid metric name
What it means
PgHero raises this from the private gcp_stats helper (lib/pghero/methods/system.rb:89) when metric_name fails /\A[a-z\/_]+\z/i. The check exists because metric_name is interpolated directly into the Cloud Monitoring time-series filter string (metric.type = "cloudsql.googleapis.com/database/#{metric_name}"); anything outside letters, underscores, and slashes could break out of the quoted filter. PgHero's own callers only pass fixed names like cpu/utilization, disk/quota, postgresql/num_backends, so this fires when custom code invokes gcp_stats with an arbitrary metric string.
Source
Thrown at lib/pghero/methods/system.rb:89
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:
# 1. google-cloud-monitoring-v3
# 2. google-cloud-monitoring
# 3. google-apis-monitoring_v3
begin
require "google/cloud/monitoring/v3"
rescue LoadError
require "google/apis/monitoring_v3"
end
# for situations 1 and 2
# Google::Cloud::Monitoring.metric_service doesn't work for situation 1
if defined?(Google::Cloud::Monitoring::V3)
client = Google::Cloud::Monitoring::V3::MetricService::Client.new
interval = Google::Cloud::Monitoring::V3::TimeInterval.newView on GitHub (pinned to 7edb57986f)
Solutions
- Pass the short slash-form metric name relative to cloudsql.googleapis.com/database/ (e.g. "cpu/utilization", "disk/read_ops_count"), matching the whitelist of letters, underscores, and slashes.
- If you must call gcp_stats with a custom metric, normalize the name first: strip the cloudsql.googleapis.com/database/ prefix and replace invalid characters with underscores.
- Rescue PgHero::Error around custom metric calls and log the rejected name, since the generic Error class carries no structured details.
Example fix
# before - raises PgHero::Error: Invalid metric name obj.send(:gcp_stats, "cloudsql.googleapis.com/database/cpu/utilization") # after - use the short slash-form name (letters, underscore, slash only) obj.send(:gcp_stats, "cpu/utilization")
Defensive patterns
Strategy: validation
Validate before calling
VALID_GCP_METRIC = /\A[a-z\/_]+\z/i
name = "cloudsql.googleapis.com/database/cpu/utilization".delete_prefix("cloudsql.googleapis.com/database/")
PgHero.send(:gcp_stats, name) if VALID_GCP_METRIC.match?(name) Type guard
def valid_gcp_metric_name?(name) name.is_a?(String) && name.match?(/\A[a-z\/_]+\z/i) end
Try / catch
begin
PgHero.send(:gcp_stats, metric_name)
rescue PgHero::Error => e
raise unless e.message == "Invalid metric name"
Rails.logger.error("Rejected GCP metric name: #{metric_name.inspect}")
{}
end Prevention
- Restrict custom metrics to the whitelist charset (letters, underscore, slash) - no dots or digits.
- Derive metric names from a constant map instead of user or console input.
- Prefer extending PgHero's metrics hash in system_stats with short slash-form names.
When it happens
Trigger: Calling the private helper directly (obj.send(:gcp_stats, "disk/bytes_used")) or extending PgHero with new metrics whose names contain dots, digits, spaces, or quotes (e.g. "v2/cpu", "disk.io", "cpu utilization") — all fail the letters/underscore/slash-only whitelist.
Common situations: Plugins or monkey-patches adding custom Cloud SQL metrics to PgHero's system_stats metrics map; copy-pasted metric names from the GCP console (console paths use dots, e.g. cloudsql.googleapis.com/database/cpu/utilization) passed as the full dotted path instead of the trailing slash form.
Related errors
- Invalid database id
- Invalid config file
- pg_query required for filter_data
- Invalid connection URL
- Spec not found: #{config["spec"]}
AI-assisted analysis of ankane/pghero@7edb57986f (2026-08-21).
Data as JSON: /api/errors/1fb6dc3f10a5e4cd.
Report an issue: GitHub.