2011-08-09 9 views
16

मेरे पास एक विधि है जो पैरामीटर के रूप में आउटपुटस्ट्रीम या राइटर का उपयोग करके प्रारंभ के बाद असीमित रूप से चलती है।लॉग 4 जे: मैं आउटपुटस्ट्रीम या राइटर को लॉगर के लेखक को रीडायरेक्ट कैसे करूं?

यह आउटपुटस्ट्रीम या राइटर के लिए रिकॉर्डिंग एडाप्टर के रूप में कार्य करता है (यह एक तृतीय पक्ष API है जिसे मैं नहीं बदल सकता)।

मैं उस विधि में लॉग 4 जे के आंतरिक आउटपुटस्ट्रीम या लेखक को कैसे पास कर सकता हूं?
... क्योंकि Log4J System.out और System.err निगलता है, मैं पहले उपयोग कर रहा था।

+2

तुम सिर्फ 'सौंपने लिखने आपका अपना OutputStream को लागू नहीं किया जा सका (...) लॉगर के लिए? – Rekin

+0

@ रीकिन बिल्कुल मैंने क्या किया! –

+0

Log4J कहने से आपका क्या मतलब है System.err? –

उत्तर

7

मेरा सुझाव है, तो आप अपना आउटपुटस्ट्रीम क्यों नहीं लिखते हैं ?! मैं तुम्हारे लिए एक लिखने वाला था, लेकिन मुझे नेट पर यह अच्छा उदाहरण मिला, इसे जांचें!

LogOutputStream.java

/* 
* Jacareto Copyright (c) 2002-2005 
* Applied Computer Science Research Group, Darmstadt University of 
* Technology, Institute of Mathematics & Computer Science, 
* Ludwigsburg University of Education, and Computer Based 
* Learning Research Group, Aachen University. All rights reserved. 
* 
* Jacareto is free software; you can redistribute it and/or 
* modify it under the terms of the GNU General Public 
* License as published by the Free Software Foundation; either 
* version 2 of the License, or (at your option) any later version. 
* 
* Jacareto is distributed in the hope that it will be useful, 
* but WITHOUT ANY WARRANTY; without even the implied warranty of 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
* General Public License for more details. 
* 
* You should have received a copy of the GNU General Public 
* License along with Jacareto; if not, write to the Free 
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
* 
*/ 

package jacareto.toolkit.log4j; 


import org.apache.log4j.Level; 
import org.apache.log4j.Logger; 

import java.io.OutputStream; 

/** 
* This class logs all bytes written to it as output stream with a specified logging level. 
* 
* @author <a href="mailto:[email protected]">Christian Spannagel</a> 
* @version 1.0 
*/ 
public class LogOutputStream extends OutputStream { 
    /** The logger where to log the written bytes. */ 
    private Logger logger; 

    /** The level. */ 
    private Level level; 

    /** The internal memory for the written bytes. */ 
    private String mem; 

    /** 
    * Creates a new log output stream which logs bytes to the specified logger with the specified 
    * level. 
    * 
    * @param logger the logger where to log the written bytes 
    * @param level the level 
    */ 
    public LogOutputStream (Logger logger, Level level) { 
     setLogger (logger); 
     setLevel (level); 
     mem = ""; 
    } 

    /** 
    * Sets the logger where to log the bytes. 
    * 
    * @param logger the logger 
    */ 
    public void setLogger (Logger logger) { 
     this.logger = logger; 
    } 

    /** 
    * Returns the logger. 
    * 
    * @return DOCUMENT ME! 
    */ 
    public Logger getLogger() { 
     return logger; 
    } 

    /** 
    * Sets the logging level. 
    * 
    * @param level DOCUMENT ME! 
    */ 
    public void setLevel (Level level) { 
     this.level = level; 
    } 

    /** 
    * Returns the logging level. 
    * 
    * @return DOCUMENT ME! 
    */ 
    public Level getLevel() { 
     return level; 
    } 

    /** 
    * Writes a byte to the output stream. This method flushes automatically at the end of a line. 
    * 
    * @param b DOCUMENT ME! 
    */ 
    public void write (int b) { 
     byte[] bytes = new byte[1]; 
     bytes[0] = (byte) (b & 0xff); 
     mem = mem + new String(bytes); 

     if (mem.endsWith ("\n")) { 
      mem = mem.substring (0, mem.length() - 1); 
      flush(); 
     } 
    } 

    /** 
    * Flushes the output stream. 
    */ 
    public void flush() { 
     logger.log (level, mem); 
     mem = ""; 
    } 
} 
+1

यह ढूंढने में खुशी हुई। मेरे उपयोग परिदृश्य में दिए गए 'LogOutputStream' में निम्न समस्या है, मुझे इसे ठीक करने की आवश्यकता है: 1. यह लॉगऑन पर निर्भर करता है जो कि मैं बदल गया कॉमन्स-लॉगिंग करता हूं और मैंने' logger.info() 'को हार्ड-कोड किया है क्योंकि कॉमन्स-लॉगिंग है कोई स्तर नहीं (जहां तक ​​मैं सेकंड में देखता हूं) 1. यह '\ n' होने के लिए नई लाइन मानता है जिसे मुझे' सिस्टम में बदलने की आवश्यकता है।getProperty ("line.separator") ' 1. चूंकि इसकी 'फ्लश()' जांच नहीं करती है कि' mem' खाली है या नहीं, तो आपको रैपिंग 'राइटर' कॉल 'फ्लश()' के बाद आउटपुट पर अतिरिक्त खाली रेखा मिलती है अंतिम 'println()' – hokr

