2013-08-16 2 views
5

Я пытаюсь использовать новый RoutingAppender Log4j2 для маршрутизации различных журналов на основе MDC (ThreadContext в Log4j2). То, что я хочу сделать, это следующее:Подстановочный шаблон для RoutingAppender Log4j2

  • Если MDC карта имеет $ ContextID -> Append до $ ContextID Appender (конкретный журнал)
  • Если MDC не $ ContextID -> Добавить к основному Appender (общая журнал)

Я хочу, чтобы достичь этого, используя шаблон подстановки в теге, а затем фильтруют, используя ключевой параметр в течение ContextID ($ {CTX: ContextID}) и использование по умолчанию (без ключа paramenter) для основной appender, однако я не знаю, какое значение является шаблоном.

Любая помощь приветствуется, возможно, я приближаюсь к этому с неправильного пути. Я читал об фильтрах, но, похоже, не работает так, как хочу.

Спасибо!

ответ

1

Спасибо за ссылку Remko, я нашел временное решение, пока эта функция не улучшается от парней Log4j2. Решение использует как RoutingAppender, так и Filters. Это как мой log4j2 конфигурации выглядит (у меня есть определенные свойства, но я не показывать их здесь):

<appenders> 
    <appender name="applicationAppender" type="RollingFile" fileName="${logFileName}" filePattern="${logFileNamePattern}" bufferedIO="true" immediateFlush="true" append="true"> 
     <layout type="PatternLayout" pattern="${logPattern}" /> 
     <Policies> 
      <TimeBasedTriggeringPolicy /> 
      <SizeBasedTriggeringPolicy size="${logFileSize}" /> 
     </Policies> 
     <DefaultRolloverStrategy max="${logFileCount}" /> 
    </appender> 

    <Routing name="contextSpecificAppender"> 
     <Routes pattern="$${ctx:contextId}"> 
      <Route> 
       <appender name="Rolling-${ctx:contextId}" type="RollingFile" fileName="logs/${ctx:contextId}.log" filePattern="${logFileNamePattern}" bufferedIO="true" immediateFlush="true" append="true"> 
        <layout type="PatternLayout" pattern="${logPattern}" /> 
        <Policies> 
         <TimeBasedTriggeringPolicy /> 
         <SizeBasedTriggeringPolicy size="${logFileSize}" /> 
        </Policies> 
        <DefaultRolloverStrategy max="${logFileCount}" /> 
       </appender> 
      </Route> 
     </Routes> 
    </Routing> 
</appenders> 

<loggers> 
    <root level="info"> 
     <appender-ref ref="contextSpecificAppender"> 
      <ThreadContextMapFilter onMatch="DENY" onMismatch="ACCEPT"> 
       <KeyValuePair key="contextId" value="" /> 
      </ThreadContextMapFilter> 
     </appender-ref> 
     <appender-ref ref="applicationAppender"> 
      <ThreadContextMapFilter onMatch="ACCEPT" onMismatch="DENY"> 
       <KeyValuePair key="contextId" value="" /> 
      </ThreadContextMapFilter> 
     </appender-ref> 
    </root> 
</loggers> 

Что я делаю это звонит ThreadContext.put («ContextID», «») или ThreadContext.put («contextId», «something») в зависимости от того, какой appender я хочу зарегистрировать. Я надеюсь, что функция wildward скоро будет реализована, но пока это решение для меня достаточно.

Спасибо!

+1

Я нашел решение, так что вам не нужно использовать фильтр в соединении с переключением ключа ThreadContext из заполненного в пустым), используя два маршрута. Как этот пример объясняет http://logging.apache.org/log4j/2.x/faq.html#separate_log_files Вы можете использовать атрибут ключа на маршруте для создания маршрута, который выбран, если ThreadContext не имеет значения для ключ. Затем я использую этот маршрут для ссылки на мой основной файл. Если вы настроили этот второй «маршрут», вам совсем не обязательно использовать ThreadContextMapFilter. Кроме того, вам понадобится только один appender-ref в корневом журнале. – Alex

0

Благодарим hveiga за продолжение и публикацию вашего решения, это было полезно. Я хотел сказать, что вы можете избежать своего фильтра, добавив второй «маршрут», который маршрутизирует все сообщения без значения для вашего ключа маршрутизации, как описано здесь: http://logging.apache.org/log4j/2.x/faq.html#separate_log_files

Таким образом, обновленная конфигурация log4j будет выглядеть следующим образом.

<appenders> 
    <appender name="applicationAppender" type="RollingFile" fileName="${logFileName}" filePattern="${logFileNamePattern}" bufferedIO="true" immediateFlush="true" append="true"> 
     <layout type="PatternLayout" pattern="${logPattern}" /> 
     <Policies> 
      <TimeBasedTriggeringPolicy /> 
      <SizeBasedTriggeringPolicy size="${logFileSize}" /> 
     </Policies> 
     <DefaultRolloverStrategy max="${logFileCount}" /> 
    </appender> 

    <Routing name="contextSpecificAppender"> 
     <Routes pattern="$${ctx:contextId}"> 
      <Route> 
       <appender name="Rolling-${ctx:contextId}" type="RollingFile" fileName="logs/${ctx:contextId}.log" filePattern="${logFileNamePattern}" bufferedIO="true" immediateFlush="true" append="true"> 
        <layout type="PatternLayout" pattern="${logPattern}" /> 
        <Policies> 
         <TimeBasedTriggeringPolicy /> 
         <SizeBasedTriggeringPolicy size="${logFileSize}" /> 
        </Policies> 
        <DefaultRolloverStrategy max="${logFileCount}" /> 
       </appender> 
      </Route> 
      <Route ref="applicationAppender" key="$${ctx:contextId}"> 
      </Route> 
     </Routes> 
    </Routing> 
</appenders> 

<loggers> 
    <root level="info"> 
     <appender-ref ref="contextSpecificAppender"/> 
    </root> 
</loggers> 

И в вашем приложении, вы можете просто установить ThreadContext по телефону ThreadContext.put («ContextID», «что-то») и очистить его, когда вы сделали по телефону ThreadContext.clear() или ThreadContext.remove ("ContextID")

Наконец, я использовал

<RollingFile> 

элемент (например, примеры, ссылки выше) вместо

<appender type="RollingFile"> 

элемент, который вы использовали. Я считаю, что это предпочтительнее, когда вы переходите на log4j2 из log4j.

2

Я был недоволен решением для определения резервного пути с трюком, описанным в https://issues.apache.org/jira/browse/LOG4J2-326 и http://logging.apache.org/log4j/2.x/faq.html#separate_log_files, потому что это заставляет меня дублировать конфигурацию appender, содержащуюся в маршрутах.Мне не нужна другая конфигурация appender для маршрута по умолчанию, а просто правильное имя файла для общего журнала.

Учитывая, что карта свойств по умолчанию ищет свойство, которое не определено в его контексте, см. https://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution. Я считаю, что наиболее простым способом является определение значения по умолчанию, например.

<Properties> 
    <Property name="fruits">any_fruit</Property> 
</Properties> 

и в случае, если контекст потока не имеет $ {CTX: фрукты} в "any_fruit" берется.

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