Logback — получить имя метода

#java #logging #log4j #logback

#java #ведение журнала #log4j #logback

Вопрос:

В настоящее время мы переходим с log4j на Logback, но у нас возникают проблемы с получением «оригинального» имени метода, который вызвал журнал.

Я называю это «original», потому что у нас есть централизованный класс logger (для скрытия и управления определенными журналами), и в журналах отображается имя метода из этого централизованного класса.

В log4j мы смогли правильно получить «исходное» имя метода.

Может ли Logback получить его или нет?

Параметры регистраторов:

log4j

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

Logback

 <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            
 

Logback

 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);
    }
}
 

logback

 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>
 

logback

 <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>
 

Комментарии:

1. В Log4j, который вы используете %M , который возвращает вызывающий метод. Я не понимаю, как ваш Log4j мог бы справиться с вашим централизованным классом ведения журнала лучше, чем Logback. Является ли этот централизованный класс ведения журнала чем-то новым?

2. Нет, централизованный регистратор использовался уже давно. Когда я увидел это поведение в logback, я проверил некоторые журналы log4j, чтобы узнать, происходит ли это также, но нет.

3. Документы log4j предостерегают от использования M, поскольку «Генерация информации о местоположении вызывающего абонента выполняется чрезвычайно медленно, и ее следует избегать, если скорость выполнения не является проблемой». В прошлом, когда мне требовалось имя метода, из которого я регистрирую сообщение, я включал имя метода в текст метода. например, ведение журнала из основного метода: logger.info («main(); бла-бла-бла»);

4. Пожалуйста, обновите свой вопрос, чтобы предоставить небольшой пример кода, который выведет правильное имя метода в Log4j и неправильное имя метода в Logback. Я все еще не уверен, что вы достигнете этого с помощью Log4j.

5. В соответствии с запросом только что добавлен пример

Ответ №1:

Вам нужно убедиться, что «данные вызывающего абонента» указаны правильно в событии журнала.

Вероятно, один из этих вариантов будет работать:

Вызовите ILoggingEvent::getCallerData() в оболочке вашего регистратора, чтобы убедиться, что данные вызывающего абонента собраны заранее.

Может быть, вы можете украсить событие в своем централизованном регистраторе, чтобы подделать данные вызывающего абонента ILoggingEvent::getCallerData() вызов?

Или извлеките данные вызывающего абонента, затем преобразуйте ILoggingEvent в LoggingEvent и вызовите setCallerData() вместе с вами.

Комментарии:

1. Я новичок в logback и не понимаю, что вы под этим подразумеваете. Не могли бы вы привести пример? Заранее спасибо.

2. Взгляните на исходный код logback, посмотрите, как это делает AsyncAppender.

3. Просто посмотрел в AsyncAppender.java и это 4 метода: boolean isDiscardable(событие ILoggingEvent), void preprocess(событие ILoggingEvent EventObject), boolean isIncludeCallerData(), void setIncludeCallerData(логическое значение includeCallerData), и я до сих пор не понимаю, как я могу включить его в свой LoggerCommon.java

4. Большая часть логики находится в базовом классе.

5. Кстати, действительно ли нужно иметь собственную оболочку журнала. Если вы можете просто перейти к обычному ведению журнала, тогда это намного проще.

Ответ №2:

Решил это с помощью этого:

 methodName = stackTrace[xxxx].getMethodName();
 

Не идеально, поскольку xxxx зависит от сервера, но это лучшее, что мы смогли найти