4

स्रोत: http://sysgears.com/articles/how-to-redirect-stdout-and-stderr-writing-to-a-log4j-appender/

Blockquote

log4j बॉक्स से बाहर stdout और stderr संदेशों को पकड़ने के लिए अनुमति नहीं है। हालांकि, यदि आप तृतीय पक्ष घटकों का उपयोग कर रहे हैं और उन्हें लॉग ऑन करना है जो वे स्ट्रीम में फ़्लश करते हैं, तो आप लॉगिंग का समर्थन करने वाले कस्टम आउटपुट स्ट्रीम को थोड़ा सा चाल और कार्यान्वित कर सकते हैं।

यह जिम मूर द्वारा पहले ही किया जा चुका है (लॉग 4j स्रोत कोड में लॉगिंगऑटपुटस्ट्रीम देखें)। एकमात्र मुद्दा यह है कि जिममूर के लॉगिंगऑटपुटस्ट्रीम को org.apache.log4j.Category और org.apache.log4j की आवश्यकता होती है। प्राथमिकता जिसे अब आंशिक रूप से बहिष्कृत किया गया है।

यहाँ संशोधित किया गया है LoggingOutputStream बहिष्कृत तरीकों से बचा जाता है:

public class LoggingOutputStream extends OutputStream { 

    /** 
    * Default number of bytes in the buffer. 
    */ 
    private static final int DEFAULT_BUFFER_LENGTH = 2048; 

    /** 
    * Indicates stream state. 
    */ 
    private boolean hasBeenClosed = false; 

    /** 
    * Internal buffer where data is stored. 
    */ 
    private byte[] buf; 

    /** 
    * The number of valid bytes in the buffer. 
    */ 
    private int count; 

    /** 
    * Remembers the size of the buffer. 
    */ 
    private int curBufLength; 

    /** 
    * The logger to write to. 
    */ 
    private Logger log; 

    /** 
    * The log level. 
    */ 
    private Level level; 

    /** 
    * Creates the Logging instance to flush to the given logger. 
    * 
    * @param log   the Logger to write to 
    * @param level  the log level 
    * @throws IllegalArgumentException in case if one of arguments 
    *         is null. 
    */ 
    public LoggingOutputStream(final Logger log, 
           final Level level) 
      throws IllegalArgumentException { 
     if (log == null || level == null) { 
      throw new IllegalArgumentException(
        "Logger or log level must be not null"); 
     } 
     this.log = log; 
     this.level = level; 
     curBufLength = DEFAULT_BUFFER_LENGTH; 
     buf = new byte[curBufLength]; 
     count = 0; 
    } 

    /** 
    * Writes the specified byte to this output stream. 
    * 
    * @param b the byte to write 
    * @throws IOException if an I/O error occurs. 
    */ 
    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 == curBufLength) { 
      // grow the buffer 
      final int newBufLength = curBufLength + 
        DEFAULT_BUFFER_LENGTH; 
      final byte[] newBuf = new byte[newBufLength]; 
      System.arraycopy(buf, 0, newBuf, 0, curBufLength); 
      buf = newBuf; 
      curBufLength = newBufLength; 
     } 

     buf[count] = (byte) b; 
     count++; 
    } 

    /** 
    * Flushes this output stream and forces any buffered output 
    * bytes to be written out. 
    */ 
    public void flush() { 
     if (count == 0) { 
      return; 
     } 
     final byte[] bytes = new byte[count]; 
     System.arraycopy(buf, 0, bytes, 0, count); 
     String str = new String(bytes); 
     log.log(level, str); 
     count = 0; 
    } 

    /** 
    * Closes this output stream and releases any system resources 
    * associated with this stream. 
    */ 
    public void close() { 
     flush(); 
     hasBeenClosed = true; 
    } 
} 

अब आप उन संदेशों को stderr को प्लावित या निम्नलिखित तरीके से stdout रहे हैं पकड़ कर सकते हैं:

System.setErr(new PrintStream(new LoggingOutputStream(
     Logger.getLogger("outLog"), Level.ERROR))); 

log4j.properties विन्यास:

log4j.logger.outLog=error, out_log 

log4j.appender.out_log=org.apache.log4j.RollingFileAppender 
log4j.appender.out_log.file=/logs/error.log 
log4j.appender.out_log.MaxFileSize=10MB 
log4j.appender.out_log.threshold=error 

दिमित्री पावलेंको,,210 SysGears

Blockquote

0

के बाद से एक लेखक कि Log4J करने के लिए निर्देशित की पिछले उदाहरण चला गया मृत: http://www.opensource.apple.com/source/JBoss/JBoss-737/jboss-all/common/src/main/org/jboss/logging/util/LoggerWriter.java

+0

जबकि यह सैद्धांतिक रूप से प्रश्न का उत्तर दे सकता है, [यह बेहतर होगा] (// meta.stackoverflow.com/q/8259) यहां उत्तर के आवश्यक हिस्सों को शामिल करने के लिए, और संदर्भ के लिए लिंक प्रदान करें । –

संबंधित मुद्दे