2013-10-06 4 views
0
public class SessionLogger { 

    private final String sessionId; 

    public SessionLogger(String sessionId) { 
     this.sessionId = sessionId; 
    } 

    public void info(Log log, String message, Object... args) { 
     log.info(formatMessage(message, args)); 
    } 

    public void error(Log log, String message, Throwable t, Object... args) { 
     log.error(formatMessage(message, args), t); 
    } 

    private String formatMessage(String message, Object... args) { 
     for (int i = 0; i < args.length; i++) { 
      message = message.replaceFirst("\\{\\}", args[i].toString()); 
     } 
     return String.format("SessionId [%s]: %s", sessionId, message); 
    } 
} 

Что я хочу сделать, это передать экземпляр Logger в класс SessionLogger, и я хотел бы увидеть имя класса, в котором был инициализирован Logger.Pass Logger как аргумент другому классу

public class A { 
    private static final Log log = LogFactory.getLog(A.class) 
    public void doIt() { 
    sessionLogger.info(log, "hello world"); 
    } 
} 

я бы ожидал увидеть класс А в журнале сообщений вместо SessionLogger:

2013-10-07 00:29:27,328 INFO [main] (SessionLogger.java:17) - SessionId [123]: Hello world 

Я Викисклада logging.jar и log4j-1.2.16.jar в пути к классам. Logger является экземпляром org.apache.commons.logging.Log

Update

Просто выпустили, что ожидаемое поведение, вызвать Logger регистрирует строчку кода, где был вызван метод журнала. Так оно и должно быть сделано по-другому как-то

+0

>> заставляет Logger записывать строку кода, где был вызван метод журнала <<. , , Это зависит от конфигурации вашего log4j.properties - вы также можете вывести имя регистратора (которое должно быть «A») – cljk

+0

Да. Но было бы неплохо также записать строку кода. Поскольку log4j вызывает Thread.currentThread(). GetStackTrace() ..., чтобы получить номер строки во время выполнения, я не могу использовать этот подход в этом случае – user12384512

ответ

1

Я думаю, что решение написать собственный Log4j шаблон макета, как представлено в этой статье: http://fw-geekycoder.blogspot.com/2010/07/creating-log4j-custom-patternlayout.html

Тогда вам не нужно будет SessionLogger, что позволит упростить код значительно.

Планировка:

public class MyPatternLayout extends PatternLayout { 

    @Override 
    protected PatternParser createPatternParser(String pattern) { 
     return new MyPatternParser(pattern); 
    } 
} 

шаблон парсер:

public class MyPatternParser extends PatternParser { 

    private static final char USERNAME_CHAR = 'S'; 

    public MyPatternParser(String pattern) { 
     super(pattern); 
    } 

    @Override 
    protected void finalizeConverter(char c) { 
     switch (c) { 
      case USERNAME_CHAR: 
       currentLiteral.setLength(0); 
       addConverter(new MyPatternConverter()); 
       break; 
      default: 
       super.finalizeConverter(c); 
     } 
    } 
} 

Pattern конвертер:

public class MyPatternConverter extends PatternConverter { 
    @Override 
    protected String convert(LoggingEvent event) { 
     // Retrieve SessionID 
     return "123"; 
    } 
} 

Log4j конфигурации:

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> 

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> 
    <appender name="console" class="org.apache.log4j.ConsoleAppender"> 
     <param name="Target" value="System.out"/> 
     <layout class="MyPatternLayout"> 
      <param name="ConversionPattern" value="%d{HH:mm:ss,SSS} %-5p (%F:%L) - Session ID:%S %m%n"/> 
     </layout> 
    </appender> 

    <root> 
     <priority value ="debug" /> 
     <appender-ref ref="console" /> 
    </root> 

</log4j:configuration> 
1

После взгляда на то, что вы пытаетесь достичь, я верю вместо того, чтобы делать этот кусочек сложного материала SessionLogger, используя MDC, может быть более разумным выбором.

Установка идентификатора сеанса в MDC (в зависимости от вашего дизайна приложения. Для веб-приложения наличие фильтра сервлетов, выполняющего работу по настройке MDC, является разумным), и пусть каждый просто использует регистратор как обычно. Имея соответствующий шаблон, вы можете поместить идентификатор сеанса в сообщение журнала результатов.

Не уверен, что MDC открыт в журнале регистрации Apache, но доступен в SLF4J или Log4J.

Любопытно, есть ли причина использовать ACL (который, как известно, имеет довольно много проблем). Подумайте о переходе на SLF4J, который более широко принят в последние годы.

+0

Спасибо за обмен MDC-подходом. Но это не подходит для меня, потому что оно зависит от переменных ThreadLocal. – user12384512

+0

Мне интересно узнать, почему проблема с ThreadLocal является проблемой? Если вы не делаете какой-то сложный многопоточный материал, ThreadLocal редко бывает проблемой. ThreadLocal - это то, что используется намного больше, чем вы ожидали, например.в управлении транзакциями и т. д. –

+0

Да, есть много многопотоков, исполнителей, производителей/потребителей и т. д. Это не простое веб-приложение – user12384512

Смежные вопросы