「ああ、そうだね!今日はまたレッスンがあるのを覚えてる?」

「いえ、ただあなたを探していたんです。もう少しで…」

「わかりました。それでは始めましょう。今日は伐採についてお話したいと思います。」

「ログとは、発生したイベントのリストです。船のログや日記に似ています。あるいは Twitter のほうがわかりやすいかもしれません。当然のことながら、ロガーはログを記録するために使用するオブジェクトです。」

「プログラミングでは、ほとんどすべてをログに記録するのが通例です。そして Java では、すべてをログに記録しますが、それ以上のログも記録します。」

「実際のところ、Java プログラムは UI やコンソールなどを持たない大規模なサーバー アプリケーションであることが非常に多いです。Java プログラムは同時に何千ものユーザー リクエストを処理するため、さまざまなエラーが発生することがよくあります。特に、異なるスレッドが相互に干渉し始めた場合はそうです。」

「実際、このような状況で再現性の低いバグや障害を検索する唯一の方法は、各スレッドで発生したすべてのことを記録することです。」

「ほとんどの場合、ログにはメソッドの引数、検出されたエラー、および多くの中間情報に関する情報が含まれています。」

「ログが完全であればあるほど、一連のイベントを再現し、障害やバグの原因を追跡することが容易になります。」

「ログが 1 日に数ギガバイトに達することがあります。これは正常な状態です。」

「数ギガバイト?O_o」

「はい。ほとんどの場合、ログ ファイルは関連する日付を示して自動的にアーカイブされます。」

"うわあ。"

「そうですね。当初、Java には独自のロガーがありませんでした。その結果、いくつかの独立したロガーが作成されました。その中で最も一般的なのは log4j でした。」

「数年後、Java は独自のロガーを手に入れましたが、その機能ははるかに劣っており、広く使用されませんでした。」

「 Java に公式ロガーがあるのは事実ですが、Java プログラマーのコミュニティ全体が他のロガーを使用することを好みます。 」

「その後、さらにいくつかのロガーが log4j に基づいて作成されました。」

「その後、現在広く使用されている特別なユニバーサル ロガー slf4j が、それらすべてのために作成されました。これは log4j に非常に似ているので、ロギングを説明する際の例として使用します。」

「ロギングプロセス全体は 3 つの部分で構成されます。」

まずは情報収集です。」

次に、収集した情報をフィルタリングします。」

"第三に、選択した情報を記録します。"

「収集から始めましょう。ログを記録するクラスの典型的な例を次に示します。」

ロギングのあるクラス
class Manager
{
 private static final Logger logger = LoggerFactory.getLogger(Manager.class);

 public boolean processTask(Task task)
 {
  logger.debug("processTask id = " + task.getId());
  try
  {
   task.start();
   task.progress();
   task.complete();
   return true;
  }
  catch(Exception e)
  {
   logger.error("Unknown error", e);
   return false;
  }
 }
}

「赤くハイライトされた単語に注目してください。」

"行 3  –ロガーオブジェクトを作成します。このような静的オブジェクトは、ほぼすべてのクラスで作成されます。ただし、データの保存以外のことを行わないクラスは除きます。"

" LoggerFactory はロガーを作成するための特別なクラスであり、getLogger はその静的メソッドの 1 つです。通常は現在のオブジェクトが渡されますが、さまざまなオプションが可能です。"

"行 7 – メソッド呼び出しに関する情報がロガーに書き込まれます。これがメソッドの最初の行であることに注意してください。メソッドが呼び出されるとすぐに、情報がログに書き込まれます。"

「私たちはデバッグメソッドと呼んでいます。これは、情報の重要性がデバッグレベルであることを意味します。これはフィルタリングに使用されます。それについては数分以内に説明します。」

17 行目– 例外をキャッチし、すぐにログに書き込みます。これがまさに行うべきことです。」

「今回は error メソッドを呼び出します。これにより、情報が ERROR レベルであることがすぐに示されます。」

ロガー - 1

「今のところ、すべてが明らかになっています。まあ、会話の途中で明らかになる限りでは。」

「わかりました。それではメッセージのフィルタリングに進みましょう。」

「通常、各ログ メッセージには独自の重要度レベルがあり、これを使用して一部のメッセージを破棄できます。ここで私が述べた重要度レベルを示します。」

重要度 説明
全て すべてのメッセージ
痕跡 詳細なデバッグ メッセージ
デバッグ 重要なデバッグ メッセージ
情報 情報メッセージ
警告 警告
エラー エラー
致命的 致命的なエラー
オフ メッセージはありません

これらのレベルは、メッセージをフィルタリングするときにも使用されます。

ログレベルを WARN に設定するとします。その後、WARN よりも重要度の低いすべてのメッセージ (TRACE、DEBUG、INFO) が破棄されます。

フィルタリング レベルを FATAL に設定すると、ERROR メッセージも破棄されます。

「フィルタリングの際には、さらに 2 つの重要度レベルが使用されます。1 つはすべてのメッセージを破棄する OFF、もう 1 つはすべてのメッセージを表示する (何も破棄されない) です。」

「フィルタリングはどこでどのように設定すればよいですか?」

