Лучший способ изменить log4j, добавленный для регистрации - PullRequest
8 голосов
/ 02 июля 2011

В настоящее время я скоро развиваюсь, чтобы стать большим (функциональным) веб-сервисом для отдыха, и я хочу действительно хорошо записывать логи, чтобы я мог хорошо понять, что и где происходит.На данный момент я использую log4j для ведения журнала, используя эту добавленную настройку:

<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
    <param name="Target" value="System.out" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%-5p: %c - %m%n" />
    </layout>
</appender>

, которая производит такие журналы:

10:44:55,893 INFO  [STDOUT] INFO : my.package.MyClass - I'm class message
  1. Как я могу сделать это сообщениевыглядит так:

    10:44:55,893 INFO : my.package.MyClass - I'm class message
    
  2. Могу ли я сделать специальный appender или что-то еще, и использовать его в некоторых классах не во всех, т.е. я хочу, чтобы в нескольких моих журналах это:

    • Payload: some request parameters
    • Response: some response that my service returns
    • extra data : some extra data

Без этих INFO [STDOUT] INFO my.package.MyClass in front of it

ОБНОВЛЕНИЕ

Я забыл упомянуть в вопросе, что я использую Jboss 5. Я думаю, что jboss может добавлять 10:44:55,893 INFO [STDOUT] в любой форматчто я положил в мою конфигурацию log4j.

ОБНОВЛЕНИЕ BOUNTY

Я изменил это:

<!-- ============================== -->
   <!-- Append messages to the console -->
   <!-- ============================== -->

   <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
      <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
      <param name="Target" value="System.out"/>
      <param name="Threshold" value="INFO"/>

      <layout class="org.apache.log4j.PatternLayout">
         <!-- The default pattern: Date Priority [Category] Message\n -->
         <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
      </layout>
   </appender>

на это:

<!-- ============================== -->
   <!-- Append messages to the console -->
   <!-- ============================== -->

       <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
          <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
          <param name="Target" value="System.out"/>
          <param name="Threshold" value="INFO"/>

          <layout class="org.apache.log4j.PatternLayout">
             <!-- The default pattern: Date Priority [Category] Message\n -->
             <param name="ConversionPattern" value="%m%n"/>
          </layout>
       </appender>

И это сработало, но кажется уродливым делать это так.Есть ли другой путь?Я использую пружинную комбинацию MVC / JBoss.

Теперь я получаю хорошие чистые сообщения:

10:44:55,893 INFO : my.package.MyClass - I'm class message

без раздражающего префикса

10:44:55,893 INFO  [STDOUT]

Ответы [ 5 ]

7 голосов
/ 03 июля 2011

Вопрос 1:

Используйте следующий макет шаблона для вашего приложения:

<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p: %c - %m%n" />

Шаблон преобразования в указанном вами файле конфигурации не соответствует виду журнала, который вы указали. Например, дата / время не включены в шаблон конверсии.


Вопрос 2:

Вы можете использовать специальный регистратор, который использует другой appender, который только регистрирует чистое сообщение.

Ваша конфигурация будет выглядеть, например, следующим образом:

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

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

    <appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%m%n" />
        </layout>
    </appender>

    <appender name="consoleAppender2" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p: %c - %m%n" />
        </layout>
    </appender>

    <logger name="specialLogger" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender" />
    </logger>

    <root>
        <priority value="INFO" />
        <appender-ref ref="consoleAppender2" />
    </root>

</log4j:configuration>

Вы используете specialLogger для чистых сообщений без дополнительной информации. Может использоваться в нескольких классах.

В конфигурации specialLogger требуется additivity = "false", потому что в противном случае appender consoleAppender2 корневого регистратора будет регистрировать то же сообщение. (В этом случае сообщение будет зарегистрировано два раза.)

Ваш код может выглядеть, например, так:

public class TestClassA
{
    private static Logger specialLogger = Logger.getLogger("specialLogger");
    private static Logger logger = Logger.getLogger(TestClassA.class);    

    public TestClassA() {

    }

    public void doSomething() {
        logger.info("Some message from TestClassA");
        specialLogger.info("Some message via the specialLogger from TestClassA");
    }
}

Вызов doSomething приводит к:

17:17:18,125 INFO : com.foo.TestClassA - Some message from TestClassA
Some message via the specialLogger from TestClassA

Где-то в вашем основном классе вам нужно настроить log4j как обычно, например ::1010 *

DOMConfigurator.configureAndWatch("log4j.xml", 60 * 1000);
4 голосов
/ 13 июля 2011

INFO [STDOUT] обычно приходит из log4j и прослушивает System.out.У нас был похожий случай, когда само приложение имело свою собственную конфигурацию log4j и, таким образом, получило своего собственного корневого приложения.Это приведет к входу в консоль, которую прослушивает JBoss log4j.Это, в свою очередь, добавляет INFO [STDOUT], как если бы вы писали непосредственно в System.out (или ERROR [STDERR] при записи в System.err).

Решение в нашем случае состояло в том, чтобы удалить специфическую для приложения конфигурацию log4j и просто использовать ту, в которую пишет JBoss.

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

Что касается второй части, то есть автоматического расширения журналов с ответом, запросом и т. Д. Данными:

В одном случае мы имелисуперкласс для сессионных компонентов без сохранения состояния, который обеспечивал функциональность регистрации и имел (перезаписываемый) журнал для каждого экземпляра.Базовые методы, такие как info, будут вызывать регистратор и автоматически добавлять необходимые данные.

Второй подход может быть MCD, т.е. вы помещаете некоторые данные (например, запрос) в локальный поток MDC (в основном это карта), а затем получите к ним доступ в своем определении шаблона.

Например, у нас есть несколько похожих приложений, каждое из которых имеет несколько классов, которые есть и у других.Таким образом, нам понадобится приложение, из которого пришло сообщение, и, следовательно, добавление имени приложения в MDC:

В коде:
MDC.put("app.name", "myapplication");

В конфигурации шаблона log4j:
<param name="ConversionPattern" value="%d %-5p [%c (%X{app.name})] %m%n"/> (обратите внимание на % X {app.name} )

Я не проверял, можно ли сделать что-то вроде ввода запроса в MDC и затем использовать: %X{request.getAttribute('xyz')}, но если он просто получает значение в MDC и вызывает toString(), вы можете создать оболочку запроса следующим образом:

class RequestLogWrapper {
  private HttpServletRequest request; //initialize through constructor etc.

  public String toString() {
    return request.getAttribute("xyz") + ";" + request.getAttribute("abc") + ... //handle null etc. as well
  }
}

Затем вызовите MDC.put("request", new RequestLogWrapper(request)); и в конфигурации используйте %X{request}.

1 голос
/ 15 июля 2011

Если вам не нравится файл конфигурации log4j xml, вы можете вместо этого переключиться на файл свойств.Вы не можете настроить фильтры, используя простой файл свойств, но, поскольку кажется, что они вам не нужны, это не должно быть проблемой.

Учитывая, что вы

...в настоящее время он скоро превратится в большой (функционально разумный) веб-сервис для отдыха, и я хочу действительно хорошо записывать логи, чтобы я мог лучше понять, что и где происходит.

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

Пожалуйста, обратитесь к Log4j Best Practices для хорошего ознакомления с дизайном журналов.Пожалуйста, взгляните на ALL его параграфы, включая косметические соображения в самом конце.Надеюсь, это поможет.

1 голос
/ 13 июля 2011

Попробуйте использовать этот шаблон, поскольку он даст вам чистое сообщение:

 <param name="ConversionPattern" value="%d{HH:mm:ss.SSS} %-5p %c %X %m/>

Хорошей идеей будет добавить какое-то уникальное значение в MDC при поступлении запроса, а затем добавить% X {uniqueValueKey} вваш образец.Это позволит вам отслеживать журналы для этого уникального запроса.

0 голосов
/ 13 июля 2011

для печати только сообщений, подойдет следующий шаблон преобразования.

<param name="ConversionPattern" value="%m%n"/>

В зависимости от ваших требований вы можете установить для шаблона преобразования любое значение:

  1. % - 5p относится к типу записи журнала.Это будет отображаться в файле журнала как INFO, DEBUG, ERROR и т. Д. Технически,% p будет достаточно, чтобы включить это описание;-5 здесь для включения слова в 5-символьный столбец ширины.
  2. % d относится к дате.
  3. % t к имени потока, который поднял эту запись журнала.
  4. % c содержит категорию, сгенерировавшую этот журнал, обычно это имя класса.
  5. % m отображает сообщение
  6. % n добавляет возврат каретки.

Собираетесь ли вы размещать всю необходимую информацию только в сообщениях?Я не уверен, но это не очень хорошая идея.

...