2013-08-16 47 views
5

Tôi đang cố gắng sử dụng RoutingAppender mới của Log4j2 để định tuyến các nhật ký khác nhau dựa trên MDC (ThreadContext trong Log4j2). Những gì tôi muốn làm là như sau:Mẫu ký tự đại diện cho RoutingAppender of Log4j2

  • Nếu bản đồ MDC có $ contextId -> Nối đến $ contextId appender (cụ thể log)
  • Nếu MDC không có $ contextId -> Nối để appender chính (chung log)

Tôi muốn đạt được điều này bằng cách sử dụng mẫu ký tự đại diện trong thẻ và sau đó lọc bằng thông số chính trong ngữ cảnhId ($ {ctx: contextId}) và sử dụng mặc định (không có thông số chính) ứng dụng chính, tuy nhiên tôi không biết giá trị nào là ký tự đại diện.

Bất kỳ trợ giúp nào được đánh giá cao, có thể tôi đang tiếp cận điều này từ con đường sai. Tôi đã đọc về Bộ lọc nhưng dường như không hoạt động như tôi muốn.

Cảm ơn!

Trả lời

1

Cảm ơn bạn đã liên kết Remko, tôi đã tìm thấy một giải pháp tạm thời cho đến khi tính năng được cải tiến từ các guys của Log4j2. Giải pháp đang sử dụng cả RoutingAppender và Filters. Đây là cách cấu hình log4j2 của tôi trông giống như (Tôi có thuộc tính được định nghĩa nhưng tôi không hiển thị chúng ở đây):

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

Những gì tôi làm điều đó đang kêu gọi ThreadContext.put ("contextId", "") hoặc ThreadContext.put ("contextId", "một cái gì đó") tùy thuộc vào những gì appender tôi muốn đăng nhập. Tôi hy vọng tính năng hoang dã được triển khai sớm, nhưng trong thời gian chờ đợi, giải pháp này là đủ cho tôi.

Cảm ơn!

+1

Tôi đã tìm thấy giải pháp để bạn không phải sử dụng bộ lọc trong giao lộ với việc chuyển đổi khóa ThreadContext từ được điền thành trống) bằng cách sử dụng hai tuyến. Giống như ví dụ này giải thích http://logging.apache.org/log4j/2.x/faq.html#separate_log_files Bạn có thể sử dụng thuộc tính khóa trên tuyến đường để tạo tuyến đường được chọn nếu ThreadContext không có giá trị cho Chìa khóa. Sau đó tôi sử dụng tuyến đường này để tham khảo người phụ trách chính của tôi. Nếu bạn thiết lập "tuyến đường" thứ hai này, bạn không phải sử dụng ThreadContextMapFilter. Hơn nữa, bạn sẽ chỉ cần một appender-ref trong logger gốc của bạn. – Alex

0

Cảm ơn hveiga đã theo dõi và đăng giải pháp của bạn, điều đó rất hữu ích. Tôi muốn nói rằng bạn có thể tránh giải pháp lọc của mình bằng cách thêm 'tuyến đường' thứ hai định tuyến tất cả thư không có giá trị cho khóa định tuyến của bạn như được giải thích tại đây: http://logging.apache.org/log4j/2.x/faq.html#separate_log_files

Vì vậy, cấu hình log4j được cập nhật của bạn sẽ trông như thế này.

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

Và trong ứng dụng của bạn, bạn chỉ có thể thiết lập các ThreadContext bằng cách gọi ThreadContext.put ("contextId", "cái gì đó") và xóa nó khi bạn đang thực hiện bằng cách gọi ThreadContext.clear() HOẶC ThreadContext.remove ("contextId")

Cuối cùng, tôi đã sử dụng các yếu tố

<RollingFile> 

(như các ví dụ liên kết ở trên) thay vì

<appender type="RollingFile"> 

yếu tố bạn đã sử dụng. Tôi tin rằng điều này được ưa thích khi bạn di chuyển đến log4j2 từ log4j.

2

Tôi không hài lòng với giải pháp để xác định tuyến đường dự phòng bằng mẹo được mô tả trong https://issues.apache.org/jira/browse/LOG4J2-326http://logging.apache.org/log4j/2.x/faq.html#separate_log_files, bởi vì điều này buộc tôi phải sao chép cấu hình bộ điều hợp chứa trong các tuyến đường.Tôi không cần cấu hình appender khác nhau cho các tuyến đường mặc định, nhưng chỉ là một tên tập tin thích hợp cho nhật ký chung.

Cho rằng bản đồ thuộc tính mặc định được tìm kiếm cho một thuộc tính không xác định trong ngữ cảnh của nó, xem https://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution, tôi nghĩ cách đơn giản nhất là xác định mặc định, ví dụ:

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

và trong trường hợp bối cảnh thread không có $ {ctx: Trái cây} các "any_fruit" được thực hiện.