fix(metrics): prevent negative gauge values for buffer metrics - #5467
fix(metrics): prevent negative gauge values for buffer metrics#5467VedantMadane wants to merge 1 commit into
Conversation
LocalMetrics sub/dec could drive buffer size gauges below zero when racey buffer accounting under/over-subtracted (issues fluent#5303, fluent#2712). That produced negative Prometheus series such as fluentd_output_status_buffer_total_bytes. Clamp gauge sub/dec at zero in LocalMetrics, and clamp stage/queue sizes when exporting buffer statistics. Fixes fluent#5303 Signed-off-by: Vedant Madane <6527493+VedantMadane@users.noreply.github.com>
a9e5a03 to
50918f2
Compare
|
Thanks for digging into #5303. However, I think clamping at zero is the wrong direction for the buffer counters: it converts a transient, self-healing negative into a permanent over-count.
That leaves a window in which the enqueue thread can run Take a 100-byte chunk in that window:
Under load this repeats on every flush cycle and accumulates. Note that @total_limit_size > @stage_size_metrics.get + @queue_size_metrics.getSo an effectively empty buffer eventually fails this check and the output starts raising Two related points:
I would suggest fixing the add/sub pairing in One more thing unrelated to the design question: |
There was a problem hiding this comment.
Pull request overview
This PR addresses negative buffer size gauge values that can surface under concurrent buffer stage/queue transitions, ensuring exported buffer metrics do not report negative byte sizes (notably impacting Prometheus consumers).
Changes:
- Clamp
LocalMetricsgaugesub/decoperations so gauge values do not fall below zero. - Clamp buffer
statisticsexport forstage_byte_size/queue_byte_sizeto non-negative values. - Add unit tests to verify gauge
sub/decnever produce negative values.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
lib/fluent/plugin/metrics_local.rb |
Floors gauge decrements/subtractions at zero to prevent negative gauges in the default local metrics backend. |
lib/fluent/plugin/buffer.rb |
Ensures exported buffer statistics never publish negative stage/queue byte sizes by clamping at export time. |
test/plugin/test_metrics_local.rb |
Adds unit tests validating non-negative behavior for gauge sub/dec. |
Suppressed comments (1)
lib/fluent/plugin/buffer.rb:925
available_buffer_space_ratiosis described as a ratio of available space, butbuffer_spacecan still go below 0.0 (or above 1.0) if stage/queue counters drift upward beyond@total_limit_size. This would export negative (or >100) ratios; consider clamping the computed ratio to [0.0, 1.0] before publishing.
buffer_space = 1.0 - ((stage_size + queue_size * 1.0) / @total_limit_size)
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| # Clamp to non-negative: historical races can leave counters slightly | ||
| # negative (issues #5303, #2712). Exported Prometheus gauges must not | ||
| # report negative buffer sizes. | ||
| stage_size = [@stage_size_metrics.get, 0].max | ||
| queue_size = [@queue_size_metrics.get, 0].max |
Which issue(s) this PR fixes:
Fixes #5303
What this PR does / why we need it:
Buffer size gauges (
stage_byte_size,queue_byte_size, and derivedtotal_queued_size) can go negative when Fluentd core under/over-subtracts during concurrent stage/queue transitions. Those values are mirrored by the Prometheus plugin asfluentd_output_status_buffer_total_bytes/fluentd_output_status_buffer_stage_byte_size, which is what #5303 reports.@Watson1978 noted on the issue that the Prometheus plugin only mirrors Fluentd core counters; the drift lives in core (related to the class of races addressed in #2712 / #2734).
This PR:
LocalMetricsgaugesub/decat zero so gauges never go negative under local metrics (the default).statisticsso exporters never publish negative sizes even if an alternate metrics backend returns a negative intermediate value.sub/dec.This does not attempt a full re-audit of every buffer lock path; it stops the user-visible bad export and prevents counter corruption from cascading.
Docs Changes:
N/A
Release Note:
stage_byte_size/queue_byte_size/total_queued_size) under concurrent buffer operations