Печать «исходного» класса в операторе журнала с помощью оболочки log4j - PullRequest
7 голосов
/ 25 мая 2010

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

Есть ли способ обеспечить отображение "правильного" источника помимо создания новых экземпляров org.apache.log4j.Logger для каждого оператора журнала? Я также пытался использовать метод Logger.log (String callerFQCN, Уровень приоритета, Сообщение объекта, Throwable t), но он, похоже, не работает, например:

public class Logger2 {

    public static org.apache.log4j.Logger log4JLogger = org.apache.log4j.Logger.getLogger(Logger2.class);

    public static void warning(Object source, String message) {

        log(source, message, Level.WARN, null)
    }

    private static void log(Object source, String message, Level level, Throwable t) {

        String className = source.getClass().getName();
        System.out.println("Logging class should be " + className);
        log4JLogger.log(className, loggingLevel, message, t);
    }
}

При вызове:

public void testWarning() {
    Logger2.warning(new Integer(3), "This should warn");
}

Печать:

Logging class should be java.lang.Integer
2010-05-25 10:49:57,152 WARN                              test.Logger2 - This should warn

Ответы [ 3 ]

6 голосов
/ 25 мая 2010

В моем домашнем журнале было использовано класс log4j LocationInfo для поиска информации об исходном коде.

С этим решением объект locationInfo содержит информацию от объекта, который вызывает мой регистратор с loggerName.

Вот упрощенная версия моего регистратора, который регистрирует с log4j:

public void log(Level level, String message) {
    LocationInfo locationInfo = new LocationInfo(new Throwable(),
            loggerName);

    MDC.put(LINE_NUMBER, locationInfo.getLineNumber());
    MDC.put(FILE_NAME, locationInfo.getFileName());
    MDC.put(CLASS_NAME, locationInfo.getClassName());
    MDC.put(METHOD_NAME, locationInfo.getMethodName());
    MDC.put(FQMETHOD_NAME, locationInfo.getClassName() + "."
            + locationInfo.getMethodName());

    logger.log(level, message);

    MDC.remove(LINE_NUMBER);
    MDC.remove(FILE_NAME);
    MDC.remove(CLASS_NAME);
    MDC.remove(METHOD_NAME);
    MDC.remove(FQMETHOD_NAME);
}

Кстати: класс Level , MDC и Logger - это все классы log4j.

Ответы на комментарии:

Объект MDC хранится в объекте ThreadLocal и доступен для регистратора log4j.

Из документации MDC Java:

Управление MDC осуществляется отдельно для каждого потока.

0 голосов
/ 23 июля 2014

Это должно сделать это:

class Logger2 {

  Logger _log4JLogger;

  public void log(Object msg) {
    _log4JLogger.log(Logger2.class.getName(), Priority.INFO, msg, null);
  }

}
0 голосов
/ 14 октября 2010

В Log4J API о Logger.log (String callerFQCN, уровень приоритета, сообщение объекта, Throwable t):

Параметры:

  • callerFQCN - Полное имя класса класса-оболочки.
  • level - уровень запроса на регистрацию.
  • message - сообщение о запросе на регистрацию.
  • t - Выбрасываемый запрос на регистрацию может быть нулевым.

См .: Log4J API .

Довольно странно, я знаю, аргумент называется "callerFQCN", который выглядит как класс объекта вызывающей стороны, НО (muajaja!) На самом деле это класс "оболочки" (например, MyClass.class.getName ()).

На самом деле, я думаю, что вызывающий абонент получает аргумент Throwable. Не уверен, не проверял реализацию.

Когда вы оставите аргумент Throwable пустым, я думаю, что-то подобное должно происходить ниже:

StackTraceElement[] stack = (new Throwable()).getStackTrace();
String caller = stack[something, meaby 1].getClassName();

Если вы хотите создать оболочку Logger, вам нужно сделать что-то вроде этого:

public static void myWarn(String message) {
    myLogger.log(MyWrapper.class.getName(), message, Level.WARN, null);
}

Эта работа без проблем в качестве обёртки.

Или, если вам абсолютно необходимо поддерживать интерфейс, который вы показываете ниже, сделайте что-то вроде этого:

// Warning: Pseudocode
public static void myWarn(Object source, String message) {
    String sourceClass = source.class.GetName();
    StackTraceElement[] stack = (new Throwable()).getStackTrace();
    stack[1, or meaby 2... or 0?] = new whatever(sourceClass);
    myLogger.log(MyWrapper.class.getName(), message, Level.WARN, myStack);
}

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...