SLF4J ファサードとロガー
適切なレベルでログを記録します。
「SLF4J ファサードとロガー」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
SLF4Jとは
SLF4J(Simple Logging Facade for Java)は抽象化レイヤーです。SLF4JのAPIに対してコードを記述し、実際のロギングはLogbackやLog4j2などのバックエンドが行います。
これにより、ライブラリはアプリケーションに特定の実装を強制せずにログを出力できます。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.info("Application started");
}
}ロガーの取得
LoggerFactory.getLogger(MyClass.class)を使って、クラスごとに1つのロガーを作成します。
慣例では、フィールドをprivate static finalとして宣言し、logまたはloggerという名前を付けます。クラス名がロガー名になり、出力に表示されます。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OrderService {
private static final Logger log = LoggerFactory.getLogger(OrderService.class);
void placeOrder(String id) {
log.info("Placing order {}", id);
}
}5つのレベル
SLF4Jのロガーには、各レベルに対応するメソッドがあります。
log.trace(...)log.debug(...)log.info(...)log.warn(...)log.error(...)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.trace("entering main");
log.debug("args length = {}", args.length);
log.info("service is up");
log.warn("cache miss");
log.error("failed to connect");
}
}適切なレベルの選択
ガイドラインは次のとおりです。
- ERROR:人が確認する必要がある実際の障害です。
- WARN:回復可能な異常です。
- INFO:重要なライフサイクルイベントです。
- DEBUG:開発者向けの診断情報です。本番環境では無効にします。
- TRACE:非常に詳細なトレース情報です。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PaymentService {
private static final Logger log = LoggerFactory.getLogger(PaymentService.class);
void charge(int cents) {
if (cents <= 0) { log.warn("non-positive charge: {}", cents); return; }
log.info("charged {} cents", cents);
}
}ロガー名と階層
ロガー名は、ドットで区切られたパッケージによる階層構造になっています。com.example.svcという名前のロガーは、com.exampleの子ロガーです。
親に設定した構成は、上書きされない限り子に適用されるため、パッケージごとにレベルを設定できます。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger a = LoggerFactory.getLogger("com.example.app");
Logger b = LoggerFactory.getLogger("com.example.app.db");
a.info("parent logger");
b.debug("child inherits parent's level unless overridden");
}
}コストの高い呼び出しを制御する
メッセージの構築にコストがかかる場合は、isDebugEnabled()で囲み、そのレベルが有効な場合にのみ処理を実行します。
次のレッスンで扱うパラメーター化ロギングを使えば、通常はこれを行う必要はありません。ただし、自分で文字列を構築する場合には不可欠です。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
static String heavyDump() { return "...large state..."; }
public static void main(String[] args) {
if (log.isDebugEnabled()) {
log.debug("state: {}", heavyDump());
}
}
}例外をログに記録する
完全なスタックトレースとともに例外を記録するには、Throwableを最後の引数として渡します。
プレースホルダーに例外を入れず、メッセージの後に渡してください。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
try {
throw new IllegalStateException("boom");
} catch (Exception e) {
log.error("Operation failed for id {}", 42, e);
}
}
}クラスごとに1つのロガー
ロガーはstatic finalフィールドとして1回だけ宣言してください。メソッド内でロガーを作成すると処理が無駄になり、クラス名を利用できる利点も失われるため、決して行わないでください。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserRepository {
// Good: one shared logger named after the class
private static final Logger log = LoggerFactory.getLogger(UserRepository.class);
void save(String user) { log.debug("saving {}", user); }
}SLF4Jとバックエンド
SLF4JはAPIにすぎません。実行時には、クラスパス上にあるバックエンドにバインドされます。
logback-classicを追加すると、SLF4JはLogbackを使用します。log4j-slf4j2-implを追加すると、SLF4JはLog4j2を使用します。
コードを変更する必要はありません。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
// Same code, different backend depending on classpath
log.info("backend-agnostic logging");
}
}機密データのロギングを避ける
パスワード、トークン、クレジットカード番号全体を決してログに記録しないでください。ログは多くのシステムに送信され、長期間保存されることがよくあります。
ログに記録する前に、機密フィールドをマスクするか除外してください。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
static String mask(String card) { return "****" + card.substring(card.length() - 4); }
public static void main(String[] args) {
log.info("charged card {}", mask("4111111111111234"));
}
}実際的なサービス
ここまでの内容をまとめ、適切なレベルでログを記録し、例外発生時の処理も備えた小さなサービスを見てみます。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EmailService {
private static final Logger log = LoggerFactory.getLogger(EmailService.class);
void send(String to) {
log.debug("preparing email to {}", to);
try {
if (to == null) throw new IllegalArgumentException("null recipient");
log.info("email sent to {}", to);
} catch (Exception e) {
log.error("failed to send email", e);
}
}
}クイックチェック
SLF4Jの基本についての理解度を確認します。
振り返り
SLF4Jファサードについて学びました。
- クラスごとに
private static final Loggerを1つ取得します。 - 5つのレベル用メソッドを適切に使い分けます。
- ロガー名は階層構造になっており、パッケージ単位で制御できます。
- スタックトレースを記録するには
Throwableを最後に渡し、秘密情報は決してログに記録しません。
次は、効率的なパラメーター化メッセージです。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.info("SLF4J facade recap complete");
}
}よくある質問
「SLF4J ファサードとロガー」レッスンは無料ですか?
はい。「SLF4J ファサードとロガー」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「SLF4J ファサードとロガー」で何を学びますか?
適切なレベルでログを記録します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「SLF4J ファサードとロガー」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 構造化ログを使う理由
- SLF4J ファサードとロガー
- パラメータ化ロギング
- Logback の設定