88import java .util .concurrent .ConcurrentMap ;
99import java .util .concurrent .ThreadLocalRandom ;
1010import java .util .concurrent .TimeUnit ;
11- import java .util .concurrent .atomic .AtomicInteger ;
1211import java .util .function .Consumer ;
1312
1413public class ConditionalLogger {
@@ -19,125 +18,75 @@ public class ConditionalLogger {
1918 private final String key ;
2019 private final Logger logger ;
2120
22- private final ConcurrentMap <String , AtomicInteger > messageToCount ;
23- private final ConcurrentMap <String , Long > messageToWait ;
21+ private final ConcurrentMap <String , Instant > messageToWait ;
2422
2523 public ConditionalLogger (String key , Logger logger ) {
2624 this .key = key ; // can be null
2725 this .logger = Objects .requireNonNull (logger );
2826
29- messageToCount = Caffeine .newBuilder ()
30- .maximumSize (CACHE_MAXIMUM_SIZE )
31- .expireAfterWrite (EXPIRE_CACHE_DURATION , TimeUnit .HOURS )
32- .<String , AtomicInteger >build ()
33- .asMap ();
34-
3527 messageToWait = Caffeine .newBuilder ()
3628 .maximumSize (CACHE_MAXIMUM_SIZE )
3729 .expireAfterWrite (EXPIRE_CACHE_DURATION , TimeUnit .HOURS )
38- .<String , Long >build ()
30+ .<String , Instant >build ()
3931 .asMap ();
4032 }
4133
4234 public ConditionalLogger (Logger logger ) {
4335 this (null , logger );
4436 }
4537
46- public void infoWithKey (String key , String message , int limit ) {
47- log (key , limit , logger -> logger . info ( message ) );
38+ public void debug (String message , long duration , TimeUnit unit ) {
39+ log (message , duration , unit , logger :: debug );
4840 }
4941
50- public void info (String message , int limit ) {
51- log (message , limit , logger -> logger . info ( message ) );
42+ public void debug (String message , double samplingRate ) {
43+ log (message , samplingRate , logger :: debug );
5244 }
5345
5446 public void info (String message , long duration , TimeUnit unit ) {
55- log (message , duration , unit , logger -> logger . info ( message ) );
47+ log (message , duration , unit , logger :: info );
5648 }
5749
5850 public void info (String message , double samplingRate ) {
59- if (samplingRate >= 1.0d || ThreadLocalRandom .current ().nextDouble () < samplingRate ) {
60- logger .warn (message );
61- }
51+ log (message , samplingRate , logger ::info );
6252 }
6353
64- public void errorWithKey (String key , String message , int limit ) {
65- log (key , limit , logger -> logger . error ( message ) );
54+ public void warn (String message , long duration , TimeUnit unit ) {
55+ log (message , duration , unit , logger :: warn );
6656 }
6757
68- public void error (String message , int limit ) {
69- log (message , limit , logger -> logger . error ( message ) );
58+ public void warn (String message , double samplingRate ) {
59+ log (message , samplingRate , logger :: warn );
7060 }
7161
7262 public void error (String message , long duration , TimeUnit unit ) {
73- log (message , duration , unit , logger -> logger . error ( message ) );
63+ log (message , duration , unit , logger :: error );
7464 }
7565
7666 public void error (String message , double samplingRate ) {
77- if (samplingRate >= 1.0d || ThreadLocalRandom .current ().nextDouble () < samplingRate ) {
78- logger .error (message );
79- }
80- }
81-
82- public void debug (String message , int limit ) {
83- log (message , limit , logger -> logger .debug (message ));
84- }
85-
86- public void debug (String message , long duration , TimeUnit unit ) {
87- log (message , duration , unit , logger -> logger .debug (message ));
67+ log (message , samplingRate , logger ::error );
8868 }
8969
90- public void debug (String message , double samplingRate ) {
70+ private static void log (String message , double samplingRate , Consumer < String > logger ) {
9171 if (samplingRate >= 1.0d || ThreadLocalRandom .current ().nextDouble () < samplingRate ) {
92- logger .debug (message );
72+ logger .accept (message );
9373 }
9474 }
9575
96- public void warn (String message , int limit ) {
97- log (message , limit , logger -> logger .warn (message ));
98- }
99-
100- public void warn (String message , long duration , TimeUnit unit ) {
101- log (message , duration , unit , logger -> logger .warn (message ));
102- }
103-
104- public void warn (String message , double samplingRate ) {
105- if (samplingRate >= 1.0d || ThreadLocalRandom .current ().nextDouble () < samplingRate ) {
106- logger .warn (message );
107- }
108- }
109-
110- /**
111- * Calls {@link Consumer} if the given limit for specified key is not exceeded.
112- */
113- private void log (String key , int limit , Consumer <Logger > consumer ) {
114- final String resolvedKey = ObjectUtils .defaultIfNull (this .key , key );
115- final AtomicInteger count = messageToCount .computeIfAbsent (resolvedKey , ignored -> new AtomicInteger ());
116- if (count .incrementAndGet () >= limit ) {
117- count .set (0 );
118- consumer .accept (logger );
119- }
120- }
76+ private void log (String message , long duration , TimeUnit unit , Consumer <String > logger ) {
77+ final String key = ObjectUtils .defaultIfNull (this .key , message );
78+ final Instant currentTime = Instant .now ();
79+ final Instant endTime = messageToWait .computeIfAbsent (
80+ key , ignored -> calculateEndTime (currentTime , duration , unit ));
12181
122- /**
123- * Calls {@link Consumer} if the given time for specified key is not exceeded.
124- */
125- private void log (String key , long duration , TimeUnit unit , Consumer <Logger > consumer ) {
126- final long currentTime = Instant .now ().toEpochMilli ();
127- final String resolvedKey = ObjectUtils .defaultIfNull (this .key , key );
128- final long endTime = messageToWait .computeIfAbsent (resolvedKey , ignored -> calculateEndTime (duration , unit ));
129-
130- if (currentTime >= endTime ) {
131- messageToWait .replace (resolvedKey , endTime , calculateEndTime (duration , unit ));
132- consumer .accept (logger );
82+ // we skip 1st ever log event for the key
83+ if (currentTime .isAfter (endTime ) || currentTime .equals (endTime )) {
84+ messageToWait .replace (key , endTime , calculateEndTime (currentTime , duration , unit ));
85+ logger .accept (message );
13386 }
13487 }
13588
136- /**
137- * Returns time in millis as current time incremented by specified duration.
138- */
139- private static long calculateEndTime (long duration , TimeUnit unit ) {
140- final long durationInMillis = unit .toMillis (duration );
141- return Instant .now ().plusMillis (durationInMillis ).toEpochMilli ();
89+ private static Instant calculateEndTime (Instant currentTime , long duration , TimeUnit unit ) {
90+ return currentTime .plusMillis (unit .toMillis (duration ));
14291 }
14392}
0 commit comments