3週間新年ブレーク(華)金利(風水)の後にあなたの幸せ新年、私は戻って、前の4人の小さなパートナーが使用ログとベストプラクティスを理解する必要があり、おそらく後に、この一連の記事を更新していますそれは最後まで程度であり、今日は合計する来ます。
概要
この記事では、SLF4Jの設計を議論し、SLF4J幸いなことに、何を、ほとんどの最後に、我々は適切にログファイルの出力を分割する方法を見て旧シリーズの正誤表といくつかのQ&A、後。
解析と設計
SLF4Jバインディングいわゆるコンパイルするためにインターネットを使用しなかった場合は、実際には、大会の道の採用があり、どのようにしますか?単に直接ロードされorg/slf4j/impl/StaticLoggerBinder.class
、直接使用することを見つけるために見つける,,以上のメッセージの警告は、ソースコードを解析見つけられませんでした:
ロガーは、私たちが作成する方法の一例を見てみましょう。
org.slf4j.LoggerFactory#getLogger(java.lang.String)
本当の入り口のロガーインスタンスを取得するにはch.qos.logback.classic.LoggerContext#getLogger(java.lang.String)
、のlogbackと呼ばれるLoggerContext
)以下ここに解決するために呼び出す具体的には、どのように、(LoggerFactoryを達成)- あなたは見ることができます
childLogger = logger.createChildByName(childName);
フォローアップを継続し、作成したlogggerインスタンスを - では
ch.qos.logback.classic.Logger#createChildByName
この方法で見ることができchildLogger = new Logger(childName, this, this.loggerContext);
、これまで私たちの目的は達成された、ロガーは、いわゆるコンパイル時の新しいうちに結合されていません。
私たちは、呼び出しがlogbackする方法を追跡し続けるLoggerContext
(LogggerFactory)、そしてそれは、いわゆるコンパイルを結合されているかどうかを確認するために:
-
あるいは、
org.slf4j.LoggerFactory#getLogger(java.lang.String)
この方法は、この時間は、我々は従うorg.slf4j.LoggerFactory#getILoggerFactory
方法FOUNDが呼び出されperformInitialization
、見つけるために、呼び出しで行くbind
、見つけるために、通話をフォローアップfindPossibleStaticLoggerBinderPathSet
現在で指定されたすべてのクラスパス照会するメソッドorg/slf4j/impl/StaticLoggerBinder.class
の戻りへのクラスパスを -
非常に明確に書かれたコメントは、以下の実際のコード、:
Set<URL> staticLoggerBinderPathSet = null; // skip check under android, see also // http://jira.qos.ch/browse/SLF4J-328 if (!isAndroid()) { staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet(); reportMultipleBindingAmbiguity(staticLoggerBinderPathSet); } // the next line does the binding StaticLoggerBinder.getSingleton(); 复制代码
StaticLoggerBinder
仲介クラスが提供すると言うことです。このクラスのキーバインドで、ポイントはクラスにSLF4Jを見つけましたが、Logbackからされていない、SLF4J使用するサードパーティ(Logback、Log4jのなど)、(春ブーツの自動設定もの一部です。外観があれば記事のフルスタックシリーズは、ディテール、歓迎の注意)で分析された後、このアイデアを使用しNoClassDefFoundError
、その後、もはやログリマインダーユーザーです。SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. 复制代码
結論:
JDK 1.6のリリースは、JSR269でコンパイルできるようになるまでのJavaバインディング(バインディング)の概念についての私たちの最初の明確な結論を与える前に、Javaの自体は、ランタイム(実行時)にバインドされたスタティック(静的)結合をサポートしています結合するとき、結合は、外側部材lomokコンパイルされたバイトコードに似ていることは、コンパイル・プロセスを変更することがわかります。ロガーインスタンスSFL4j結合の新しい出ているLogContext
のStaticLoggerBinder
(中間のタイプは)死んで書き込まれ、コンパイル時に任意のロジックに対処していなかったが、また、結合、コンパイル時のあまりない、SLF4Jは、関連する文書を見つけることができませんでした外側部材の検索設定の原則を超える大会-コンパイル時に結合した物質は、公式には、単に間違ってコンパイル時にインターネット上で循環させる結合、SLF4Jは設定より規約(CoC認証)を使用したので、戻って記事のタイトルに、「スタティックバインディング」にのみ言及しました私はあなたがフレームワークをログに記録しているか気にしない、私はちょうどロードされましたorg.slf4j.impl.StaticLoggerBinder
。これは、アプリケーションで非常に大きなのデザインは、直接殴られ顔、非効率的、とOSGiの共通としたが、完璧なKISSのためのフィット(愚か、それをシンプルに保つ)ソフトウェア設計の原則、および動的ロードなどコモンズロギングマジック(魔法)でありますより多くの燃料の使用によるクラスローダの問題、外側部材とが互いに励ましので、ない書き込みコードの名手を行います。
これらは、読者が再びそれを読むためにわざわざスキップ、この記事の核心です。
なぜSLF4Jより良いです
SLF4Jが良く、春から以下の2つの段落は、公式ドキュメントを4.xの理由で最初に見て:
コモンズロギングを使用しません
残念ながら、中にランタイム発見アルゴリズムは
commons-logging
、エンドユーザーのための便利な一方で、問題があります。我々は新しいプロジェクトとして今時計を元に戻すと、春を開始することができれば、それは、異なるログの依存関係を使用します。最初の選択肢は、おそらく単純なロギングJava用のファサード(だろうSLF4Jもの人々が自分のアプリケーション内で春を使用する他のツールの多くで使用されています)、。残念ながら、
commons-logging
私は、このアルゴリズムは、ユーザーにとって便利であるが、実行されていることがわかったが、問題があります。我々は後悔が再起動し、新規プロジェクトとして春を使用することができている場合は、最初の選択肢は、おそらくJava用のシンプルなログファサード(SLF4J)で 、 他のツールは、春にはまた、それを使用することができます頼っています。
それはちょうど、いくつかのログを取得するには、依存関係の多くのように見えるかもしれません。まあそれはあるが、それはあり、オプション、およびそれがより良いバニラよりも振る舞うべき
commons-logging
あなたはOSGiプラットフォームのような厳格な容器の中にあり、特に場合は、クラスローダの問題に関して。バインディングがない実行時コンパイル時にしているので、伝えられるところでは、パフォーマンス上の利点があります。私達はちょうど依存性の多くをログに記録する必要があるかのように見えます。しかし、これらの依存関係は、クラスローダの問題の観点から、それはあなたがそのような密閉容器のOSGiプラットフォームである場合は特に、平均コモンズ・ログよりも良好に機能する必要があり、オプションです。コンパイル時ではなく、実行時に結合するので、パフォーマンス上の利点があるといわれています。
これら二つの言葉は心からの言葉、周りに行かなかった公正・公平、外部検証スタッフが、私は、いわゆるパフォーマンス上の利点を考えると言うことができるstatic final
、パフォーマンス上の利点があまりできませんレベルの変数を。SLF4J外のメンバーは、その中に不可欠な理由にすべてのロギングフレームワークの互換性ソリューションを提供し、より良い市場に出回っていると思います。
正誤表
最初の記事「- ?アーキテクチャの記事Javaロギングシステムはとても複雑になる可能性が春ブーツを依存しているが、私は「春はlog4j2-スターターを書いていますが、パッケージを橋渡しの欠如は」間違っている、好奇心メンバーに出かける書きました、」申し訳ありませんので、春に依存するJCLオーバーSLF4J春ブーツ2.xのバージョンが独自の実装を埋める春JCLに依存しているためない理由は、しばらくJCLオーバーSLF4Jと1.xのバージョン依存はありません、確認してください私の記事がここに間違っていた、あなたが知られている願っています。
第二の記事、「Javaの経験、面接またはどのようにログを書き込むの5年がより良いと言うことはできません-ログの規範とベストプラクティスの論文?」STDOUTと呼ばれるコンソールを逃し、期間が間違っていることLog4j2設定ファイルアペンダ、コードは次のとおりです。
<Console name="STDOUT">
<PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n"/>
</Console>
复制代码
第四の記事「甘いダイナミックログ出力レベルので、あなたは必ず見に来ない? -プロダクションレベルのダイナミック入力ログファイルを。」
記事はまた、誤った位置に貼り付ける設定ファイルを持っていますが、ソースが正しいか、優先するものとソースコードにgithubのソースコードをダウンロードしてください。
Q&A
まず私は、当然のことながら、ここに手書きされ、テストの生産と使用を再入力してくださいすることができ、Log4j2にYAMLの設定ファイルのフォーマットを書くことができれば尋ねた読者の小さなQ&A要件、次のとおりです。
Configuration:
status: debug
name: YAMLConfig
properties:
property:
name: baseDir
value: logs
appenders:
RollingFile:
- name: RollingFile
fileName: ${baseDir}/log.log
filePattern: "${baseDir}/$${date:yyyy-MM}/log-%d{yyyy-MM-dd-HH}-%i.log.gz"
PatternLayout:
pattern: "%d{yyyy-MM-dd HH:mm:ss.SSS} %5p %pid --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}"
Policies:
- TimeBasedTriggeringPolicy: true
SizeBasedTriggeringPolicy:
size: 250 MB
DefaultRollOverStrategy:
max: 100
Delete:
basePath: ${baseDir}
maxDepth: 2
IfFileName:
glob: "*/app-*.log.gz"
IfLastModified:
age: 30d
IfAny:
IfAccumulatedFileSize:
exceeds: 100 GB
IfAccumulatedFileCount:
exceeds: 10
Console:
name: STDOUT
PatternLayout:
Pattern: "[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n"
Filters:
ThresholdFilter:
level: debug
Loggers:
logger:
- name: org.apache.logging.log4j.test2
level: debug
additivity: false
AppenderRef:
ref: RollingFile
Root:
level: trace
AppenderRef:
ref: STDOUT
复制代码
私の記事のもう一つのジュニアパートナーは、いくつかの質問を提起します:
各ログファイルのサイズは、どのように?日付セグメンテーションを分割するには?ある日のA?一日一日のAファイルまたはディレクトリ?ディレクトリまたは週?地区別のエラーおよび情報のログファイルを区別しませんか?遊びの他のレベルは、ログを印刷しないのですか?あなたが動的に非同期ログのログレベルのノンストップ?必要性を変更することができ、デフォルトの同期ログへのご訪問は、それのポイントを運ぶことができませんでしたか?どのように非同期のログ?
ジュニアパートナーの態度は非常に良いではありませんが、問題はまだ非常に良いですが。
-
各ログファイルのサイズは、どのように?日付セグメンテーションを分割するには?ある日のA?一日一日のAファイルまたはディレクトリ?ディレクトリまたは週?
私は、各ファイル250Mのサイズのように、この数は、そう余りに日付でこの部門が私をすべきではない、と私は月が分割された、一般的なアプリケーションはGの何百もある、と私は言った部門別分、アプリケーションはるかに少ない1Mより、そう自分のラインのニーズに合わせて、ゆっくりと仕事を調整します。
-
地区別のエラーおよび情報のログファイルを区別しませんか?
情報、警告、エラーログレベルが有用であるとき、メンバーがしっかりとサブファイルのログレベルに応じて外部に反対し、分離あれば、シーンのバックを想像し、参照するには一つ一つではないでしょうか?私は間違った位置に配置することによって、1を行く場合は、私はBS-INGのだろうと思いますが、正しく出力ログファイルを分割する方法にとして、私は以下を参照してください、再度追加する必要があります。
-
遊びの他のレベルは、ログを印刷しないのですか?
遊びの他のレベルは、ログを印刷しない単に擬似問題であり、他のレベルを印刷する必要はありませんので、多くのログレベルを必要としない、問題がログとして理解されるべきではなく、私も見、私は通常、情報のレベルを開いて、どのようなレベルに開いている必要がありますエラーは、オンラインのみの営業となって、その後、出力はエラー(負例)の事業であるログインします。
-
あなたは、動的にログレベルノンストップを変更できますか?
エネルギーは、私の以前の記事を参照してください、と私は良い人を行うために記事を書いたよりも、この点でこれ以上あってはなりません。
-
非同期ログ、どのように非同期のログが必要なのでしょうか?
私は個人的には、ディスクIOがいっぱいである、非同期ログを好むの非同期バッファがいっぱいになっ開く、オープン非同期はパフォーマンス上の利点が大きくないもたらすとして、バッファは、完全またはブロックされたか捨てられたではありません。私が書かれているどのように非同期ログ記事、公衆番号を参照してください。
-
デフォルトの同期ログへのご訪問は、それのポイントを運ぶことができませんでしたか?
ログは最初の配慮を行っていない可能性があり、それは、ログを減らすことができない場合は、ディスクをマウントしたディスクを交換し、これより良いだけでは、ログ出力パスを考え、あまりありません。
正しいログファイルの出力点
知っているメンバー外の記事を読んで、外側部材は、ログファイルの出力点の賛成であるが、出力ファイルへの反対のレベルに応じて外側部材。どのようにして、出力ログファイルを修正するには?前の記事では、ここで何かを追加するために、書いていません。
非常に単純な、アペンダの複数、次にサブloggger文書によれば、次の通り:
<Logger name="com.jiyuanwai.log.xxx" level="info" additivity="false">
<appender-ref ref="XXXFile"/>
</Logger>
复制代码
<Logger name="com.jiyuanwai.log.yyy" level="info" additivity="false">
<appender-ref ref="YYYFile"/>
</Logger>
复制代码
これは実際には非常にシンプルですが、問題があるあなたが複数の場所に複数のログ出力をしたい場合は、単一のクラスがあり、どのように行うには、2つのソリューションがあり、ロガークラスは、複数のインスタンスを保持します。
class A {
static final Logger log = LoggerFactory.getLogger("com.jiyuanwai.log.xxx");
static final Logger log = LoggerFactory.getLogger("com.jiyuanwai.log.yyy");
...
}
复制代码
このアプローチは、我々はまた、として、ふるいにかけるMDC前の記事に従って実装されますが、外側部材が推奨されていない使用することができることを理解し、フィルターメーカーはもちろん、達成することであるとのは、プログラムの別のセットを思い付くしてみましょうエレガントシンプルですが、ではありませんなぜ、公共の福祉のファンの数が答えを得るために、公開番号返信「ふるい」に従うことができるよう、私たちはデモを見続けます。
// Marker 也可以考虑 static final
Marker file1 = MarkerFactory.getMarker("file1");
Marker file2 = MarkerFactory.getMarker("file2");
log.info(file1, "A file 1 log.");
log.info(file2, "A file 2 log.");
复制代码
次のようにコンフィギュレーションファイルは、次のとおりです。
<appender name="FILE1" class="ch.qos.logback.core.FileAppender">
<file>${LOG_PATH}/testFile1.log</file>
<append>true</append>
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator">
<marker>file1</marker>
</evaluator>
<!-- 不匹配 NEUTRAL不处理,ACCEPT接收,DENY抛弃 -->
<OnMismatch>DENY</OnMismatch>
<!-- 匹配处理方式 NEUTRAL不处理,ACCEPT接收,DENY抛弃 -->
<OnMatch>ACCEPT</OnMatch>
</filter>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<appender name="FILE2" class="ch.qos.logback.core.FileAppender">
<file>${LOG_PATH}/testFile2.log</file>
<append>true</append>
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator">
<!-- 此处可以配置多个 marker-->
<marker>file2</marker>
</evaluator>
<!-- 不匹配 NEUTRAL不处理,ACCEPT接收,DENY抛弃 -->
<OnMismatch>DENY</OnMismatch>
<!-- 匹配处理方式 NEUTRAL不处理,ACCEPT接收,DENY抛弃 -->
<OnMatch>ACCEPT</OnMatch>
</filter>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<logger name="com.jiyuanwai.logging.LoggingApplication" additivity="false">
<appender-ref ref="FILE1"/>
<appender-ref ref="FILE2"/>
</logger>
复制代码
結論
これらは、ログファイルの出力点でもより多くのロジックを記述することができますだけで開始され、小さなパートナーは自分自身を探求する必要があります。
この時点で、ログシリーズは、パートナーがメッセージ、我々は道路の春ブーツ+ Vueの完全なスタックを入力して次のシリーズなので、ご期待を話し合うことができることはほとんど疑いがあっても最後まで来ました。
問題やエラー訂正がある場合、これらは、あなたがよく書かれて感じれば、コードワードは、容易ではない、メッセージを議論するために歓迎され、ビューの個人的なポイントです前方に求めて、親指を求めて、注意を求めています。
世間の注目のスキャンコード番号、更新のための最初の時間