Copied from http://www.mail-archive.com/log4j-user@jakarta.apache.org/msg00445.html -------------------------------------------------------------------------------- RE: diverting System.stderr/stdout into log4j -------------------------------------------------------------------------------- From: Michael Smith Subject: RE: diverting System.stderr/stdout into log4j Date: Tue, 13 Mar 2001 06:46:04 -0800 -------------------------------------------------------------------------------- There is another way! In LogLog, completely ignore System.err. Instead, use the following to get the standard error stream: PrintStream err = new PrintStream(new FileOutputStream(FileDescriptor.err)); When you use System.setErr, it changes System.err, but not FileDescriptor.err, which maintains a descriptor for the original error stream. michael For a sample program to test this, see below: import java.io.*; public class Stderr { public static void main(String[] args) { // create a print stream to represent a redirect PrintStream nonStandardErr = new PrintStream(new ByteArrayOutputStream()); // Redirect standard out and standard err System.setOut(nonStandardErr); System.setErr(nonStandardErr); // attempt to print something System.err.println("You should *not* see this on the console!"); // the stuff that would appear in LogLog PrintStream logLogOut = new PrintStream(new FileOutputStream(FileDescriptor.err)); // attempt to print something logLogOut.println("You *should* see this on the console!"); } } > -----Original Message----- > From: Ceki Gülcü [mailto:cgu@qos.ch] > Sent: Monday, March 12, 2001 7:18 PM > To: LOG4J Users Mailing List > Subject: RE: diverting System.stderr/stdout into log4j > > > > Hate to follow up on myself, but the System.setErr method > reassigns the System.err variable. This can be deduced without > experimentation because the user calls the System.err variable > directly to print to the console, whatever it might be. Thus, the > reference itself must change to allow the System.err variable to > point to the new target stream. > > The funny part is that the err variable is declared 'public > final' in the JDK source code. The setErr method makes a call to > setErr0 which is declared as being 'native'. It looks like the > native part is circumventing the JDK restrictions. I find this > quite entertaining. Ceki > > At 00:58 13.03.2001 +0100, Ceki Gülcü wrote: > > >Running the risk of disappointing you here, although not full of > bugs, log4j is not bug-free as bugs creep out regularly. They > just get corrected quickly before many people are affected by them. > > > >The PrintStream se = System.err; LogLog.setPrintStream(see); > combination is simple and rather bright. I initially overlooked > the PrintStream se = System.err; part, making me think that a > lot of code needed to be modified to cater for the redirected > console case. The remedy looked worse than the illness. My fears > are largely unfounded and the solution should work quite well if > one is careful. > > > >Regards, Ceki > > > >ps: I wonder if System.err always refers to the real STDERR or > if really gets reassigned with the setErr call. It's easy to find out... > > > >At 23:20 12.03.2001 +0000, Joseph Panico wrote: > >>Of course log4j is completely bug free, but that doesn't > preclude user error. For instance, I neglected to add appenders > in my config file (actually I intentionally left them out, > thinking that would simply turn off logging) and then log4j went > into an infinite loop. The setPrintStream makes sense to me. > >> > >>joe > >> > >> > >>>From: Jim Moore > >>>Reply-To: "LOG4J Users Mailing List" > >>>To: 'LOG4J Users Mailing List' > >>>Subject: RE: diverting System.stderr/stdout into log4j > >>>Date: Mon, 12 Mar 2001 18:10:37 -0500 > >>> > >>>It doesn't. I haven't worried about it, since log4j doesn't > contain any > >>>bugs and therefore it would never happen... :) > >>> > >>>Probably the best way to handle it is to add a > >>>LogLog.setPrintStream(PrintStream) method, so you can do > something like: > >>> > >>>// remember STDERR > >>>PrintStream se = System.err; > >>> > >>>// make sure everything sent to System.err is logged > >>>System.setErr(new PrintStream(new > LoggingOutputStream(Category.getRoot(), > >>> Priority.WARN), true)); > >>> > >>>// make sure everything sent to System.out is also logged > >>>System.setOut(new PrintStream(new > LoggingOutputStream(Category.getRoot(), > >>> Priority.INFO), true)); > >>> > >>>// prevent infinate recursion in LogLog > >>>LogLog.setPrintStream(se); > >>> > >>> > >>>I can't think of any other way to do it in the current version besides > >>>getting extremely kludgey by checking the stack to see if it's > being called > >>>from LogLog and logging out the the "real" STDERR then in the > >>>LoggingOutputStream. It can be done on the theory that LogLog > wouldn't be > >>>called very often, but still... > >>> > >>>-Jim Moore > >>> > >>> > >>>-----Original Message----- > >>>From: Ceki Gülcü [mailto:cgu@qos.ch] > >>>Sent: Monday, March 12, 2001 5:15 PM > >>>To: LOG4J Users Mailing List > >>>Subject: RE: diverting System.stderr/stdout into log4j > >>> > >>> > >>>Jim, Joseph, > >>> > >>>Here is a link containing Jim's code: > >>> > >>>http://marc.theaimsgroup.com/?l=log4j-user&m=98097669218571&w=2 > >>> > >>>How does this code handle the infinite recursion problem mentioned by > >>>Joseph? Ceki > >>> > >>>At 17:03 12.03.2001 -0500, Jim Moore wrote: > >>>>Go to the mailing list archives (theAimsGroup.com is the > best) and search > >>>>for the thread with the subject of "Capturing System.err" > >>>> > >>>>-Jim Moore > >>>>"I think so, Brain; but if we gave peas a chance, won't the > lima beans get > >>>>jealous?" - Pinky > >>>> > >>>> > >>>>-----Original Message----- > >>>>From: Joseph Panico [mailto:joe_panico@hotmail.com] > >>>>Sent: Monday, March 12, 2001 4:43 PM > >>>>To: log4j-user@jakarta.apache.org > >>>>Subject: diverting System.stderr/stdout into log4j > >>>> > >>>> > >>>>Folks, > >>>> > >>>>We use a number of third-party packages that do > stderr.print... at various > >>>>random places in their code. I'm finding it quite useful to > divert these > >>>>messages into our log4j heirarchy. I do this by replacing > stderr/stdout > >>>with > >>>> > >>>>my own PrintStreams that log the lines to a special log4j > Category-- as > >>>>suggested on this list a while back. The only > fly-in-the-ointment with this > >>> > >>>>scheme is LogLog. If there is a problem with log4j such that > it cannot log > >>>>for some reason, then log4j internals use LogLog to attempt > to print an > >>>>error message. This obviously leads to an infinite recursion. > Has anyone > >>>>else been bothered by this? Would it make sense to add > interface to LogLog > >>>>which would set the PrintStream it uses to log its error messages to? > >>>> > >>>>thanks for any ideas > >>>> > >>>>joe