@@ -7,6 +7,7 @@ use std::{
77 Arc ,
88 atomic:: { AtomicUsize , Ordering } ,
99 } ,
10+ time:: Instant ,
1011} ;
1112
1213#[ cfg( test) ]
@@ -17,10 +18,12 @@ use crossbeam_queue::{ArrayQueue, SegQueue};
1718use futures:: Stream ;
1819use metrics:: { Gauge , Histogram , gauge, histogram} ;
1920use tokio:: sync:: { Notify , OwnedSemaphorePermit , Semaphore , TryAcquireError } ;
20- use vector_common:: stats:: EwmaGauge ;
21+ use vector_common:: stats:: TimeEwmaGauge ;
2122
2223use crate :: { InMemoryBufferable , config:: MemoryBufferSize } ;
2324
25+ pub const DEFAULT_EWMA_HALF_LIFE_SECONDS : f64 = 5.0 ;
26+
2427/// Error returned by `LimitedSender::send` when the receiver has disconnected.
2528#[ derive( Debug , PartialEq , Eq ) ]
2629pub struct SendError < T > ( pub T ) ;
@@ -110,7 +113,7 @@ impl ChannelMetricMetadata {
110113struct Metrics {
111114 histogram : Histogram ,
112115 gauge : Gauge ,
113- mean_gauge : EwmaGauge ,
116+ mean_gauge : TimeEwmaGauge ,
114117 // We hold a handle to the max gauge to avoid it being dropped by the metrics collector, but
115118 // since the value is static, we never need to update it. The compiler detects this as an unused
116119 // field, so we need to suppress the warning here.
@@ -127,8 +130,10 @@ impl Metrics {
127130 fn new (
128131 limit : MemoryBufferSize ,
129132 metadata : ChannelMetricMetadata ,
130- ewma_alpha : Option < f64 > ,
133+ ewma_half_life_seconds : Option < f64 > ,
131134 ) -> Self {
135+ let ewma_half_life_seconds =
136+ ewma_half_life_seconds. unwrap_or ( DEFAULT_EWMA_HALF_LIFE_SECONDS ) ;
132137 let ChannelMetricMetadata { prefix, output } = metadata;
133138 let ( legacy_suffix, gauge_suffix, max_value) = match limit {
134139 MemoryBufferSize :: MaxEvents ( max_events) => (
@@ -157,7 +162,7 @@ impl Metrics {
157162 Self {
158163 histogram : histogram ! ( histogram_name, "output" => label_value. clone( ) ) ,
159164 gauge : gauge ! ( gauge_name, "output" => label_value. clone( ) ) ,
160- mean_gauge : EwmaGauge :: new ( mean_gauge_handle, ewma_alpha ) ,
165+ mean_gauge : TimeEwmaGauge :: new ( mean_gauge_handle, ewma_half_life_seconds ) ,
161166 max_gauge,
162167 legacy_max_gauge,
163168 #[ cfg( test) ]
@@ -173,7 +178,7 @@ impl Metrics {
173178 Self {
174179 histogram : histogram ! ( histogram_name) ,
175180 gauge : gauge ! ( gauge_name) ,
176- mean_gauge : EwmaGauge :: new ( mean_gauge_handle, ewma_alpha ) ,
181+ mean_gauge : TimeEwmaGauge :: new ( mean_gauge_handle, ewma_half_life_seconds ) ,
177182 max_gauge,
178183 legacy_max_gauge,
179184 #[ cfg( test) ]
@@ -183,10 +188,10 @@ impl Metrics {
183188 }
184189
185190 #[ expect( clippy:: cast_precision_loss) ]
186- fn record ( & self , value : usize ) {
191+ fn record ( & self , value : usize , reference : Instant ) {
187192 self . histogram . record ( value as f64 ) ;
188193 self . gauge . set ( value as f64 ) ;
189- self . mean_gauge . record ( value as f64 ) ;
194+ self . mean_gauge . record ( value as f64 , reference ) ;
190195 #[ cfg( test) ]
191196 if let Ok ( mut recorded) = self . recorded_values . lock ( ) {
192197 recorded. push ( value) ;
@@ -221,10 +226,11 @@ impl<T: Send + Sync + Debug + 'static> Inner<T> {
221226 fn new (
222227 limit : MemoryBufferSize ,
223228 metric_metadata : Option < ChannelMetricMetadata > ,
224- ewma_alpha : Option < f64 > ,
229+ ewma_half_life_seconds : Option < f64 > ,
225230 ) -> Self {
226231 let read_waker = Arc :: new ( Notify :: new ( ) ) ;
227- let metrics = metric_metadata. map ( |metadata| Metrics :: new ( limit, metadata, ewma_alpha) ) ;
232+ let metrics =
233+ metric_metadata. map ( |metadata| Metrics :: new ( limit, metadata, ewma_half_life_seconds) ) ;
228234 match limit {
229235 MemoryBufferSize :: MaxEvents ( max_events) => Inner {
230236 data : Arc :: new ( ArrayQueue :: new ( max_events. get ( ) ) ) ,
@@ -256,7 +262,7 @@ impl<T: Send + Sync + Debug + 'static> Inner<T> {
256262 // acquired fewer permits than their true size, `size` is the correct utilization since
257263 // the queue must have been empty for the oversized acquire to succeed.
258264 let utilization = size. max ( self . used_capacity ( ) ) ;
259- metrics. record ( utilization) ;
265+ metrics. record ( utilization, Instant :: now ( ) ) ;
260266 }
261267 self . data . push ( ( permits, item) ) ;
262268 self . read_waker . notify_one ( ) ;
@@ -275,7 +281,7 @@ impl<T> Inner<T> {
275281 // been released yet, used_capacity is stable against racing senders acquiring those
276282 // permits.
277283 let utilization = self . used_capacity ( ) . saturating_sub ( permit. num_permits ( ) ) ;
278- metrics. record ( utilization) ;
284+ metrics. record ( utilization, Instant :: now ( ) ) ;
279285 }
280286 // Release permits after recording so a waiting sender cannot enqueue a new item
281287 // before this pop's utilization measurement is taken.
@@ -446,9 +452,9 @@ impl<T> Drop for LimitedReceiver<T> {
446452pub fn limited < T : InMemoryBufferable + fmt:: Debug > (
447453 limit : MemoryBufferSize ,
448454 metric_metadata : Option < ChannelMetricMetadata > ,
449- ewma_alpha : Option < f64 > ,
455+ ewma_half_life_seconds : Option < f64 > ,
450456) -> ( LimitedSender < T > , LimitedReceiver < T > ) {
451- let inner = Inner :: new ( limit, metric_metadata, ewma_alpha ) ;
457+ let inner = Inner :: new ( limit, metric_metadata, ewma_half_life_seconds ) ;
452458
453459 let sender = LimitedSender {
454460 inner : inner. clone ( ) ,
0 commit comments