2017-11-23 16 views
1

私はlog4j 2.9.xに深刻な問題があります log4jのドキュメントはとてもうんざりですから "serious"と書いています! このバージョンの最新のドキュメントはありません。既存の文書化されたコードであっても、毎回変更を壊してしまったのでコンパイラに渡されず、文書化されたバージョンを確認できません。私は一日中グーグルグーグルを行ったが、私が見つけたものはほとんどが時代遅れだった。
私は、プログラムでlog4j2を設定するのが少し混乱しています。私が達成したいものをLog4j 2.9.1 AppenderにThresholdFilterをプログラムで追加する

:()

2)gradlesのライフサイクルにアナログコンソールにログインし、ファイルを常に独立し、現在のログレベルのコンソールに出力します

1)追加の「ログレベル」を

3)実行時に決定されたファイル名

XMLで1)と2)を達成する方法が見つかりました。私は3)のための適切な方法を見つけていない。私は並行処理の問題が予想されるので、ファイル名に静的コンテキストまたはシステム変数を使用したくない。

私のアプローチは、log4jをプログラムで設定することです。ここで私の設定工場:

package my.abc 

import org.apache.logging.log4j.Level 
import org.apache.logging.log4j.core.Filter 
import org.apache.logging.log4j.core.LoggerContext 
import org.apache.logging.log4j.core.config.Configuration 
import org.apache.logging.log4j.core.config.ConfigurationFactory 
import org.apache.logging.log4j.core.config.ConfigurationSource 
import org.apache.logging.log4j.core.config.Order 
import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder 
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder 
import org.apache.logging.log4j.core.config.builder.api.LoggerComponentBuilder 
import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration 
import org.apache.logging.log4j.core.config.plugins.Plugin 

@Plugin(name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY) 
@Order(50) 
class CustomConfigurationFactory extends ConfigurationFactory { 

    private static String MESSAGE_PATTERN = "%d{HH:mm:ss.SSS} [%t] %-5level 123 %logger{36} - %msg%n" 

    Level logLevel 
    String packageToScan 

    CustomConfigurationFactory(Level logLevel, String packageToScan) { 
     this.logLevel = logLevel 
     this.packageToScan = packageToScan 
    } 

    private Configuration createConfiguration(final String name, ConfigurationBuilder<BuiltConfiguration> builder) { 
     builder.setConfigurationName(name) 
     builder.setStatusLevel(Level.ERROR) 

     //add appender 
     builder.add(createConsoleAppender(builder)) 
     builder.add(createLifecycleAppender(builder)) 

     //add logger 
     builder.add(createLogger(builder)) 

//  builder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.DENY) 
//    .addAttribute("level", logLevel)) 

     builder.add(builder.newRootLogger(Level.TRACE).add(builder.newAppenderRef("stdout"))) 
     return builder.build() 
    } 

    @Override 
    Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) { 
     return getConfiguration(loggerContext, source.toString(), null) 
    } 

    @Override 
    Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) { 
     ConfigurationBuilder<BuiltConfiguration> builder = newConfigurationBuilder() 
     return createConfiguration(name, builder) 
    } 

    @Override 
    protected String[] getSupportedTypes() { 
     return [{ "*" }] 
    } 

    private AppenderComponentBuilder createConsoleAppender(ConfigurationBuilder<BuiltConfiguration> builder) { 
     AppenderComponentBuilder appenderBuilder = builder.newAppender("stdout", "CONSOLE") 
     appenderBuilder.add(builder.newLayout("PatternLayout"). 
       addAttribute("pattern", MESSAGE_PATTERN)) 
     appenderBuilder.add(builder.newFilter("MarkerFilter", Filter.Result.DENY, 
       Filter.Result.NEUTRAL).addAttribute("marker", "lifecycle")) 
//  appenderBuilder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, 
//    Filter.Result.DENY).addAttribute("level", logLevel)) 
     return appenderBuilder 
    } 

    private AppenderComponentBuilder createLifecycleAppender(ConfigurationBuilder<BuiltConfiguration> builder) { 
     AppenderComponentBuilder appenderBuilder = builder.newAppender("lifecycle", "CONSOLE") 
     appenderBuilder.add(builder.newLayout("PatternLayout"). 
       addAttribute("pattern", "%d{HH:mm:ss.SSS} [%t] LIFECYCLE %logger{36} - %msg%n")) 
     appenderBuilder.add(builder.newFilter("MarkerFilter", Filter.Result.ACCEPT, Filter.Result.DENY) 
       .addAttribute("marker", "lifecycle")) 
     return appenderBuilder 
    } 

    private LoggerComponentBuilder createLogger(ConfigurationBuilder<BuiltConfiguration> builder) { 
     builder.newLogger(packageToScan, "trace") 
       .add(builder.newAppenderRef("stdout")) 
       .add(builder.newAppenderRef("lifecycle")) 
       .addAttribute("additivity", false) 
    } 
} 

