【问题标题】:Logback - get method nameLogback - 获取方法名称
【发布时间】:2014-06-20 13:38:06
【问题描述】:

我们目前正在从 log4j 迁移到 Logback,但在获取触发日志的“原始”方法名称时遇到问题。

我称它为“原始”,因为我们有一个集中式记录器类(用于隐藏和操作某些日志),而日志中显示的是该集中式类的方法名称。

在 log4j 中,我们能够正确获取“原始”方法名称。

Logback 能不能获取到?

记录器参数

log4j

<param name="ConversionPattern" value="%d{dd-MM-yyyy HH:mm:ss,SSS} %5p [%F] - %M() - %m%n"/>

回退

<pattern>%d{"dd-MM-yyyy HH:mm:ss,SSS"} %-5level [%logger - %M] - %msg%n</pattern>

结果:(方法名 - 类名)

log4j

doLogTester1 - a.Tester1            
doLogTester2 - b.Tester2            
doLogTester1 - a.Tester1            
doLogTester2 - b.Tester2            

回退

processLog - a.Tester1              
processLog - b.Tester2              
processLog - a.Tester1              
processLog - b.Tester2              

编辑 - 完整示例

Main.java

public class Main
{
private static final LoggerCommon logger = new LoggerCommon(Main.class);

    public static void main(String[] args)
    {
        logger.doLog("I'm on the Main class in the main method");
    }
}

LoggerCommon

log4j

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

public class LoggerCommon
{
    private static Logger logger;

    public LoggerCommon(Class<?> c)
    {
        logger = Logger.getLogger(c);
    }

    public void doLog(String message)
    {
        logger.log(LoggerCommon.class.getName(), Level.INFO, message, null);
    }
}

回退

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoggerCommon
{
    private Logger logger;

    public LoggerCommon(Class<?> c)
    {
        logger = LoggerFactory.getLogger(c);
    }

    public void doLog(String message)
    {
        logger.info(message);
    }
}

配置的

log4j

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <appender name="CA" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%M - %F - %m%n"/>
        </layout>
    </appender>
    <root>
        <level value="debug"/>
        <appender-ref ref="CA"/>
    </root>
</log4j:configuration>

回退

<configuration>
    <appender name="CA" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%M - %logger - %msg %n</pattern>
        </encoder>
    </appender>
    <root level="TRACE">
        <appender-ref ref="CA"/>
    </root>
</configuration>

【问题讨论】:

  • 在 Log4j 中,您使用的是 %M,它返回调用方法。我看不出您的 Log4j 如何比 Logback 更好地应对您的集中式日志记录类。这种集中式日志记录类是新事物吗?
  • 不,集中记录器已经使用了很长时间了。当我在 logback 中看到这种行为时,我检查了一些 log4j 日志,看看它是否也发生了,但没有。
  • log4j 文档警告不要使用 M,因为“生成调用方位置信息非常慢,应该避免,除非执行速度不是问题。”过去,当我需要用于记录消息的方法名称时,我会将方法名称包含在方法的文本中。例如,从 main 方法记录:logger.info("main(); blah blah blah");
  • 请更新您的问题以提供一个小示例代码,该代码将在 Log4j 中打印正确的方法名称,在 Logback 中打印错误的方法名称。我仍然不相信你会用 Log4j 实现它。
  • 按要求添加了示例

标签: java logging log4j logback


【解决方案1】:

您需要确保日志事件中的“调用者数据”正确无误。

这些选项之一可能会起作用:

在您的记录器包装器中调用 ILoggingEvent::getCallerData(),以确保尽早收集调用者数据。

也许您可以在集中式记录器中装饰事件以欺骗调用者数据 ILoggingEvent::getCallerData() 调用?

或者派生调用者数据,然后将 ILoggingEvent 转换为 LoggingEvent,并与你调用 setCallerData()。

【讨论】:

  • 我是 logback 的新手,我不明白你的意思。你能举个例子吗?提前致谢。
  • 看看logback源码,看看AsyncAppender是怎么做的。
  • 刚刚查看了 AsyncAppender.java,它有 4 个方法:boolean isDiscardable(ILoggingEvent event)、void preprocess(ILoggingEvent eventObject)、boolean isIncludeCallerData()、void setIncludeCallerData(boolean includeCallerData),我仍然没有了解如何将其包含到我的 LoggerCommon.java
  • 大部分逻辑都在基类中。
  • 顺便说一句,真的需要拥有自己的日志包装器。如果您可以转移到正常的日志记录,那就容易多了。
【解决方案2】:

用这个解决了:

methodName = stackTrace[xxxx].getMethodName();

不完美,因为 xxxx 因服务器而异,但这是我们能找到的最好的

【讨论】:

    猜你喜欢
    • 2015-11-02
    • 1970-01-01
    • 1970-01-01
    • 2016-03-13
    • 2015-10-01
    • 1970-01-01
    • 2011-10-09
    • 2012-10-25
    • 2011-11-25
    相关资源
    最近更新 更多