mabi
mabi

Reputation: 5307

Can I make Log4J suppress logging specific messages for a time?

I thought this is a pretty basic requirement, although difficult to implement efficiently:

At one codebase, we log quite a bit, depending on user behavior. For the sake of argument say every click on a button creates a log message with the name of the clicked button.

Now, I don't care about each and every clicked button. I'm quite content having one message printed once every 5 minutes, regardless of the number of times the user clicked the button.

I can do this pretty easily in user code:

private static final Logger LOG = Logger.getLogger("buttons");
private static final long LOG_ONLY_EVERY = Duration.ofMinutes( 5 ).getSeconds();

private static final Map<String, Long> loggedViolations = new HashMap<>();

public static void logClick( String buttonName )
{
    String msg = "Button " + buttonName + " has been clicked";

    final long epochSecond = Instant.now( Clock.systemUTC() ).getEpochSecond();
    if ( !loggedViolations.containsKey( msg ) )
    {
        loggedViolations.put( msg, epochSecond );
    }
    if ( loggedViolations.get( msg ) + LOG_ONLY_EVERY < epochSecond )
    {
        LOG.warn( msg );
        loggedViolations.put( msg, epochSecond );
    }
}

My question is: can SLF4J or Log4J do this for me? How?

And yes, I'm aware the above code is lacking synchronization. If the answer to the above question is "no, do it yourself" - would the above be safe in a multi-threaded environment (since I don't remove messages, anyway)?

Upvotes: 1

Views: 4430

Answers (1)

jmehrens
jmehrens

Reputation: 11045

Use the BurstFilter and install it on the buttons logger:

The BurstFilter provides a mechanism to control the rate at which LogEvents are processed by silently discarding events after the maximum limit has been reached.

For Logback use the DuplicateMessageFilter.

Upvotes: 2

Related Questions