Last active
September 6, 2024 13:45
-
-
Save LrWm3/6a1cd21c7c50de6663f943da9ef574a6 to your computer and use it in GitHub Desktop.
Log4j2 debounce filter example (untested)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.apache.logging.log4j.core.config.plugins.Plugin; | |
import org.apache.logging.log4j.core.config.plugins.PluginAttribute; | |
import org.apache.logging.log4j.core.config.plugins.PluginFactory; | |
// Register the plugin to allow it to be used later | |
@Plugin(name = "DebounceFilter", category = "Core", elementType = "filter", printObject = true) | |
public class DebounceFilterPlugin extends DebounceFilter { | |
// Factory method for creating the filter from configuration | |
@PluginFactory | |
public static DebounceFilter createFilter(@PluginAttribute("debounceTimeMs") long debounceTimeMs) { | |
return new DebounceFilter(debounceTimeMs); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Configuration status="WARN"> | |
<Appenders> | |
<Console name="Console" target="SYSTEM_OUT"> | |
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> | |
</Console> | |
</Appenders> | |
<Loggers> | |
<!-- Root logger without the debounce filter --> | |
<Root level="info"> | |
<AppenderRef ref="Console"/> | |
</Root> | |
<!-- Logger specifically for classes which may log a high level of warn messages --> | |
<Logger name="com.myorg.myproduct.MySpecificClass" level="warn" additivity="false"> | |
<AppenderRef ref="Console"/> | |
<Filters> | |
<!-- Debounce filter applied only to this logger --> | |
<Filter type="DebounceFilter" debounceTimeMs="60000" onMatch="NEUTRAL" onMismatch="DENY"/> | |
</Filters> | |
</Logger> | |
</Loggers> | |
</Configuration> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.apache.logging.log4j.core.Filter; | |
import org.apache.logging.log4j.core.LogEvent; | |
import org.apache.logging.log4j.core.filter.AbstractFilter; | |
import org.apache.logging.log4j.core.filter.Filter.Result; | |
import java.util.Map; | |
import java.util.concurrent.ConcurrentHashMap; | |
public class DebounceFilter extends AbstractFilter { | |
// Class to hold details about a log message's debouncing status | |
private static class LogEntry { | |
long firstLoggedTime; // First time the message was logged | |
long lastLoggedTime; // Last time the message was logged | |
int debounceCount; // Number of times the message was suppressed | |
} | |
// Map to store log messages and their debouncing information | |
private final Map<String, LogEntry> messageLogEntries = new ConcurrentHashMap<>(); | |
// Time window for debounce in milliseconds (e.g., 1 minute = 60000 ms) | |
private final long debounceTimeMs; | |
// Constructor to set debounce time | |
public DebounceFilter(long debounceTimeMs) { | |
this.debounceTimeMs = debounceTimeMs; | |
} | |
@Override | |
public Result filter(LogEvent event) { | |
// Get the log message | |
String message = event.getMessage().getFormattedMessage(); | |
long currentTime = System.currentTimeMillis(); | |
// Get or create a LogEntry for this message | |
LogEntry logEntry = messageLogEntries.computeIfAbsent(message, k -> new LogEntry()); | |
// If this is the first time the message is being logged, initialize the entry | |
if (logEntry.firstLoggedTime == 0) { | |
logEntry.firstLoggedTime = currentTime; | |
logEntry.lastLoggedTime = currentTime; | |
logEntry.debounceCount = 0; | |
return Result.NEUTRAL; // Log the message | |
} | |
// Check if enough time has passed since the last time the message was logged | |
if ((currentTime - logEntry.lastLoggedTime) > debounceTimeMs) { | |
// Log the original message along with the debounce count and duration | |
if (logEntry.debounceCount > 0) { | |
String debounceInfo = String.format( | |
"[%d suppressed occurrences over %d ms]", | |
logEntry.debounceCount, | |
currentTime - logEntry.firstLoggedTime | |
); | |
// Log the message with debounce info (you can decide how to log this, like appending to the original message) | |
System.out.println(message + " " + debounceInfo); | |
} | |
// Reset the debounce state for the message | |
logEntry.firstLoggedTime = currentTime; | |
logEntry.lastLoggedTime = currentTime; | |
logEntry.debounceCount = 0; | |
return Result.NEUTRAL; // Log the message | |
} else { | |
// Debounce the message: update the last logged time and increment the debounce count | |
logEntry.lastLoggedTime = currentTime; | |
logEntry.debounceCount++; | |
return Result.DENY; // Suppress the message | |
} | |
} | |
// Factory method for the filter configuration (optional, can be customized) | |
public static DebounceFilter createFilter(long debounceTimeMs) { | |
return new DebounceFilter(debounceTimeMs); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment