Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change Log4J's Threshold dynamically through user input

I'm writing a simple console application which sends and receives data to/from a socket via user commands, such as "send hello" -> receives "hello" from socket. One of the available commands should be logLevel (ALL|WARN|DEBUG|etc.), which enables the user to set the log level of the Log4J logger which I'M using throughout the application.

Right now, I specified two Appenders in my properties file:

# Root logger option
log4j.rootLogger=INFO, file, stdout

# Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./logs/client.log
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=1
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
# info and above messages are printed to stdout
log4j.appender.stdout.Threshold=INFO
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

My goal here is to send all log entries from any level to the logfile, but only the ones that match the specified log level currently set by the user to stdout. A sample workflow could look like this:

> INFO: current log level is INFO and above.
> send hello
> INFO: sending hello to server
> INFO: receiving "hello" from server
> logLevel WARN
> INFO: log level set to warn
> send hello
> # no info here, but its still sent to the logfile
like image 817
doque Avatar asked Jan 13 '23 00:01

doque


1 Answers

My goal here is to send all log entries from any level to the logfile, but only the ones that match the specified log level currently set by the user to stdout.

So essentially you want to change the threshold on the stdout appender programmatically. This is easy enough to do, the wrinkle is that the threshold property is part of the AppenderSkeleton abstract class (which ConsoleAppender extends) rather than the Appender interface itself.

((AppenderSkeleton)Logger.getRootLogger().getAppender("stdout"))
   .setThreshold(Level.toLevel(levelNameProvidedByUser));

If you really do want all log messages to go to the file then you should probably configure the root logger level to ALL rather than INFO in your log4j.properties, and rely on the threshold to filter stdout.

like image 163
Ian Roberts Avatar answered Feb 06 '23 12:02

Ian Roberts