khris khris - 1 month ago 19
Java Question

How to catch third party console log using log4j

I'm using log4j for logging actions in my application. I use following file appender:

private FileAppender getFileAppender(String name) {
PatternLayout layout = new PatternLayout("%d{ABSOLUTE} %5p %t %c{1}:%M:%L - %m%n");
StringBuilder filePath = new StringBuilder();
filePath.append("logs/")
.append(name)
.append(".log");
FileAppender fileAppender = null;

try {
File file = new File(filePath.toString());
file.getParentFile().mkdirs();
file.createNewFile();

fileAppender = new FileAppender(layout, filePath.toString(), true);
fileAppender.setName("FileAppender");
fileAppender.setAppend(true);
} catch (IOException e) {
LogWrapper.LOG.get(this.getClass().getSimpleName()).trace(e);
}

return fileAppender;
}


My application uses third party, what logs web services calls into console. Then I run application I see those logs in my console in Intellij Idea, but not on the generated log file.

How to redirect those logs into the file, generated by File Appender?

Update
The answer is correct, but there is one more third party what use logback with Console Appender, properties looks like:

<configuration status="OFF">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="WARN">
<appender-ref ref="STDOUT" />
</root>




Because of this catching console output stacks. How could I catch and re-write Logback properties and make it log to file or disable logs at all?

xav xav
Answer

You can try this to log STDOUT as INFO and STDERR as WARNING for example:

final Logger myLog4jLogger = Logger.getLogger(getClass());

System.setOut(new PrintStream(new ByteArrayOutputStream() {
    @Override
    public synchronized void write(byte[] pB, int pOff, int pLen) {
        super.write(pB, pOff, pLen);
        myLog4jLogger.info(toString());
        reset();
    }
}));

System.setErr(new PrintStream(new ByteArrayOutputStream() {
    @Override
    public synchronized void write(byte[] pB, int pOff, int pLen) {
        super.write(pB, pOff, pLen);
        myLog4jLogger.warn(toString());
        reset();
    }
}));

Do this only once after Log4j initialization and before calling your third party tool. Be careful, it means that the STDOUT and STDERR of your process will be redirected to your logs, so all the text sent to STDOUT/STDERR by your process will go to logs, including your own "System.out.println()".

Also, using this, you may want to avoid logging to the console, because I'm not sure what will happen if you log to the console and that the console is redirected to the logs... (endless loop? stack overflow? OutOfMemoryError?)

Comments