【问题标题】:log4j add prefix to all messages from one abstract classlog4j 为来自一个抽象类的所有消息添加前缀
【发布时间】:2016-08-01 18:36:50
【问题描述】:

我正在尝试使用 log4j 为所有日志命令添加前缀。

以前我一直在所有类前面使用@Slf4j,但是现在我需要给所有消息添加某些前缀,所以这不再可能了。

我的班级结构如下:

abstract class MyAbstractClass {
    protected final MyLogger log;
    MyAbstractClass(String foodType) {
        this.log = new MyLogger(Logger.getLogger(this.getClass(), foodType));
    }
}

class MyClass1 extends MyAbstractClass {
    MyClass1(String foodType) { super(foodType); }   
    public static void myMethod1() {
        log.info("hehe");
    } 
}

class MyClass2 extends MyAbstractClass {
    MyClass2(String foodType) { super(foodType); }   
    public static void myMethod2() {
        log.info("hohohoho");
    } 
}

/* MyLogger.java */

@Slf4j
public class MyLogger  {
    private final Logger LOGGER;
    private String PREFIX;
    public MyLogger(Logger logger, String foodType) {
        LOGGER = logger;
        PREFIX = foodType + ": ";
    }

    public void info(final String str) {
        log.info(PREFIX + str);
    }

    public void warn(final String str) {
        log.warn(PREFIX + str);
    }

    public void debug(final String str) { log.debug(PREFIX + str); }

    public void error(final String str) {
        log.error(PREFIX + str);
    }

    public void error(final String str, Exception e) {
        log.error(PREFIX + str, e);
    }
    ...

    // i know.. it's so inconvenient because I have to override all the methods that I want to use from log4j Logger. I wish there is an alternative.

}

如果我要这样做,

public static void main() {
    MyClass1 c1 = new MyClass1("burger");
    MyClass2 c2 = new MyClass2("pizza");
    c1.myMethod1();
    c2.myMethod2();
}

我会得到这样的东西。

/* console */
[INFO] MyLogger#info - burger: hehe
[INFO] MyLogger#info - pizza: hohoho

但是,我想得到这样的东西,以便能够追踪它的确切来源(原来的 Log4j 就是这样做的)。

/* console */
[INFO] MyClass1#MyMethod1 - burger: hehe
[INFO] MyClass2#MyMethod2 - pizza: hohoho

我有办法做到这一点吗?

谢谢!

【问题讨论】:

  • Rathan 包装了log4j 记录器,你为什么不做类似log.info(foodType + ": hehe" ) 的事情?另外,我看不到为[INFO] MyLogger#info 生成#info 的位置。它是否在PatternLayout 中定义?如果是这样,也发布。
  • @bradimus 我可以使用 log.info(food type + ":" + msg) 方法,但是当我有很多日志调用时,这是非常重复的。我只是想要一种更干净的方式来做到这一点哈哈。另外,我不知道 PatternLayout,你能提供更多关于这个的信息吗?生成 #info 是因为 log4j 日志调用是从 MyLogger.info 进行的。 log4j 似乎正在跟踪其对 MyLogger 函数的日志调用,而不是调用日志函数的实际方法(MyClass1.myMethod1 和 MyClass2.myMethod2)
  • @bradimus 这里是完整的模式布局(我修改了一下,仍然无法打印汉堡和披萨):%d{yyyy-MM-dd HH:mm:ss,SSS} [% -5p] %c{1}#%M - %m%n
  • 问题解决了吗?使用上面的模式,我得到了正确的输出。

标签: java log4j slf4j


【解决方案1】:

我通过使用 MDC 模式解决了这个问题。我不再需要 MyLogger 类。我可以使用 Log4j 的 Logger 类。

你可以这样做

abstract class MyAbstractClass {
    protected final Logger log;
    MyAbstractClass(String foodType) {
        MDC.put("myfood", foodType);
        this.log = LoggerFactory.getLogger(getClass()));
    }
}

在模式中,您可以添加 %X{myfood} 以访问您设置的变量:)

在此处了解有关 MDC 的更多信息:http://logback.qos.ch/manual/mdc.html

【讨论】:

    【解决方案2】:

    如果你使用PatternLayout(你应该),你可以通过将模式定义为

    %C{1}:%M - %m%n
    

    【讨论】:

    • 你能扩展一下吗?我不太了解 PatternLayout
    • @Blee 这里是一个很好的布局教程。 logging.apache.org/log4j/2.x/manual/layouts.html
    • 这不起作用。仍然打印 MyLogger#info。这是我制作的模式: %d{yyyy-MM-dd HH:mm:ss,SSS} [%-5p] %c{1}#%M - %m%n
    • 我还应该补充一点,我希望能够控制 XML 中各个类的日志记录级别。目前,在我的 log4j.xml 中,我只有这个:<logger name="com.logger.MyLogger"> <level value="INFO" /> </logger> 而且我无法控制各个类(MyClass1,MyClass2)
    • @Blee 这是一个资本C 在你的模式中是一个小的c
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多