「早速お話します。」

通常、log4j ロガー設定は log4j.properties ファイルで指定されます。

このファイルには複数のアペンダー オブジェクトを指定できます。データはこれらのオブジェクトに書き込まれます。データ ソースとアペンダー、つまり反対の目的を持つオブジェクトがあります。データが水のように流れ込むオブジェクト。

"ここではいくつかの例を示します:"

コンソールへのログ記録
# Root logger option
log4j.rootLogger = INFO, stdout

# Direct log messages to stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss}

1 行目と 4 行目 – これらはコメントです

行 2 – 必要なログレベルを示します。重要度の低いレベル (DEBUG、TRACE) はすべて破棄されます。

同じ場所にカンマを追加し、ログが書き込まれるオブジェクトの名前 (自分たちで考えたもの) を示します。5 ~ 9 行目にその設定が含まれています。

5 行目 – アペンダーのタイプ ( ConsoleAppender ) を指定します。

6 行目 – どこに記述しているかを正確に示します ( System.out. )。

7 行目 – 変換パターン (PatternLayout) を管理するクラスを設定します。

8 行目 – 書き込みに使用される変換パターンを設定します。上の例では、日付と時刻です。

「ファイルへの書き込みは次のようになります。」

ファイルへのログ記録
# Root logger option
log4j.rootLogger = INFO, file

# Direct log messages to a log file
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File = C:\\loging.log
log4j.appender.file.MaxFileSize = 1MB
log4j.appender.file.MaxBackupIndex = 1
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = %-5p %c{1}:%L - %m%n

「行 2 は、メッセージ フィルタリング レベルとアペンダー オブジェクト (シンク) の名前を設定します。」

「行 5 – ファイル アペンダー タイプ ( RollingFileAppender ) を指定します。」

「行 6 – ログが書き込まれるファイルの名前を指定します。」

「7 行目 – 最大ログ サイズを指定します。このサイズ制限を超えると、新しいファイルが作成されます。」

「8 行目 – 保存する古いログ ファイルの数を指定します。」

「9~10行目 – 変換パターンを設定します。」

「ここで何が起こっているのか分かりませんが、推測はできます。それは心強いです。」

「それは素晴らしいですね。では、ファイルとコンソールにログを書き込む方法の例を次に示します。」

コンソールとファイルへのログ記録
# Root logger option
log4j.rootLogger = INFO, file, stdout

# Direct log messages to a log file
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File = C:\\loging.log
log4j.appender.file.MaxFileSize = 1MB
log4j.appender.file.MaxBackupIndex = 1
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = %-5p %c{1}:%L - %m%n

# Direct log messages to stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss}

「ああ、それができるんですか?すごいですね!」

「はい。必要な数のアペンダーを宣言して、それぞれをカスタマイズできます。」

さらに、各アペンダーはメッセージ フィルタリングに関して非常に柔軟な設定を行うことができます。各アペンダーに個別のメッセージ フィルタリング レベルを割り当てるだけでなく、パッケージごとにメッセージをフィルタリングすることもできます。ロガーを作成するときにクラスを指定する必要があるのはこのためです (ここではLoggerFactory.getLoggerについて話しています)。

"例えば:"

コンソールとファイルへのログ記録
# Root logger option
log4j.rootLogger = INFO, file, stdout

# Direct log messages to a log file
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.threshold = DEBUG
log4j.appender.file.File = C:\\loging.log
log4j.appender.file.MaxFileSize = 1MB
log4j.appender.file.MaxBackupIndex = 1
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = %-5p %c{1}:%L - %m%n

# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.threshold = ERROR
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss}

log4j.logger.org.springframework = ERROR
log4j.logger.org.hibernate = ERROR
log4j.logger.com.codegym = DEBUG
log4j.logger.org.apache.cxf = ERROR

「6 行目と 15 行目 – 各アペンダーに独自のフィルタリング レベルを設定します。」

「行 20 ~ 23 – パッケージ名とそのメッセージのフィルター レベルを指定します。Log4j.logger はプレフィックスです。パッケージ名はオレンジ色で強調表示されます。」

「本当ですか? それもできますよ。まあ、いいですね!」

「ところで、log4j も slf4j も JDK には含まれていません。それらを個別にダウンロードする必要があります。それはここで行うことができます。しかし、別の方法があります。」

ステップ 1 :クラスにインポートを追加します。」

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

ステップ 2。IntelliJ IDEA でこれらの行にカーソルを置き、Alt+Enter を押します」

ステップ 3.「Web 上のファイル jar」メニュー項目を選択します。

ステップ4。「slf4j-log4j13.jar」を選択します。」

ステップ 5.ライブラリ (jar) をダウンロードする場所を指定する」

ステップ 6。必要なクラスを使用します。」

「おお!今日はなんて一日だったんだろう。新しいこともたくさんあるし、クールなこともたくさんあるよ!」

「ロギングに関する別の優れた記事は次のとおりです: https://docs.oracle.com/javase/10/core/java-logging-overview.htm#JSCOR-GUID-48004124-2C00-49F7-A640-0C0DDA271DBC

「分かった、もう十分だ。リラックスしてください、プログラマー。」