Log4j2のドキュメント読むよ
About
Log4j2はSLF4jのようにLogFacadeとしての機能もあるみたい
以下のようなアドバンテージがあるとのこと
lambdaをサポートしてる
SLF4Jより色々ロギングメソッドを提供してる
SLF4Jでサポートしてる parameterized loggingに加えて、java.text.MessageFormat syntaxをサポートしてる
などなど
パフォーマンスが改善されてる
Asynchronous Logging機能を使うことでかなりパフォーマンスが出るっぽい
古いLog4jやSLF4J, Commons LoggingなどのAPIも提供してるとのこと……
パッケージだけ差し替えれば動くみたいなはなし??
Logbackと違い、設定ファイル書き換えたらどうてきに読み込んで動く
Logbackとかより進んだFilterが作れる?
manual
Architecture
https://gyazo.com/138b502cc2c4f6175345ade5cfcd9e38
Alog4j2 APIを使用するアプリケーションはLogManagerに特定の名前のLoggerを要求する
LogManagerは適切なLoggerContextをみつけてそこからLoggerを取得する
Loggerを作成しなければ行けない場合は以下のいずれかに含まれるLoggerConfigに関連ずけられる
同じ名前のLogger
親のパッケージ名に含まれる
root LoggerConfig.
LoggerConifgオブジェクトは設定内のLogger宣言から作られる
LoggerConifgはLogEventsを発信するAppenderに関連づけられる
Logger Hierarchy
Log4j1.xのLogger HierarchyはLogger感の関係で管理されていたが、Log4j2はそのような管理の仕方はしない
変わりにLoggerConfigオブジェクト間の関係で管理される
A LoggerConfig is said to be an ancestor of another LoggerConfig if its name followed by a dot is a prefix of the descendant logger name.
A LoggerConfig is said to be a parent of a child LoggerConfig if there are no ancestors between itself and the descendant (子孫) LoggerConfig.
e.g.
LoggerConfig com.foo は LoggerConfig com.foo.Bar の親になる
rootのLoggerConfigはLogger hierarchyのトップに位置する。これは例外的な存在で、常にすべてのヒエラルキーの一部になる。
root LoggerConfigに直接紐づくLoggerは以下のように取得できる
Logger logger = LogManager.getRootLogger();
他のすべてのLoggerはstatic method LogManager.getLogger に、名前を渡すことで取得することができる。
構成要素
LoggerContext
LoggerContextはLogging systemのアンカー(いかり)としての役割を果たす
しかし、複数のLoggerContextをを動作させることも可能
Configuration
すべてのLoggerContextは有効なConfigurationを持つ
ConfigurationはすべてのAppenderやcontextレベルのFilter, ConggerCongisやStrSubstitutor? を持つ
Configurationが再構成され、複数存在すると、すべてのLoggerは新しいConfigurationへリダイレクトされる
古いConfigurationは止められて、破棄される。
これは結局 xmlとかの設定ファイルとは違うのだろうか?
Logger
Loggerは LogManager.getLogger によって前もって作成される。
Logger自身が直接actoinを起こすことはない
Loggerはシンプルに名前とLoggerConfigへの関連を持つ
Loggerは AbstractLoggerを実装している
Configurationが変更されるとLoggerは別のLoggerConfigい関連づけられるようになり、その結果動作が変更されることがある
LogManager.getLogger は同じ名前を渡せば完全に同じLoggerオブジェクトへの参照を返す
log4jの環境設定は基本的にはApplicatoinのinitialize時に行われる。
設定ファイルを読み取るのが推奨される方法である
Log4jではソフトウェアコンポーネントからかんたんにLoggerへ名前をつけることができる
これはそれぞれのクラスでLoggerをインスタンス化することで達成できます。ロガー名はクラスの完全修飾名と同じになる。
logのoutput時、生成するLogger名も出力されるので、ログメッセージの発信元を簡単に識別できる
これは一般的なやり方だが矯正ではない。開発者は必要に応じてLoggerに好きな名前を与えることができる。
LoggerConfig
ConfiguretionによってLoggerが宣言されると、LoggerConfigも作成される
LoggerConfigはLogEventがAppenderに渡される前に許可しなければならない一連のFilterを含む
LogLevelについて、Log4j 1.xやLogbackはLevel Interitanceを採用していたが、Log4jではLoggerとLogConfigでオブジェクトが別れているので異なるコンセプトで実装されている。
各Loggerは適切なLoggerConfig経由で親を参照することになる
有効なログレベル(そのロガーが出力できるログレベル)は、有効なログレベルの割当がなかったり、親のLoggingConfigが同じログレベルの設定を持っている場合は親のものを引き継ぐ
Filter
デフォルトのlogレベルのフィルタリングに加えてlog4j2はLoggerConfigに処理が映る前にFilterを適用することができる
Filterは検査結果をAccept, Deny, Neutralのいずれかを返すことで内容をフィルターする
カスタムFilterはこんな感じっぽい
@Plugin で名前つけて設定から参照できるようにする感じね
Appender
要するにLogの出力先の設定 (fileなのか、コンソールなのかなど)
log4j複数の宛先を設定できる
各有効なLoogerへのログ出力リクエストは、そのLoggerのLoggerConfigのすべてのAppender、同様に、親LoggerConfigに含まれるAppenderへ転送される
言い換えるとAppenderはLoggerConfig経由で関節的に継承関係が作られる
ParentLoggerConfigはConsole向けのAppenderが入ってて、子供はfilter出力Appenderが入ってたら、子供の方だけファイルに出して、親のものはconsoleに出すみたいなことができる。
ロガーのadditivity="false"の設置を入れるとAppenderでの継承の動きを停止できる
Appendersの種類はこんな感じ
Layout
outputのフォーマット(%r [%t] %-5p %c - %m%n みたいなやつ)のこと
LayoutはAppenderに紐づく
Appenders
AsyncAppender
AsyncAppenderは他のAppenderから参照し、LogEventの書き込みを別Threadで実行することができる。
他のAppenderに書き込む際にエラーが起きるとそれは隠されてしまうので注意
AsyncAppenerは、適切にシャットダウンできるように参照するあペンダーの後に構成する必要がある (多分設定を後ろにしろということ)
デフォルトでAsyncAppenderは java.util.concurrent.ArrayBlockingQueue を使用するので外部ライブラリには依存しない
マルチスレッドアプリケーションはこのあペンダーをこのまま使用する場合は以下の注意が必要
BlockingQueueはロックの競合の影響を受けやすく、log4j2のテストではログに記録するスレッドが増えるとパフォーマンスが低下する場合があることがわかった
RollingFileAppender
RollingFileAppenderはfileNameパラメータによって指定されたファイルに書き込み、TriggeringPolicyとRolloverPoliciyに従ってファイルをロールオーバー(ローテーション)するOutputStreamAppenderである
RollingFilteAppenderは(OutputStreamManagerを拡張した)RollingFileManagerによってファイルのロールオーバーが実行される
TriggeringPolicy
ロールオーバーを実行するかどうかを決定する
RolloverPoliciy
ロールオーバーの実行方法を定義すrう
設定がない場合、デフォルトで DefaultRolloverStrategy が使われる
DefaultRolloverStrategyのmaxを設定すると出力するファイル数を設定できる
Parameters
bufferedIO
trueの場合bufferへ出力されるようになり、bufferがいっぱいになるとフィルに出力されるようになる
trueの場合はfileのlockは効かなくなる
immediateFlushがtrueの場合でも、bufferedIOを使うとパフォーマンスが大幅に向上する
bufferSize
bufferedIOのバッファサイズ
デフォルトは8192 bytes
fineName
書き込まれるファイル名 (同じファイル名が存在しない場合にこのファイル名で作られる)
filePattern
archiveされるログファイルのファイル名のパターンを指定する
使用されるパターンはRolloverPolicyによって異なる
DefaultRolloverPolicyはSimplDateformatと互換性のある日付/時刻パターン、整数カウンター(%i)の療法をサポートする
immediateFlush
defaultはtrue
logをdiskに書き込むことを保証するが、パフォーマンスに悪影響を及ぼす
毎回の書き込みのたびにlogをflushすることは同期ロガーで使用する場合にのみ役に立つ
非同期loggerやappenderではimmediateFlushがfalseに設定されている場合でも、複数のイベントの最後に自動的にflushされる
このときのdiskへの書き込みは保証されるが、同期の場合に比べてより効率的である
Triggering Policies
CompositeTriggeringPolicyによって、複数のtriggering policyを複数指定することができる
よく使いそうなポリシー
Cron Triggering Policy
cron expressionでスケジュールを記述できる
TimeBased Triggering Policy
date/timeのパターンが適用されなくなるとロールオーバーが実行される
paramter
interval
日付パターンの最も詳細な時間単位に基づいてロールオーバーを発生させる
言及がないがおそらくfilePattern内の日付のことを言ってると思われる
例えば日付パターンの最も詳細が時間 (yyyy-MM-dd-HH)で4が設定されていたら4時間ごとになる
RoolingRandomAccessFileAppender
常にバッファリングされるRollingFileAppenderと考えて良さげ
内部的に BufferedoutputStreamの変わりに ByteBuffer + RandomAccessFileを使用する点が、RollingFileAppenderとの違いとのこと
RollingFileAppenderのbufferedIO=trueにしたときに比べて20~200%くらいは性能が改善してるとのころ
フォルトのバッファサイズはそれなりに大きいみたい (256 * 1024)
RandomAccessFileについて
ファイルに対してシーケンシャルに読み取りを行うのではなく、バイト配列のようにインデックスを持っていて、読み取った分のファイルポインタを進めるようになっている (つまり配列にインデックスを指定してランダムアクセスするようにファイルを読み取りれるので効率的というはなしっぽい)
Random access file is a special kind of file in Java which allows non-sequential or random access to any location in the file. This means you don't need to start from 1st line if you want to read line number 10, you can directly go to line 10 and read.