Avevo bisogno di reindirizzare gli output di System.out/err.println a slf4j.Reindirizzare System.out e System.err su slf4j
So che questo non è il modo di fare la registrazione correttamente ma c'è una libreria esterna, che registra a System.out
Avevo bisogno di reindirizzare gli output di System.out/err.println a slf4j.Reindirizzare System.out e System.err su slf4j
So che questo non è il modo di fare la registrazione correttamente ma c'è una libreria esterna, che registra a System.out
È possibile utilizzare sysout-over-slf4j.
Il modulo sysout-over-slf4j consente a un utente di reindirizzare tutte le chiamate a System.out e System.err a uno SLF4J logger definito con il nome della classe completo in cui lo System.out.println (o simili) è stata effettuata una chiamata, a livelli configurabili.
Se siete non usando Maven, download il vaso e aggiungerlo al classpath.
In alternativa, aggiungerlo come una dipendenza Maven:
<dependency>
<groupId>uk.org.lidalia</groupId>
<artifactId>sysout-over-slf4j</artifactId>
<version>1.0.2</version>
</dependency>
Poi all'avvio dell'applicazione, call:
SysOutOverSLF4J.sendSystemOutAndErrToSLF4J();
Sembra che sysout-ver-slf4j dipenda da slf4j 1.6.0 Ho provato ad aggiungerlo al nostro classpath e abbiamo errori di compilazione poiché stiamo usando slf4j 1.7.7 – pranahata
Funziona perfettamente (slf4j 1.7.13) – Andrey
Accettato come nuovo risponditore ! È meglio avere una biblioteca controllata invece di un codice di codice da qualcuno. Ma devo dire che non ho testato la libreria! – itshorty
ho risolto il problema utilizzando il LoggingOutputStream per log4j e modificato un po ' bit per slf4j.
import java.io.IOException;
import java.io.PrintStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SysStreamsLogger {
private static Logger sysOutLogger = LoggerFactory.getLogger("SYSOUT");
private static Logger sysErrLogger = LoggerFactory.getLogger("SYSERR");
public static final PrintStream sysout = System.out;
public static final PrintStream syserr = System.err;
protected static final String LINE_SEPERATOR = System.getProperty("line.separator");
public static void bindSystemStreams() {
// Enable autoflush
System.setOut(new PrintStream(new LoggingOutputStream(sysOutLogger, false), true));
System.setErr(new PrintStream(new LoggingOutputStream(sysErrLogger, true), true));
}
public static void unbindSystemStreams() {
System.setOut(sysout);
System.setErr(syserr);
}
private static class LoggingOutputStream extends java.io.OutputStream {
protected Logger log;
protected boolean isError;
/**
* 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;
private LoggingOutputStream() {
// illegal
}
/**
* Creates the LoggingOutputStream to flush to the given Category.
*
* @param log
* the Logger to write to
*
* @param isError
* the if true write to error, else info
*
* @exception IllegalArgumentException
* if cat == null or priority == null
*/
public LoggingOutputStream(Logger log, boolean isError) throws IllegalArgumentException {
if (log == null) {
throw new IllegalArgumentException("log == null");
}
this.isError = isError;
this.log = 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.
*/
@Override
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
*/
@Override
public void write(final int b) throws IOException {
if (hasBeenClosed) {
throw new IOException("The stream has been closed.");
}
// don't log nulls
if (b == 0) {
return;
}
// 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.
*/
@Override
public void flush() {
if (count == 0) {
return;
}
// don't print out blank lines; flushing from PrintStream puts out
// these
if (count == LINE_SEPERATOR.length()) {
if (((char) buf[0]) == LINE_SEPERATOR.charAt(0) && ((count == 1) || // <-
// Unix
// &
// Mac,
// ->
// Windows
((count == 2) && ((char) buf[1]) == LINE_SEPERATOR.charAt(1)))) {
reset();
return;
}
}
final byte[] theBytes = new byte[count];
System.arraycopy(buf, 0, theBytes, 0, count);
if (isError) {
log.error(new String(theBytes));
} else {
log.info(new String(theBytes));
}
reset();
}
private void reset() {
// not resetting the buffer -- assuming that if it grew that it
// will likely grow similarly again
count = 0;
}
}
}
Ora è possibile reindirizzare Sytem.out/err chiamando SysStreamsLogger.bindSystemStreams()
al all'inizio dell'applicazione.
registrazione dell'output assomiglia a questo (da avvio OpenEJB)
2012-06-27 13:44:12,792 INFO [main:] SYSOUT:181 - Apache OpenEJB 3.1.4 build: 20101112-03:32
2012-06-27 13:44:12,793 INFO [main:] SYSOUT:181 - http://openejb.apache.org/
Utilizzato questo, ma ha aggiunto un System.getProperty() per afferrare un vm -DREDIRECT_SYSLOGS = true in modo che Eclipse registri ancora errori nella sua console come previsto. Ho solo reindirizzare i registri in un ambiente di produzione. – Kieveli
N1, ma non thread-safe. –
Grazie per aver condiviso questo .. Sono riuscito a reindirizzare il flusso di errori per il log. – Buminda
googling rapida sulla questione mi ha dato la sua risposta, ma anche questo link che sembra interessante: http://projects.lidalia.org.uk/sysout-over-slf4j/index.html – remi