17

How can I use Logback to capture System.out messages in a Java program?

For example, I would like to use this code:

System.out.println("test: console out to file instead");

... and capture it's output to a file.

Can this be done using the logback.xml config file?

Matthew
  • 8,183
  • 10
  • 37
  • 65

3 Answers3

10

There's a little jar that does this for you: http://projects.lidalia.org.uk/sysout-over-slf4j/index.html

Please do read the FAQ: http://projects.lidalia.org.uk/sysout-over-slf4j/faq.html - If you use this module and configure logback to output to stdout, you'll get a stream of StackOverFlowErrors :D

If you want to do this yourself, you need to replace System.out and System.err with a custom PrintWriter (?I cannot fully remember the class name). This custom PrintWriter needs to forward the calls to logback in a semi intelligent manner, as print writters can also print character by character rather than by line.

Augusto
  • 28,839
  • 5
  • 58
  • 88
  • I suspected I was on the wrong path trying to redirect the standard output instead of creating logger objects in code. If a jar is needed to do this then I suspect there is not basic configuration for logback,xml to accomplish my goal. – Matthew Aug 26 '16 at 16:07
  • 1
    No jar is needed, you can simply set the System.out and System.err in your code. Just look at the System class methods. Only thing you need to do is passing in an OutputStream that outputs to a file (e.g. FileOutputStream) – n247s Aug 26 '16 at 16:28
  • 1
    @Matthew As the home page of the project states, it's a `hack` for very old code or bad libraries. You should never build a new app relying on something like this. The code in there is not super complex. – Augusto Aug 26 '16 at 16:47
  • I found following implementation, LoggerPrintStream, might be helpful if you want to implement yourself. https://github.com/dmlloyd/openjdk/blob/jdk/jdk/src/java.rmi/share/classes/sun/rmi/runtime/Log.java#L295 – shinpei Nov 21 '18 at 10:56
2

The sysout-over-slf4j solutions answers the question 100%.

Just take note: If you setup the Java Util Logger -> SLF4j bridge (jul-to-slf4j), all the System.out.println messages will also be in you logback log file, along with all the messages printed to the Java util logger.

Here is how to set it up: https://stackoverflow.com/a/43242620/2359435

Max
  • 1,107
  • 12
  • 24
  • 1
    sysout-over-slf4j does not redirect data that comes in via `write(byte[])`, `write(int)`, and `write(byte[], int, int)`. It's a conscious decision (saves a few cycles of usually-unnecessary call origin checking), but if data is lost you have no clue in your log. And it does bite: The SSL code in Oracle OpenJDK contains such calls when `-Djavax.net.debug` is set. – toolforger Mar 04 '19 at 15:44
-3

Yes you can do it with some configuration similar to..

<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
  <target>System.out</target>
  <filter class="com.foo.StdOutFilter" />
  ...
</appender>
<logger name="mylogger" level="debug">
   <appender-ref ref="stdout" />
</logger>
Sirsendu
  • 283
  • 1
  • 8
  • 7
    That's logging to console. The question is the opposite of that, in fact, capturing System.out and writing it to a file. – rustyx Aug 26 '16 at 16:07