0

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

我正在使用 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 中写入一个日志条目,但在给定日志文件中写入多个日志条目。

感谢您的任何回答!

4

1 回答 1

3

它会将 de logline 两次写入该文件,因为在 de LogBack 配置中,该文件已配置,并且您将其再次添加到特定 Logger。而且由于日志框架在写入哪个文件时是愚蠢的,因此它会两次写入您的日志语句。

查看代码,我看到您为每个日志语句创建了 2 次 FileAppender。有点浪费内存。如果程序发生了什么导致它向您的日志文件发送垃圾邮件,您可能会在 linux 环境中用完文件描述符。如果我是你,我应该放弃这门课,直接从你的课开始使用 SLF4J。

于 2013-11-09T20:05:14.813 回答