@@ -52,9 +52,19 @@ impl Counter {
5252 }
5353 }
5454
55- #[ track_caller]
5655 pub fn increment ( & self , count : u64 ) {
57- assert ! ( count <= u32 :: MAX as u64 ) ;
56+ // If we get a particularly large count, directly serialize it into the underlying
57+ // aggregate. We expect this to be rare, so acquiring the lock across all counters should
58+ // be relatively cheap.
59+ //
60+ // It's possible to shift the exact threshold if we wanted to (e.g., by reducing the
61+ // counter index bits, or having a more complicated serialization scheme), but we don't
62+ // expect this to matter much in practice. If the event recorded is this large there's
63+ // probably a good deal of compute needed to produce it in the first place.
64+ if count > ( u32:: MAX as u64 ) {
65+ self . channels . lock_aggregate ( ) [ self . counter as usize ] . value += count;
66+ return ;
67+ }
5868 self . channels
5969 . send_event ( ( ( self . counter as u64 ) << 32 ) | count) ;
6070 }
@@ -76,3 +86,18 @@ fn basic() {
7686
7787 assert_eq ! ( registry. take_current_metrics_line( ) , "a=5,b=9" ) ;
7888}
89+
90+ #[ test]
91+ fn check_u64_max ( ) {
92+ let registry = crate :: Registry :: new ( ) ;
93+ let a = registry. register_counter ( String :: from ( "a" ) , None ) ;
94+ let b = registry. register_counter ( String :: from ( "b" ) , None ) ;
95+
96+ a. increment ( u64:: MAX ) ;
97+ b. increment ( u32:: MAX as u64 ) ;
98+
99+ assert_eq ! (
100+ registry. take_current_metrics_line( ) ,
101+ format!( "a={},b={}" , u64 :: MAX , u32 :: MAX )
102+ ) ;
103+ }
0 commit comments