You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-user@logging.apache.org by "Aksamit, Rafal (Rafal)" <ra...@avaya.com> on 2014/02/13 16:18:47 UTC

StatusLogger doesn't honor reassignments of System.err made after its construction

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