Hi All,

  I'm writing a Windows service that uses log4j2. Since the service is started 
by Windows Service Manager I don't think there's a way to capture the service's 
standard error. I'd like to capture standard error though since this is the 
only place to print debug messages until log4j2 is successfully configured and 
started.

For example if there's a problem with log4j2 configuration file (wrong syntax 
or file doesn't exist) log4j2 uses StatusLogger to print an error to System.err:

ERROR StatusLogger Unable to access file:/C:/log_config.xml%20 
java.io.FileNotFoundException: C:\log_config.xml  (The system cannot find the 
file specified)

I need to redirect this message to a file rather than console (since there's no 
console for a service). To achieve this I attempted to set my own custom 
PrintStream in place of System.err:

PrintStream ps = new PrintStream("log_server.err");
System.setErr(ps);

However StatusLogger doesn't honor reassignments of System.err made after its 
construction and continues to print to console.

By looking at the source code it seems to me that this is happening because 
org.apache.logging.log4j.simple.SimpleLogger()'s constructor (used internally 
by StatusLogger) assigns its "stream" field to the value of System.err on 
construction and there's no public API to change it.

I found that a facility to "follow" the current (rather than stored) System.err 
value is already available for ConsoleAppender 
(https://issues.apache.org/jira/browse/LOG4J2-128).

Could the same functionality be provided for StatusLogger? Perhaps a public API 
that could be used to set an alternative PrintStream or perhaps StatusLogger 
could always reference current value of System.err rather than storing its own 
copy of PrintStream?

Note: a not-so-pretty workaround is to make sure that the call to 
System.setErr() is done before the first call to any of log4j2 APIs. This is 
not ideal as then for example a simple and standard log declaration of form:

private static final Logger log = LogManager.getLogger(Server.class.getName());

is not allowed anymore as LogManager will initialize StatusLogger with initial 
value of System.err (console).

Best regards,
Rafal Aksamit

Reply via email to