@@ -9,7 +9,7 @@ use std::{
99} ;
1010
1111use eyre:: { eyre, Result } ;
12- use log:: { debug, error} ;
12+ use log:: { debug, error, warn } ;
1313
1414use crate :: {
1515 metrics:: { KeyedMetricReading , MetricStringKey } ,
@@ -70,19 +70,10 @@ where
7070 . map ( |sectors_written| * sectors_written * SECTOR_SIZE ) ;
7171
7272 if let Some ( bytes_written) = bytes_written {
73- if let Some ( prev_bytes_written) = prev_bytes_reading. replace ( bytes_written) {
74- let bytes_metric_key = MetricStringKey :: from_str ( & format ! (
75- "{}/{}/bytes_written" ,
76- DISK_METRIC_NAMESPACE , disk_name
77- ) )
78- . map_err ( |e| eyre ! ( "Invalid metric key: {}" , e) ) ?;
79- let bytes_since_last_reading = bytes_written - prev_bytes_written;
80- let bytes_metric = KeyedMetricReading :: new_counter (
81- bytes_metric_key,
82- bytes_since_last_reading as f64 ,
83- ) ;
84-
85- metrics. push ( bytes_metric) ;
73+ match Self :: calc_bytes_written_reading ( bytes_written, prev_bytes_reading, disk_name) {
74+ Ok ( Some ( reading) ) => metrics. push ( reading) ,
75+ Ok ( None ) => { }
76+ Err ( e) => debug ! ( "Failed to calculate bytes_written: {}" , e) ,
8677 }
8778 }
8879
@@ -155,6 +146,36 @@ where
155146
156147 Ok ( metrics)
157148 }
149+
150+ fn calc_bytes_written_reading (
151+ cur_bytes_written : u64 ,
152+ prev_bytes_written : & mut Option < u64 > ,
153+ disk_name : & str ,
154+ ) -> Result < Option < KeyedMetricReading > > {
155+ if let Some ( prev_bytes_written) = prev_bytes_written. replace ( cur_bytes_written) {
156+ match cur_bytes_written. checked_sub ( prev_bytes_written) {
157+ Some ( _) => {
158+ let bytes_metric_key = MetricStringKey :: from_str ( & format ! (
159+ "{}/{}/bytes_written" ,
160+ DISK_METRIC_NAMESPACE , disk_name
161+ ) )
162+ . map_err ( |e| eyre ! ( "Invalid metric key: {}" , e) ) ?;
163+ let bytes_since_last_reading = cur_bytes_written - prev_bytes_written;
164+ let bytes_metric = KeyedMetricReading :: new_counter (
165+ bytes_metric_key,
166+ bytes_since_last_reading as f64 ,
167+ ) ;
168+ Ok ( Some ( bytes_metric) )
169+ }
170+ None => {
171+ warn ! ( "bytes_written metric overflow, discarding reading" ) ;
172+ Ok ( None )
173+ }
174+ }
175+ } else {
176+ Ok ( None )
177+ }
178+ }
158179}
159180
160181impl < M > SystemMetricFamilyCollector for DiskMetricsCollector < M >
@@ -323,6 +344,21 @@ mod test {
323344 } ) ;
324345 }
325346
347+ #[ test]
348+ fn test_calc_bytes_reading_overflow ( ) {
349+ let mut prev_bytes_reading = Some ( 1000 ) ;
350+ let cur_bytes_written = 500 ;
351+
352+ let result = DiskMetricsCollector :: < FakeMmc > :: calc_bytes_written_reading (
353+ cur_bytes_written,
354+ & mut prev_bytes_reading,
355+ "mmcblk0" ,
356+ )
357+ . unwrap ( ) ;
358+
359+ assert ! ( result. is_none( ) ) ;
360+ }
361+
326362 #[ rstest]
327363 #[ case( DiskstatsMetricsConfig :: Auto ) ]
328364 #[ case( DiskstatsMetricsConfig :: Devices (
0 commit comments