Skip to content

Instantly share code, notes, and snippets.

@Scarsz
Created April 7, 2025 22:57
Show Gist options
  • Save Scarsz/558065dc7996b8676c3cadb1f7160637 to your computer and use it in GitHub Desktop.
Save Scarsz/558065dc7996b8676c3cadb1f7160637 to your computer and use it in GitHub Desktop.
Run a Runnable when a specific Log4J message is appended to the log
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.layout.PatternLayout;
import java.lang.reflect.InvocationTargetException;
import java.util.function.Predicate;
/**
* Executes the passed Runnable when a matching log message is appended
*/
public class LogHook extends AbstractAppender {
private final Predicate<LogEvent> predicate;
private final Runnable runnable;
public LogHook(String message, Runnable runnable) {
this(event -> event.getMessage().getFormattedMessage().equals(message), runnable);
}
public LogHook(String logger, String message, Runnable runnable) {
this(event -> (event.getLoggerName().equals(logger) || event.getSource().getClassName().equals(logger)) && event.getMessage().getFormattedMessage().equals(message), runnable);
}
public LogHook(Predicate<LogEvent> predicate, Runnable runnable) {
super("LogHook", null, PatternLayout.createDefaultLayout(), false);
this.predicate = predicate;
this.runnable = runnable;
Logger rootLogger = LogManager.getRootLogger();
try {
rootLogger.getClass().getMethod("addAppender", Appender.class).invoke(rootLogger, this);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
@Override
public void append(LogEvent event) {
if (predicate.test(event)) {
try {
Thread thread = new Thread(runnable);
thread.start();
thread.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
@Override
public boolean isStarted() {
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment