Class: RuboCop::Cop::Sequra::PrometheusMetricLabels
- Inherits:
-
Base
- Object
- Base
- RuboCop::Cop::Sequra::PrometheusMetricLabels
- Extended by:
- AutoCorrector
- Defined in:
- lib/rubocop/cop/sequra/prometheus_metric_labels.rb
Overview
Detects malformed label arguments on prometheus_exporter metric calls.
PrometheusExporter::Client::RemoteMetric takes labels as a positional
hash, and the position differs per method:
increment(keys = nil, value = 1)
decrement(keys = nil, value = 1)
observe(value = 1, keys = nil)
None of them accept keyword arguments, so increment(labels: {...})
does not raise. Ruby folds the keyword into the positional keys hash
and the exporter emits a series carrying a label literally named
labels, whose value is the stringified inner hash. The result is
valid Prometheus exposition text, so the scrape succeeds and the
target stays healthy — sum by (outcome) simply never matches.
Nothing downstream can catch it: the exporter keys its series by the
raw hash, labels_text interpolates label names without validating
them, and opts: { labels: [...] } at registration is discarded
outright for counters and gauges. There is no label schema anywhere,
so a wrong label name is indistinguishable from a new one, and the
mistake only surfaces when a query silently returns nothing.
Constant Summary collapse
- MSG_LABELS_KEYWORD =
"Pass Prometheus labels positionally, not as a `labels:` keyword. " \ "`increment`/`observe`/`decrement` take no keyword arguments, so this " \ "becomes a single series labelled `labels=\"{...}\"` and by-label " \ "queries never match. Use `increment({ outcome: :bound })`.".freeze
- MSG_VALUE_FIRST =
"`observe` takes the value first and the labels second: " \ "`observe(value, { outcome: :ok })`. A labels hash in the first position " \ "is recorded as the observed value.".freeze
- MSG_LABELS_FIRST =
"`%<method>s` takes the labels first and the value second: " \ "`%<method>s({ outcome: :ok }, 1)`. This is the reverse of `observe`.".freeze
- MSG_STUBBED_LABELS =
"Stubbing `increment` with a `labels:` keyword asserts a label shape " \ "prometheus_exporter never produces, so the spec stays green while " \ "the metric is broken. Match the positional hash instead: " \ "`.with({ outcome: :bound })`.".freeze
- LABELS_FIRST_METHODS =
[:increment, :decrement].freeze
- VALUE_FIRST_METHODS =
[:observe].freeze
- METRIC_METHODS =
(LABELS_FIRST_METHODS + VALUE_FIRST_METHODS).freeze
Instance Method Summary collapse
Instance Method Details
#on_send(node) ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/rubocop/cop/sequra/prometheus_metric_labels.rb', line 84 def on_send(node) check_stubbed_labels_keyword(node) return unless node.receiver && METRIC_METHODS.include?(node.method_name) # A `labels:` key is the more specific diagnosis, so when it is # present it wins and the positional checks stay quiet. return if check_labels_keyword(node) check_argument_order(node) end |