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