あなたは2つのコメントアウトされた行に気づくかもしれません。それは私の問題です。

builder.add(builder.newFilter("ThresholdFilter"...を使用すると、すべてのログはログレベルに適合しないと除外されます。いずれにせよ、私が記録したいと思う「ライフサイクル」 - ログ。私は appenderBuilder.add(builder.newFilter("ThresholdFilter...を使用する場合

iは奇妙である何のエラーメッセージ2017-11-23 12:12:34,905 main ERROR appender CONSOLE has no parameter that matches element ThresholdFilter

を得ました。なぜなら、私はxmlですべてを設定するので、私はちょうどそのことを行うことができます(単一のappenderにthresholdfilterを追加する)、それが動作します。ここerequirements 1のために働く全体のxmlを完全beeingてへ

<Appender type="Console" name="STDOUT" > 
    <Filters> 
     <Filter type="MarkerFilter" marker="lifecycle" onMatch="DENY" onMismatch="NEUTRAL"/> 
     <Filter type="ThresholdFilter" level="${logLevel}" onMatch="ACCEPT" onMismatch="DENY" /> 
    </Filters> 
    <Layout type="PatternLayout" pattern="${pattern}"/> 
</Appender> 

)及び2)

<?xml version="1.0" encoding="UTF-8"?> 
<Configuration status="info" strict="true" name="XMLConfigTest" 
       packages="org.apache.logging.log4j.test"> 
    <Properties> 
     <Property name="logLevel">error</Property> 
     <Property name="filename">target/test.log</Property> 
     <Property name="pattern">%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Property> 
    </Properties> 

    <Appenders> 
     <Appender type="Console" name="STDOUT"> 
      <Filters> 
       <Filter type="MarkerFilter" marker="lifecycle" onMatch="DENY" onMismatch="NEUTRAL"/> 
       <Filter type="ThresholdFilter" level="${logLevel}" onMatch="ACCEPT" onMismatch="DENY"/> 
      </Filters> 
      <Layout type="PatternLayout" pattern="${pattern}"/> 
     </Appender> 
     <Appender type="Console" name="LIFECYCLE"> 
      <Filters> 
       <Filter type="MarkerFilter" marker="lifecycle" onMatch="ACCEPT" onMismatch="DENY"/> 
      </Filters> 
      <Layout type="PatternLayout" pattern="%d{HH:mm:ss.SSS} [%t] LIFECYCLE %logger{36} - %msg%n"/> 
     </Appender> 
     <Appender type="File" name="File" fileName="${filename}"> 
      <Layout type="PatternLayout"> 
       <Pattern>%d %p %C{1.} [%t] %m%n</Pattern> 
      </Layout> 
     </Appender> 
    </Appenders> 

    <Loggers> 
     <Logger name="my.abc" level="trace" additivity="false"> 
      <AppenderRef ref="STDOUT"/> 
      <AppenderRef ref="LIFECYCLE"/> 
     </Logger> 

     <Root level="error"> 
      <AppenderRef ref="STDOUT"/> 
     </Root> 
    </Loggers> 
</Configuration> 

はアペンダにThresholdFilterを追加する方法がなければなりません。 ThresholdFilterクラスが見つかりました。しかし、私はそれをどのように使用するか全く分かりません。インスタンシングはThresholdFilter.createFilter(...)で動作しますが、どこで追加できますか?

がどのように私は、XMLせずに、単一のアペンダにThresholdFilter追加することができます。..短い長い話をカットするには?

答えて

0

FYI

すべての要件解決するための私のアプローチ:

を私はXMLにスイッチバックし、いくつかの力学的特性を追加しました。一部のプロパティはシステムプロパティから取得されます。それらが存在しない場合は、xmlプロパティとして定義されたデフォルト値が使用されます。

プロパティ "logFile"を特に見てください。システムプロパティ(ログファイルへの修正パス用)とlog4jによって動的に決定されます。これは本当にスレッドセーフではありません。しかし、私たちの場合は容認できます。

<?xml version="1.0" encoding="UTF-8"?> 
<Configuration status="info" strict="true" name="XMLConfig" 
       packages="org.apache.logging.log4j.test"> 
    <Properties> 
     <Property name="logLevel">INFO</Property> 
     <Property name="logFileDir">log/</Property> 
     <Property name="logLevelFile">OFF</Property> 
     <Property name="logFile">${sys:logFileDir}ConfigMgmt-${date:yyyyMMdd_HHmmss-SSS}.log</Property> 
     <Property name="packageName">com.hamburgsud</Property> 
     <Property name="messagePattern">%d{HH:mm:ss.SSS} (Test) %-5level %logger{1.} - %msg%n</Property> 
    </Properties> 

    <Appenders> 
     <!-- Console Logging --> 
     <Appender type="Console" name="STDOUT"> 
      <Filters> 
       <Filter type="MarkerFilter" marker="lifecycle" onMatch="DENY" onMismatch="NEUTRAL"/> 
       <Filter type="ThresholdFilter" level="${sys:logLevel}" onMatch="ACCEPT" onMismatch="DENY"/> 
      </Filters> 
      <Layout type="PatternLayout" pattern="${sys:messagePattern}"/> 
     </Appender> 
     <!-- LIFECYCLE is analog to gradles lifecycle log level - means always logging 
      When the marker for lifecycle-logging is added, the message will always be logged --> 
     <Appender type="Console" name="LIFECYCLE"> 
      <Filters> 
       <Filter type="MarkerFilter" marker="lifecycle" onMatch="ACCEPT" onMismatch="DENY"/> 
      </Filters> 
      <Layout type="PatternLayout" pattern="%logger{1.} - %msg%n"/> 
     </Appender> 


     <!-- File Logging --> 
     <Appender type="File" name="FILE" fileName="${sys:logFile}" createOnDemand="true"> 
      <Filters> 
       <Filter type="MarkerFilter" marker="lifecycle" onMatch="DENY" onMismatch="NEUTRAL"/> 
       <Filter type="ThresholdFilter" level="${sys:logLevelFile}" onMatch="ACCEPT" onMismatch="DENY"/> 
      </Filters> 
      <Layout type="PatternLayout" pattern="${sys:messagePattern}"/> 
     </Appender> 
     <!-- Counterpart to consoles LIFECYCLE logging. When file logging is activated and a log is marked with 
      lifecycle, the message will be logged to the file too. --> 
     <Appender type="File" name="FILELIFECYCLE" fileName="${sys:logFile}" createOnDemand="true"> 
      <Filters> 
       <Filter type="MarkerFilter" marker="lifecycle" onMatch="ACCEPT" onMismatch="DENY"/> 
      </Filters> 
      <Layout type="PatternLayout" pattern="%logger{1.} - %msg%n"/> 
     </Appender> 
    </Appenders> 

    <Loggers> 
     <Root level="trace" additivity="false"> 
      <AppenderRef ref="STDOUT"/> 
      <AppenderRef ref="LIFECYCLE"/> 
      <AppenderRef ref="FILE"/> 
      <AppenderRef ref="FILELIFECYCLE"/> 
     </Root> 
    </Loggers> 
</Configuration> 
関連する問題