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 Henrik Engert <he...@axiell.com> on 2005/11/17 11:21:40 UTC
Redirecting System.err to log4j
Hi,
This subject has been upp before, but I can not get it to work in our
app. We need/want to make sure that runtime exceptions such as
NullPointerException etc. should be logged together in our log file that
is managed by log4j. I have found some old emails on this mailing list
where the suggestion was to write your own Outputstream to get it to
work. I have tried to use that code, but we get a bunch of
space-characters in our logfile.
Is there any easier way in redirecting System.err to log4j?
Any suggestion would help.
Code below.
Thanks.
************************
import java.io.*;
import org.apache.log4j.*;
/**
* An OutputStream that flushes out to a Category.<p>
* <p/>
* Note that no data is written out to the Category until the stream is
* flushed or closed.<p>
* <p/>
* Example:<pre>
* // make sure everything sent to System.err is logged
* System.setErr(new PrintStream(new
LoggingOutputStream(Category.getRoot(),
* Priority.WARN), true));
* <p/>
* // make sure everything sent to System.out is also logged
* System.setOut(new PrintStream(new
LoggingOutputStream(Category.getRoot(),
* Priority.INFO), true));
* </pre>
*
* @author <a href="mailto://Jim.Moore@rocketmail.com">Jim Moore</a>
* @see Category
*/
public class LoggingOutputStream extends OutputStream {
/**
* Used to maintain the contract of {@link #close()}.
*/
protected boolean hasBeenClosed = false;
/**
* The internal buffer where data is stored.
*/
protected byte[] buf;
/**
* The number of valid bytes in the buffer. This value is always
* in the range <tt>0</tt> through <tt>buf.length</tt>; elements
* <tt>buf[0]</tt> through <tt>buf[count-1]</tt> contain valid
* byte data.
*/
protected int count;
/**
* Remembers the size of the buffer for speed.
*/
private int bufLength;
/**
* The default number of bytes in the buffer. =2048
*/
public static final int DEFAULT_BUFFER_LENGTH = 2048;
/**
* The category to write to.
*/
protected Logger logger;
/**
* The priority to use when writing to the Category.
*/
protected Level level;
private LoggingOutputStream() {
// illegal
}
/**
* Creates the LoggingOutputStream to flush to the given Category.
*
* @param log the Logger to write to
* @param level the Level to use when writing to the Logger
* @throws IllegalArgumentException if cat == null or priority ==
null
*/
public LoggingOutputStream(Logger log, Level level)
throws IllegalArgumentException {
if (log == null) {
throw new IllegalArgumentException("cat == null");
}
if (level == null) {
throw new IllegalArgumentException("priority == null");
}
this.level = level;
logger = log;
bufLength = DEFAULT_BUFFER_LENGTH;
buf = new byte[DEFAULT_BUFFER_LENGTH];
count = 0;
}
/**
* Closes this output stream and releases any system resources
* associated with this stream. The general contract of
* <code>close</code>
* is that it closes the output stream. A closed stream cannot
perform
* output operations and cannot be reopened.
*/
public void close() {
flush();
hasBeenClosed = true;
}
/**
* Writes the specified byte to this output stream. The general
* contract for <code>write</code> is that one byte is written
* to the output stream. The byte to be written is the eight
* low-order bits of the argument <code>b</code>. The 24
* high-order bits of <code>b</code> are ignored.
*
* @param b the <code>byte</code> to write
* @throws IOException if an I/O error occurs. In particular,
* an <code>IOException</code> may be thrown if
the
* output stream has been closed.
*/
public void write(final int b) throws IOException {
if (hasBeenClosed) {
throw new IOException("The stream has been closed.");
}
// would this be writing past the buffer?
if (count == bufLength) {
// grow the buffer
final int newBufLength = bufLength + DEFAULT_BUFFER_LENGTH;
final byte[] newBuf = new byte[newBufLength];
System.arraycopy(buf, 0, newBuf, 0, bufLength);
buf = newBuf;
bufLength = newBufLength;
}
buf[count] = (byte) b;
count++;
}
/**
* Flushes this output stream and forces any buffered output bytes
* to be written out. The general contract of <code>flush</code> is
* that calling it is an indication that, if any bytes previously
* written have been buffered by the implementation of the output
* stream, such bytes should immediately be written to their
* intended destination.
*/
public void flush() {
if (count == 0) {
return;
}
// don't print out blank lines; flushing from PrintStream puts
out these
if (count == 1 && ((char) buf[0]) == '\n') {
reset();
return;
}
final byte[] theBytes = new byte[buf.length];
System.arraycopy(buf, 0, theBytes, 0, count);
logger.log(level, new String(theBytes));
reset();
}
private void reset() {
// not resetting the buffer -- assuming that if it grew then it
// will likely grow similarly again
count = 0;
}
}
************************
************************
// remember STDERR
PrintStream se = System.err;
// make sure everything sent to System.err is logged
System.setErr(new PrintStream(new
LoggingOutputStream(Logger.getRootLogger(),
Level.WARN), true));
// make sure everything sent to System.out is also logged
System.setOut(new PrintStream(new
LoggingOutputStream(Logger.getRootLogger(),
Level.INFO), true));
***********************
###########################################
This message has been scanned by F-Secure Anti-Virus for Microsoft Exchange.
For more information, connect to http://www.f-secure.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org
Re: Redirecting System.err to log4j
Posted by Xavier Outhier <xa...@siemens.com>.
Xavier Outhier wrote:
> Try the modified code below, it should help to have a better output :
> no blank,
> no empty line and should be valid on the 3 systems: linux, win and mac.
>
> Cheers,
>
> Xavier.
> [...]
The line below is of course useless. I used it for my own tests.
> static Logger myLogger =
> Logger.getLogger(JscLoggingOutputStream.class.getName());
[...]
---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org
Re: Redirecting System.err to log4j
Posted by Xavier Outhier <xa...@siemens.com>.
Try the modified code below, it should help to have a better output : no
blank,
no empty line and should be valid on the 3 systems: linux, win and mac.
Cheers,
Xavier.
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
/**
* An OutputStream that flushes out to a Category.<p>
* <p/>
* Note that no data is written out to the Category until the stream is
* flushed or closed.<p>
* <p/>
* Example:<pre>
* // make sure everything sent to System.err is logged
* System.setErr(new PrintStream(new
* JscLoggingOutputStream(Category.getRoot(),
* Priority.WARN), true));
* <p/>
* // make sure everything sent to System.out is also logged
* System.setOut(new PrintStream(new
* JscLoggingOutputStream(Category.getRoot(),
* Priority.INFO), true));
* </pre>
*
* @author <a href="mailto://Jim.Moore@rocketmail.com">Jim Moore</a>
* @see Category
*/
//
public class JscLoggingOutputStream extends OutputStream {
static Logger myLogger =
Logger.getLogger(JscLoggingOutputStream.class.getName());
/**
* Used to maintain the contract of {@link #close()}.
*/
protected boolean hasBeenClosed = false;
/**
* The internal buffer where data is stored.
*/
protected byte[] buf;
/**
* The number of valid bytes in the buffer. This value is always
* in the range <tt>0</tt> through <tt>buf.length</tt>; elements
* <tt>buf[0]</tt> through <tt>buf[count-1]</tt> contain valid
* byte data.
*/
protected int count;
/**
* Remembers the size of the buffer for speed.
*/
private int bufLength;
/**
* The default number of bytes in the buffer. =2048
*/
public static final int DEFAULT_BUFFER_LENGTH = 2048;
/**
* The category to write to.
*/
protected Logger logger;
/**
* The priority to use when writing to the Category.
*/
protected Level level;
private JscLoggingOutputStream() {
// illegal
}
/**
* Creates the JscLoggingOutputStream to flush to the given Category.
*
* @param log the Logger to write to
* @param level the Level to use when writing to the Logger
* @throws IllegalArgumentException if cat == null or priority ==
* null
*/
public JscLoggingOutputStream(Logger log, Level level)
throws IllegalArgumentException {
if (log == null) {
throw new IllegalArgumentException("cat == null");
}
if (level == null) {
throw new IllegalArgumentException("priority == null");
}
this.level = level;
logger = log;
bufLength = DEFAULT_BUFFER_LENGTH;
buf = new byte[DEFAULT_BUFFER_LENGTH];
count = 0;
}
/**
* Closes this output stream and releases any system resources
* associated with this stream. The general contract of
* <code>close</code>
* is that it closes the output stream. A closed stream cannot
* perform
* output operations and cannot be reopened.
*/
public void close() {
flush();
hasBeenClosed = true;
}
/**
* Writes the specified byte to this output stream. The general
* contract for <code>write</code> is that one byte is written
* to the output stream. The byte to be written is the eight
* low-order bits of the argument <code>b</code>. The 24
* high-order bits of <code>b</code> are ignored.
*
* @param b the <code>byte</code> to write
* @throws IOException if an I/O error occurs. In particular,
* an <code>IOException</code> may be thrown if
* the
* output stream has been closed.
*/
public void write(final int b) throws IOException {
if (hasBeenClosed) {
throw new IOException("The stream has been closed.");
}
// would this be writing past the buffer?
if (count == bufLength) {
// grow the buffer
final int newBufLength = bufLength + DEFAULT_BUFFER_LENGTH;
final byte[] newBuf = new byte[newBufLength];
System.arraycopy(buf, 0, newBuf, 0, bufLength);
buf = newBuf;
bufLength = newBufLength;
}
buf[count] = (byte) b;
count++;
}
/**
* Flushes this output stream and forces any buffered output bytes
* to be written out. The general contract of <code>flush</code> is
* that calling it is an indication that, if any bytes previously
* written have been buffered by the implementation of the output
* stream, such bytes should immediately be written to their
* intended destination.
*/
public void flush() {
if (count == 0) {
return;
}
// don't print out blank lines; flushing from PrintStream puts
// out these
// For linux system
if (count == 1 && ((char) buf[0]) == '\n') {
reset();
return;
}
// For mac system
if (count == 1 && ((char) buf[0]) == '\r') {
reset();
return;
}
// On windows system
if (count==2 && (char)buf[0]=='\r' && (char)buf[1]=='\n') {
reset();
return;
}
final byte[] theBytes = new byte[count];
System.arraycopy(buf, 0, theBytes, 0, count);
logger.log(level, new String(theBytes));
reset();
}
private void reset() {
// not resetting the buffer -- assuming that if it grew then it
// will likely grow similarly again
count = 0;
}
}
Henrik Engert wrote:
>Hi,
>
>This subject has been upp before, but I can not get it to work in our
>app. We need/want to make sure that runtime exceptions such as
>NullPointerException etc. should be logged together in our log file that
>is managed by log4j. I have found some old emails on this mailing list
>where the suggestion was to write your own Outputstream to get it to
>work. I have tried to use that code, but we get a bunch of
>space-characters in our logfile.
>
>Is there any easier way in redirecting System.err to log4j?
>
>Any suggestion would help.
>
>Code below.
>
>Thanks.
>
>************************
>import java.io.*;
>
>import org.apache.log4j.*;
>
>/**
> * An OutputStream that flushes out to a Category.<p>
> * <p/>
> * Note that no data is written out to the Category until the stream is
> * flushed or closed.<p>
> * <p/>
> * Example:<pre>
> * // make sure everything sent to System.err is logged
> * System.setErr(new PrintStream(new
>LoggingOutputStream(Category.getRoot(),
> * Priority.WARN), true));
> * <p/>
> * // make sure everything sent to System.out is also logged
> * System.setOut(new PrintStream(new
>LoggingOutputStream(Category.getRoot(),
> * Priority.INFO), true));
> * </pre>
> *
> * @author <a href="mailto://Jim.Moore@rocketmail.com">Jim Moore</a>
> * @see Category
> */
>
>public class LoggingOutputStream extends OutputStream {
>
> /**
> * Used to maintain the contract of {@link #close()}.
> */
> protected boolean hasBeenClosed = false;
>
> /**
> * The internal buffer where data is stored.
> */
> protected byte[] buf;
>
> /**
> * The number of valid bytes in the buffer. This value is always
> * in the range <tt>0</tt> through <tt>buf.length</tt>; elements
> * <tt>buf[0]</tt> through <tt>buf[count-1]</tt> contain valid
> * byte data.
> */
> protected int count;
>
> /**
> * Remembers the size of the buffer for speed.
> */
> private int bufLength;
>
> /**
> * The default number of bytes in the buffer. =2048
> */
> public static final int DEFAULT_BUFFER_LENGTH = 2048;
>
>
> /**
> * The category to write to.
> */
> protected Logger logger;
>
> /**
> * The priority to use when writing to the Category.
> */
> protected Level level;
>
>
> private LoggingOutputStream() {
> // illegal
> }
>
>
> /**
> * Creates the LoggingOutputStream to flush to the given Category.
> *
> * @param log the Logger to write to
> * @param level the Level to use when writing to the Logger
> * @throws IllegalArgumentException if cat == null or priority ==
>null
> */
> public LoggingOutputStream(Logger log, Level level)
> throws IllegalArgumentException {
> if (log == null) {
> throw new IllegalArgumentException("cat == null");
> }
> if (level == null) {
> throw new IllegalArgumentException("priority == null");
> }
>
> this.level = level;
> logger = log;
> bufLength = DEFAULT_BUFFER_LENGTH;
> buf = new byte[DEFAULT_BUFFER_LENGTH];
> count = 0;
> }
>
>
> /**
> * Closes this output stream and releases any system resources
> * associated with this stream. The general contract of
> * <code>close</code>
> * is that it closes the output stream. A closed stream cannot
>perform
> * output operations and cannot be reopened.
> */
> public void close() {
> flush();
> hasBeenClosed = true;
> }
>
>
> /**
> * Writes the specified byte to this output stream. The general
> * contract for <code>write</code> is that one byte is written
> * to the output stream. The byte to be written is the eight
> * low-order bits of the argument <code>b</code>. The 24
> * high-order bits of <code>b</code> are ignored.
> *
> * @param b the <code>byte</code> to write
> * @throws IOException if an I/O error occurs. In particular,
> * an <code>IOException</code> may be thrown if
>the
> * output stream has been closed.
> */
> public void write(final int b) throws IOException {
> if (hasBeenClosed) {
> throw new IOException("The stream has been closed.");
> }
>
> // would this be writing past the buffer?
> if (count == bufLength) {
> // grow the buffer
> final int newBufLength = bufLength + DEFAULT_BUFFER_LENGTH;
> final byte[] newBuf = new byte[newBufLength];
>
> System.arraycopy(buf, 0, newBuf, 0, bufLength);
>
> buf = newBuf;
> bufLength = newBufLength;
> }
>
> buf[count] = (byte) b;
> count++;
> }
>
>
> /**
> * Flushes this output stream and forces any buffered output bytes
> * to be written out. The general contract of <code>flush</code> is
> * that calling it is an indication that, if any bytes previously
> * written have been buffered by the implementation of the output
> * stream, such bytes should immediately be written to their
> * intended destination.
> */
> public void flush() {
> if (count == 0) {
> return;
> }
>
> // don't print out blank lines; flushing from PrintStream puts
>out these
> if (count == 1 && ((char) buf[0]) == '\n') {
> reset();
> return;
> }
>
> final byte[] theBytes = new byte[buf.length];
>
> System.arraycopy(buf, 0, theBytes, 0, count);
>
> logger.log(level, new String(theBytes));
>
> reset();
> }
>
>
> private void reset() {
> // not resetting the buffer -- assuming that if it grew then it
> // will likely grow similarly again
> count = 0;
> }
>
>}
>************************
>
>************************
>// remember STDERR
>PrintStream se = System.err;
>
>// make sure everything sent to System.err is logged
>System.setErr(new PrintStream(new
> LoggingOutputStream(Logger.getRootLogger(),
> Level.WARN), true));
>
>// make sure everything sent to System.out is also logged
>System.setOut(new PrintStream(new
> LoggingOutputStream(Logger.getRootLogger(),
> Level.INFO), true));
>***********************
>###########################################
>
>This message has been scanned by F-Secure Anti-Virus for Microsoft Exchange.
>For more information, connect to http://www.f-secure.com/
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
>For additional commands, e-mail: log4j-user-help@logging.apache.org
>
>
>
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org