2012-06-25 22 views
21

System.out/err.println çıkışlarını slf4j'ye yeniden yönlendirmem gerekiyordu.Yönlendirme System.out ve System.err için slf4j

bu düzgün giriş yapmak için yol olmadığını biliyorum ama log4j için LoggingOutputStream kullanan sorun çözüldü

+0

Hızlı googling bana cevap değil, aynı zamanda ilginç görünüyor bu bağlantıyı verdi: http://projects.lidalia.org.uk/sysout-over-slf4j/index.html – remi

cevap

13

(OpenEJB başlangıçta itibaren) bu gibi görünüyor.

sysout-aşırı slf4j modülü tam sınıf adıyla kaydedicisini tanımlanan bir SLF4J için System.out ve System.err tüm aramaları yönlendirmek için bir olanak sağlar ki burada System.out.println (veya benzerleri), yapılandırılabilir seviyelerde yapıldı.

Maven kullanarak değil, download kavanoz ve Sınıfyolu eklemek edin. uygulamanın başlangıcında Sonra

<dependency> 
    <groupId>uk.org.lidalia</groupId> 
    <artifactId>sysout-over-slf4j</artifactId> 
    <version>1.0.2</version> 
</dependency> 

, call:

Alternatif olarak, bir Maven bağımlılık olarak ekleyin

SysOutOverSLF4J.sendSystemOutAndErrToSLF4J(); 
o konuda
+1

Görünüşe göre sysout-ver-slf4j slf4j'ye bağlı 1.6.0 Sınıf yolumuza eklemeyi denedim ve slf4j'i kullandığımız için derleme zamanı hataları aldık 1.7.7 – pranahata

+1

İşler mükemmel derecede iyi (slf4j 1.7.13) – Andrey

+0

Yeni yanıt veren kişi olarak kabul edildi ! Birinden bir kod pratiği yerine bir ana kütüphaneye sahip olmak daha iyidir. Ama kütüphaneyi test etmediğimi söylemem gerek! – itshorty

19

System.out için kaydeder harici kütüphane vardır ve bunu biraz modifiye slf4j için biraz.

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; 
    } 
} 
} 

Şimdi sıra uygulamanın başında SysStreamsLogger.bindSystemStreams() arayarak Sytem.out/err yönlendirmek mümkündür. Sen sysout-over-slf4j kullanabilirsiniz

açılıyor Çıktı

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/ 
+0

Bunu kullandım, ancak bir vm -DREDIRECT_SYSLOGS = true almak için bir System.getProperty() ekledik, böylece Eclipse hala hataları konsola kaydeder. beklenildiği gibi. Sadece günlükleri bir üretim ortamında yönlendiriyorum. – Kieveli

+0

N1, ancak dişli güvenli değil. –

+0

Bunu paylaştığınız için teşekkürler .. Hata akışını günlüğe kaydetmeyi başardım. – Buminda