73 votes

log4j rediriger stdout vers DailyRollingFileAppender

J'ai une application java qui utilise log4j.

Config:

log4j.rootLogger=info, file

log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File=${user.home}/logs/app.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d [%t] %c %p %m%n

Donc, le journal de toutes les déclarations sont correctement ajouté au fichier, mais je suis de perdre stdout et stderr. Comment puis-je rediriger exception des traces de pile et sysouts pour le quotidien roulé fichier ?

110voto

Michael S. Points 584
// I set up a ConsoleAppender in Log4J to format Stdout/Stderr
log4j.rootLogger=DEBUG, CONSOLE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[%t] %-5p %c - %m%n


// And I call this StdOutErrLog.tieSystemOutAndErrToLog() on startup

public class StdOutErrLog {

    private static final Logger logger = Logger.getLogger(StdOutErrLog.class);

    public static void tieSystemOutAndErrToLog() {
        System.setOut(createLoggingProxy(System.out));
        System.setErr(createLoggingProxy(System.err));
    }

    public static PrintStream createLoggingProxy(final PrintStream realPrintStream) {
        return new PrintStream(realPrintStream) {
            public void print(final String string) {
                realPrintStream.print(string);
                logger.info(string);
            }
        };
    }
}

13voto

Dario Points 745

J'ai pris l'idée de Michael S., mais comme mentionné dans un autre commentaire, il a quelques problèmes: il ne rend pas compte de tout, et il affiche des lignes vides.

Aussi je voulais séparer System.out et System.err, de sorte qu' System.out obtient connecté avec le niveau de journal 'INFO' et System.err obtient connecté avec 'ERROR' (ou 'WARN' si vous le souhaitez).

Donc, c'est ma solution: D'abord une classe qui étend la classe OutputStream (il est plus facile de remplacer toutes les méthodes d' OutputStream que PrintStream). Il se connecte avec un certain niveau de journal et aussi des copies de tout autre OutputStream. Et aussi il détecte le "vide" des chaînes de caractères (contenant des espaces uniquement) et n'enregistre pas.

import java.io.IOException;
import java.io.OutputStream;

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

public class LoggerStream extends OutputStream
{
private final Logger logger;
private final Level logLevel;
private final OutputStream outputStream;

public LoggerStream(Logger logger, Level logLevel, OutputStream outputStream)
{
    super();

    this.logger = logger;
    this.logLevel = logLevel;
    this.outputStream = outputStream;
}

@Override
public void write(byte[] b) throws IOException
{
    outputStream.write(b);
    String string = new String(b);
    if (!string.trim().isEmpty())
        logger.log(logLevel, string);
}

@Override
public void write(byte[] b, int off, int len) throws IOException
{
    outputStream.write(b, off, len);
    String string = new String(b, off, len);
    if (!string.trim().isEmpty())
        logger.log(logLevel, string);
}

@Override
public void write(int b) throws IOException
{
    outputStream.write(b);
    String string = String.valueOf((char) b);
    if (!string.trim().isEmpty())
        logger.log(logLevel, string);
}
}

Et puis un utilitaire très simple classe pour définir out et err:

import java.io.PrintStream;

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

public class OutErrLogger
{
public static void setOutAndErrToLog()
{
    setOutToLog();
    setErrToLog();
}

public static void setOutToLog()
{
    System.setOut(new PrintStream(new LoggerStream(Logger.getLogger("out"), Level.INFO, System.out)));
}

public static void setErrToLog()
{
    System.setErr(new PrintStream(new LoggerStream(Logger.getLogger("err"), Level.ERROR, System.err)));
}

}

12voto

Fizou Points 61

Dans Skaffman code : Pour supprimer les lignes vides dans log4j journaux, il suffit d'ajouter "println" méthode de PrintStream de createLoggingProxy

public static PrintStream createLoggingProxy(final PrintStream realPrintStream) {
    return new PrintStream(realPrintStream) {
        public void print(final String string) {
            logger.warn(string);
        }
        public void println(final String string) {
            logger.warn(string);
        }
    };
}

6voto

Juha Syrjälä Points 11475

Si vous utilisez un serveur d'application, conteneur de servlet ou quelque chose de similaire, voir kgiannakakis de réponse.

Pour les applications autonomes voir ce. Vous pouvez reassing stdin, stdout et stderr à l'aide de java.lang.Système de classe. En gros, vous créez un nouveau sous-classe PrintStream et de définir cette instance de Système..

Quelque chose le long de ces lignes au début de votre application (non testé).

// PrintStream object that prints stuff to log4j logger
public class Log4jStream extends PrintStream {
      public void write(byte buf[], int off, int len) {
        try {
           // write stuff to Log4J logger
        } catch (Exception e) {
       }
    }
}

// reassign standard output to go to log4j
System.setOut(new Log4jStream());

2voto

Brian Agnew Points 143181

Je suppose que vous êtes journalisation stacktraces via e.printStackTrace() ? Vous pouvez passer un objet d'exception dans le Log4j méthodes de journalisation et de ceux qui apparaissent dans votre journal (voir l'Enregistreur.erreur(Object obj, Throwable t))

Notez que vous pouvez changer de Système.et du Système.euh pour un autre PrintStream qui redirige vers la Log4j. Que serait un simple changement et de vous sauver la conversion de tous vos System.out.println() des déclarations.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X