Skip to content

rate_limit: don't update metrics when a selector has no metrics: block#13343

Open
moonchen wants to merge 1 commit into
apache:masterfrom
moonchen:rate-limit-init-metric-ids
Open

rate_limit: don't update metrics when a selector has no metrics: block#13343
moonchen wants to merge 1 commit into
apache:masterfrom
moonchen:rate-limit-init-metric-ids

Conversation

@moonchen

@moonchen moonchen commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

A rate_limit selector configured without a metrics: block should be a metrics no-op. It isn't.

_metrics is value-initialized to 0, but incrementMetric() only suppresses the update when an entry equals the TS_ERROR (−1) sentinel that metric_helper() uses for "not registered":

std::array<int, RATE_LIMITER_METRIC_MAX> _metrics{};   // value-initialized to 0

void incrementMetric(uint metric) {
  if (_metrics[metric] != TS_ERROR) {                  // 0 != -1 → true → does NOT skip
    TSStatIntIncrement(_metrics[metric], 1);           // increments an unregistered ID
  }
}

_metrics is only populated by initializeMetrics(), which parseYaml() calls only when a selector has a metrics: block. Without that block the guard never fires, so every queue/reject/expire/resume (sni_limiter.cc, sni_selector.cc, txn_limiter.cc) calls TSStatIntIncrement() on an unregistered ID. It currently lands on the reserved proxy.process.api.metrics.bad_id slot (id 0), so it's absorbed rather than fatal — but the plugin still shouldn't be emitting anything.

Fix

Default _metrics to TS_ERROR in the constructor — the same "not registered" marker metric_helper() writes per element — so incrementMetric() stays a no-op until metrics are actually registered.

Testing

The equivalent fix was validated under AddressSanitizer on a 10.x branch. Not built against master locally — relying on CI for the compile.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a subtle metrics mis-accounting issue in the experimental rate_limit plugin by ensuring the RateLimiter’s metric ID array starts in an explicit “not registered” state, making metric increments a no-op unless metrics are configured and registered.

Changes:

  • Initialize RateLimiter::_metrics to TS_ERROR in the default constructor via _metrics.fill(TS_ERROR).
  • Add an explanatory comment documenting why TS_ERROR is required to avoid silently incrementing metric id 0 when selectors omit a metrics: block.

A selector configured without a `metrics:` block should be a metrics no-op.
It isn't: _metrics is value-initialized to 0, but incrementMetric() only
suppresses the update when an entry equals the TS_ERROR (-1) sentinel that
metric_helper() uses for "not registered". So the guard never fires and every
queue/reject/expire/resume calls TSStatIntIncrement() on an unregistered ID.
(It currently lands on the reserved bad_id slot, so it is absorbed rather than
fatal -- but the plugin still should not emit anything.)

Default _metrics to TS_ERROR in the constructor so incrementMetric() stays a
no-op until metrics are actually registered.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@moonchen moonchen force-pushed the rate-limit-init-metric-ids branch from 6e3aa18 to 9fa7af3 Compare June 26, 2026 21:44
@moonchen moonchen changed the title rate_limit: initialize metric IDs so an unconfigured selector is a no-op rate_limit: don't update metrics when a selector has no metrics: block Jun 26, 2026
@moonchen moonchen marked this pull request as ready for review June 26, 2026 21:46
Copilot AI review requested due to automatic review settings June 26, 2026 21:46
@moonchen moonchen self-assigned this Jun 26, 2026
@moonchen moonchen added this to the 11.0.0 milestone Jun 26, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

@bryancall bryancall self-requested a review June 29, 2026 22:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants