繁体   English   中英

Logback / SLF4J File Appender多次写入日志条目

[英]Logback/SLF4J File Appender writes log entry multiple times

我有一个用于记录的帮助程序类,该类使用slf4j创建一个loggier并写入日志文件。

我正在使用FileAppender将日志写入定义的文件中。

问题在于,此FileAppender将每条日志行多次写入定义的文件,而在glassfish服务器的server.log中仅写入一次。

这是我的班级样子:

package de.mycompany.framework.jframework.logging;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.FileAppender;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.slf4j.LoggerFactory;

/**
 * Logger
 * @author Marc Vollmer
 */
public class Logger {
  /**
   * Log Level
   * Default: OFF
   */
  private Level level = Level.OFF;

  /**
   * Constructor
   */
  public Logger() {
    String sLogLevel = "OFF";
    try {
      sLogLevel = (String)new InitialContext().lookup("jfw/LogLevel");
    } catch (NamingException ex) {

    }
    switch(sLogLevel.toUpperCase()) {
      case "DEBUG":
        level = Level.DEBUG;
        break;
      case "INFO":
        level = Level.INFO;
        break;
      case "TRACE":
        level = Level.TRACE;
        break;
      case "WARN":
        level = Level.WARN;
        break;
      case "ERROR":
        level = Level.ERROR;
        break;
      case "ALL":
        level = Level.ALL;
        break;
      default:
        level = Level.OFF;
        break;
    }
  }

  /**
   * Set the Log Level
   * 
   * @param level Log Level
   */
  public void setLevel(Level level) {
    this.level = level;
  }

  /**
   * Get the Log Level
   * 
   * @return Log Level
   */
  public Level getLevel() {
    return level;
  }

  /**
   * Get Classname from Package Path
   * 
   * @param sPackage Package Path
   * @return Class name
   */
  private String getClassFromPackage(String sPackage) {
    if (sPackage.contains(".")) {
      return sPackage.split("\\.")[(sPackage.split("\\.").length-1)];
    } else {
      return sPackage;
    }
  }

  /**
   * Is the class ignored?
   * 
   * @param sPackString Package PAth
   * @return true if ignored, false if not
   */
  private boolean isIgnoredClass(String sPackString) {
    switch (getClassFromPackage(sPackString)) {
      case "Logger":
      case "Thread":
        return true;
      default:
        return false;
    }
  }

  /**
   * Get the Logger
   * 
   * @return SLF4J Logger
   */
  private org.slf4j.Logger getLogger() {
    String sName;
    StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
    int i = 0;
    StackTraceElement e = stacktrace[i]; // TODO: Adjust after tests
    while (isIgnoredClass(e.getClassName())) {
      e = stacktrace[++i];
    }
    sName = getClassFromPackage(e.getClassName()) + "." + e.getMethodName();
    LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory();
    ch.qos.logback.classic.Logger logger = lc.getLogger(sName);
    logger.addAppender(getFileAppender(lc));
    logger.setLevel(level);
    return logger;
  }

  /**
   * Create a file appender
   * 
   * @param lc Logger Context
   * @return File Appender
   */
  private FileAppender<ILoggingEvent> getFileAppender(LoggerContext lc) {
    FileAppender<ILoggingEvent> fa = new FileAppender<>();
    fa.setContext(lc);
    fa.setName("FILE");
    try {
      fa.setFile((String)new InitialContext().lookup("jfw/LogFile"));
    } catch (NamingException ex) {
      fa.setFile("../logs/jfw.log");
    }
    PatternLayoutEncoder pl = new PatternLayoutEncoder();
    pl.setContext(lc);
    try {
      pl.setPattern((String)new InitialContext().lookup("jfw/LogPattern"));
    } catch (NamingException ex) {
      pl.setPattern("%d{dd.MM.yyyy HH:mm:ss.SSS} [%-5(%level)] [%-50.50(%C{0}.%M)] %m%n%xEx");
    }
    pl.start();
    fa.setEncoder(pl);
    fa.start();
    return fa;
  }

  /**
   * Trace Message
   * 
   * @param sMsg Log Message
   */
  public void trace(String sMsg) {
    if (getLogger().isTraceEnabled()) {
      getLogger().trace(sMsg);
    }
  }

  /**
   * Trace Message
   * 
   * @param sMsg Log Message
   * @param throwable Throwable
   */
  public void trace(String sMsg, Throwable throwable) {
    if (getLogger().isTraceEnabled()) {
      getLogger().trace(sMsg, throwable);
    }
  }

  /**
   * Debug Message
   * 
   * @param sMsg Log Message
   */
  public void debug(String sMsg) {
    if (getLogger().isDebugEnabled()) {
      getLogger().debug(sMsg);
    }
  }

  /**
   * Debug Message
   * 
   * @param sMsg Log Message
   * @param throwable Throwable
   */
  public void debug(String sMsg, Throwable throwable) {
    if (getLogger().isDebugEnabled()) {
      getLogger().debug(sMsg, throwable);
    }
  }

  /**
   * Info Message
   * 
   * @param sMsg Log Message
   */
  public void info(String sMsg) {
    if (getLogger().isInfoEnabled()) {
      getLogger().info(sMsg);
    }
  }

  /**
   * Info Message
   * 
   * @param sMsg Log Message
   * @param throwable Throwable
   */
  public void info(String sMsg, Throwable throwable) {
    if (getLogger().isInfoEnabled()) {
      getLogger().info(sMsg, throwable);
    }
  }

  /**
   * Warn Message
   * 
   * @param sMsg Log Message
   */
  public void warn(String sMsg) {
    if (getLogger().isWarnEnabled()) {
      getLogger().warn(sMsg);
    }
  }

  /**
   * Warn Message
   * 
   * @param sMsg Log Message
   * @param throwable Throwable
   */
  public void warn(String sMsg, Throwable throwable) {
    if (getLogger().isWarnEnabled()) {
      getLogger().warn(sMsg, throwable);
    }
  }

  /**
   * Error Message
   * 
   * @param sMsg Log Message
   */
  public void error(String sMsg) {
    if (getLogger().isErrorEnabled()) {
      getLogger().error(sMsg);
    }
  }

  /**
   * Error Message
   * 
   * @param sMsg Log Message
   * @param throwable Throwable
   */
  public void error(String sMsg, Throwable throwable) {
    if (getLogger().isErrorEnabled()) {
      getLogger().error(sMsg, throwable);
    }
  }
}

我使用System.out.println对控制台进行了一些调试输出,例如.trace仅被调用一次,在server.log中写入一个日志条目,但在给定的日志文件中写入多个日志条目。

感谢您的回答!

它将两次在日志行中写入该文件,因为在LogBack配置中已配置了文件,然后将其再次添加到特定的Logger中。 而且由于日志框架笨拙,无法写入哪个文件,因此它将两次写入您的日志语句。

查看代码,我看到您为每个日志语句创建了2次FileAppender。 有点浪费内存。 并且,如果该程序发生了某些事件,导致其将垃圾邮件发送到您的日志文件中,则您可能会在Linux环境中用尽文件描述符。 如果您是我,我应该放弃此类,直接从您的课堂开始使用SLF4J。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM