Kotlinのログの出力について

採用はこちら

Kotlinでアプリケーションを開発する場合、ログ出力(Logging)は非常に重要な仕組みです。

ログを適切に設計しておくことで、次のようなメリットがあります。

  • プログラムの動作を確認できる
  • 不具合の原因を特定できる
  • システムの状態を監視できる
  • 本番環境のトラブルを調査できる

特にサーバーアプリケーションやAndroidアプリでは、ログが障害調査の唯一の手掛かりになることも珍しくありません

目次

Kotlinで最もシンプルなログ出力

Kotlinで最も簡単にログのような出力を行う方法は、println を使う方法です。

fun main() {

    println("アプリケーション開始")

    val user = "Taro"

    println("ユーザー名: $user")

    println("アプリケーション終了")

}

実行すると、標準出力に文字列が表示されます。

アプリケーション開始
ユーザー名: Taro
アプリケーション終了

printlnの特徴

メリット

  • 書き方が非常に簡単
  • 学習用途に向いている

デメリット

  • ログレベルがない
  • 出力先の制御ができない
  • ファイル出力ができない
  • フォーマット管理ができない

そのため、実務ではロギングライブラリを使用するのが一般的です。

ログの基本概念

ログには、重要度を表すログレベルがあります。

一般的なログレベルは次の通りです。

ログレベル意味
TRACE非常に詳細な処理ログ
DEBUGデバッグ用の情報
INFO通常の動作ログ
WARN問題の可能性がある状態
ERRORエラー発生

例えば次のようなログになります。

DEBUG ユーザー情報取得
INFO ログイン成功
WARN API応答が遅い
ERROR データベース接続失敗

ログレベルを使うことで、環境ごとにログの出力量を調整できます。

例えば次のような設定がよく行われます。

開発環境

DEBUG
INFO
WARN
ERROR

本番環境

INFO
WARN
ERROR

Java標準ログ(java.util.logging)

KotlinはJVM上で動作するため、Javaの標準ログライブラリも利用できます。

java.util.logging はJava標準のロギングAPIです。

import java.util.logging.Logger

fun main() {

    val logger = Logger.getLogger("MyLogger")

    logger.info("アプリ開始")

    logger.warning("警告ログ")

    logger.severe("エラーログ")

}

主なログレベルは以下です。

レベル意味
SEVERE重大なエラー
WARNING警告
INFO通常情報
FINE詳細ログ
FINERさらに詳細
FINEST最も詳細

ただし、現在のJVM開発では、より柔軟なロギングを行うためにSLF4JなどのロギングAPIが使われることが多いです。

Kotlin/JVMでよく使われるロギング構成

現在のJVM開発では、次の構成がよく使われます。

Kotlin
↓
SLF4J
↓
Logback

それぞれの役割は次の通りです。

コンポーネント役割
SLF4JログAPI(共通インターフェース)
Logbackログの実装

SLF4Jはログの「API」であり、実際の出力処理はLogbackなどの実装が行います。

Gradleでの依存関係

Gradleでは次のように依存関係を追加します。

dependencies {

    implementation("org.slf4j:slf4j-api:<最新版>")

    runtimeOnly("ch.qos.logback:logback-classic:<最新版>")

}

SLF4JはAPIのみなので、実際にログを出力する実装(Logbackなど)が必要です。

Kotlinでのログ出力(SLF4J)

KotlinからSLF4Jを使う場合、次のように書きます。

import org.slf4j.LoggerFactory

class UserService {

    private val logger = LoggerFactory.getLogger(UserService::class.java)

    fun login(user: String) {

        logger.info("ログイン開始 user={}", user)

        try {

            logger.info("ログイン成功")

        } catch (e: Exception) {

            logger.error("ログイン失敗", e)

        }

    }

}

SLF4Jでは、{} を使ったプレースホルダ形式のログがサポートされています。

logger.info("user={}", user)

この書き方は、不要な文字列生成を減らすため、パフォーマンス面でも有利です。

Logbackの設定

Logbackでは、設定ファイルでログのフォーマットや出力先を定義できます。

resources/logback.xml

<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

        <encoder>

            <pattern>%d{HH:mm:ss} %-5level %logger{36} - %msg%n</pattern>

        </encoder>

    </appender>

    <root level="debug">

        <appender-ref ref="STDOUT"/>

    </root>

</configuration>

この設定では、コンソールに次の形式でログが出力されます。

10:30:11 INFO UserService - ログイン開始

Kotlin向けロギングライブラリ(kotlin-logging)

Kotlinでは、kotlin-loggingというラッパーライブラリもよく利用されます。

このライブラリは、SLF4Jの上に構築されたKotlin向けのAPIです。

Gradle

dependencies {

    implementation("io.github.oshai:kotlin-logging-jvm:<最新版>")

    implementation("org.slf4j:slf4j-api:<最新版>")

    runtimeOnly("ch.qos.logback:logback-classic:<最新版>")

}

Kotlinコード

import io.github.oshai.kotlinlogging.KotlinLogging

private val logger = KotlinLogging.logger {}

fun main() {

    logger.info { "アプリ開始" }

    logger.debug { "デバッグログ" }

}

この書き方では、ログメッセージは必要な場合のみ評価されるため、パフォーマンスを向上させることができます。

Androidでのログ出力

Androidでは android.util.Log を使ってログを出力します。

import android.util.Log

Log.d("MainActivity", "デバッグログ")

Log.i("MainActivity", "情報ログ")

Log.w("MainActivity", "警告ログ")

Log.e("MainActivity", "エラーログ")

ログレベルは以下の通りです。

メソッド意味
Log.vVerbose
Log.dDebug
Log.iInfo
Log.wWarn
Log.eError

Androidでは機密情報をログに出さないことが重要です

ログは他のアプリやデバッグツールから参照できる可能性があるため、以下のような情報は出力しないようにします。

  • パスワード
  • トークン
  • 個人情報

実務でのログ設計のポイント

実務でログを設計する際は、次の点が重要です。

機密情報を出力しない

ログにパスワードやアクセストークンを書いてはいけません。

例外は必ずstack traceを残す

logger.error("DB接続失敗", e)

例外情報がないと、原因特定が非常に困難になります。

処理IDやユーザーIDをログに含める

userId=123 login success

これにより、問題の追跡が容易になります。

処理時間を記録する

パフォーマンスの問題を調査するために、処理時間をログに残すことも重要です。

API response time=200ms

Kotlinログのおすすめ構成

Kotlin / JVM開発では、次の構成がよく使われます。

Kotlin
↓
kotlin-logging
↓
SLF4J
↓
Logback

この構成には次のメリットがあります。

  • Kotlinらしい書き方ができる
  • SLF4Jの標準APIを利用できる
  • Logbackの柔軟なログ設定を利用できる

まとめ

Kotlinのログ出力は、用途に応じて次の方法が使われます。

用途方法
簡単な確認println
Java標準java.util.logging
実務(一般的)SLF4J + Logback
Kotlin向けAPIkotlin-logging

特にサーバーアプリケーションでは、SLF4J + Logback をベースにしたロギング構成が広く利用されています。

以上、Kotlinのログの出力についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次