feat: add http_server.tcp_rejected_rate metric for connection-cap saturation - #7499
Open
ycombinator wants to merge 4 commits into
Open
feat: add http_server.tcp_rejected_rate metric for connection-cap saturation#7499ycombinator wants to merge 4 commits into
ycombinator wants to merge 4 commits into
Conversation
…uration Adds tcp_rejected (counter) and tcp_rejected_rate (gauge, rejections/sec) to Fleet Server's /stats endpoint. The rate is sampled every 10s from the count of HTTP 429 rejections issued by the chi Throttle middleware (the per-pod connection cap at max_connections), following the same pattern as the existing checkin rejection rate sampler introduced in #7330. tcp_rejected_rate is a saturation signal that complements tcp_active: - tcp_active is a utilization signal — EPA uses it to maintain headroom by scaling before pods fill up. It understates demand when connections are short-lived (e.g. an enrollment burst arriving and clearing between samples). - tcp_rejected_rate fires the moment a pod is at its connection ceiling and returning 429s, catching bursts that tcp_active misses entirely. EPA takes the maximum desired replica count across all configured metrics, so wiring both allows proactive scaling (tcp_active: maintain headroom at steady state) and reactive scaling (tcp_rejected_rate: act immediately under a burst). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
|
This pull request does not have a backport label. Could you fix it @ycombinator? 🙏
|
…d in /stats Only tcp_rejected_rate (the sampled gauge) is needed in /stats for EPA. The raw accumulator doesn't need to be a first-class metric, so replace the statsCounter (which registers with both libbeat and Prometheus registries) with an unexported atomic.Uint64. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ectionRateSampler Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…y noctx linter Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is the problem this PR solves?
Fleet Server's existing autoscaling metric,
http_server.tcp_active, is a utilization signal: EPA uses it to maintain headroom by targeting N active connections per pod. This works well at steady state but understates demand when connections are short-lived — specifically during large-scale agent enrollment, where each enrollment connection completes in under a second.tcp_activeis a point-in-time gauge: it reflects the instantaneous count of open HTTP connections at the moment EPA polls/stats. A burst of enrollment connections that arrive and clear between two EPA polls leaves no trace in the metric. The result is that pods plateau well below the theoretical requirement, agents receive HTTP 429s, and enter exponential backoff — turning a short enrollment phase into a multi-hour convergence tail.How does this PR solve the problem?
Adds
http_server.tcp_rejected_rateto/stats: a gauge, in rejections/sec, derived from an internal counter that increments whenever the chiThrottlemiddleware returns HTTP 429 due to the per-pod connection cap (max_connections). The rate is sampled every 10 s by a newRunConnRejectionRateSamplergoroutine.tcp_rejected_ratevstcp_activetcp_activetcp_rejected_rateBecause EPA takes the maximum desired replica count across all configured metrics, wiring both allows proactive scaling (
tcp_active: headroom at steady state) and reactive scaling (tcp_rejected_rate: act immediately under a burst). Neither metric suppresses the other.The raw rejection count is kept as an unexported
atomic.Uint64— only the derived rate gauge is exposed in/stats, since that is the only value EPA consumes. The chiThrottlemiddleware behaviour is unchanged; the wrapper only observes the response status code.How to test this PR locally
max_connections: Nand start it.heyorwrk).curl localhost:5066/stats | python3 -m json.tool | grep tcp_rejected— confirmtcp_rejected_ratebecomes non-zero after ~10 s.tcp_rejected_rateshould return to 0 within the next sample interval.Design Checklist
Checklist
./changelog/fragmentsusing the changelog toolRelated issues