0Pricing
Java Academy · レッスン

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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 構造化ログを使う理由
  2. SLF4J ファサードとロガー
  3. パラメータ化ロギング
  4. Logback の設定
← Java Academyに戻る