LoginSignup
7
9

More than 5 years have passed since last update.

KotlinでLoggerの生成を少し楽にした

Posted at

logger使ってますか?
Log4jとかlog4j2とかslf4jとか 色々なloggerがあると思います。
javaだったらlombockのアノテーションでいい感じにloggerを注入してくれて便利ですが、kotlinでlombockを使っても、イマイチ捗りません。

だからといって下記のようにjavaのコードを素直にkotlinに書き換える感じもめんどくさいです。特に自分で生成したクラスをいちいちLoggerに渡さないといけないなんて面倒極まりない。
ということでkotlinならどう書いたら面倒が少ないのか考えてみました。
なお利用しているloggerはlog4j2ということにしてあります。但し、ちょっと書き換えれば他のloggerでも利用可能です。

java
class LogExample{
    private static final Logger log = LogManager.getLogger(LogExample.class);
}
kotlin
class LogExample(){
    companion object{
        private val log = LogManager.getLogger(LogExample::class.java)
    }
}

1.companion objectに継承

以下のうようにKtLogというクラスを作ります。(クラス名はなんでもいいです。)

KtLog.kt
open class KtLog(){
    var log:Logger = LogManager.getLogger(
        this.javaClass.name.let {
            val matchIndex = it.length - 10
            when (it.lastIndexOf("\$Companion")) {
                matchIndex -> it.substring(0, matchIndex)
                else -> it
            }
        }
    )
}

使うときはcompanion object:KtLog()のようにcompanion objectに継承します。

kotlin
class LogExample(){
    companion object:KtLog()

    fun nanika(){
        log.debug("なにか")
    }
}

デメリットとしてはcompanion objectに他のクラスを継承させることが不可能なことです。
またKtLogではthis.javaClassLogExample$Companionとなる為、クラス名を戻す処理をしています。

2.byを使う

こちらもKtLogの様なクラスを作成します。(クラス名はなんでもいいです。)

KtLog.kt
class KtLog {
    var log:Logger? = null

    operator fun getValue(thisRef:Any,property: KProperty<*>):Logger{
        return log?:LogManager.getLogger(thisRef.javaClass.name.let {
                    val matchIndex = it.length - 10
                    when (it.lastIndexOf("\$Companion")) {
                        matchIndex -> it.substring(0, matchIndex)
                        else -> it
                    }
                }).apply { this@KtLog.log = this }
    }
}

使うときはcompanion object内でprivate val log by KtLog()を記述するだけです。

kotlin
class LogExample(){
    companion object{
        private val log by KtLog()
    }

    fun nanika(){
        log.debug("なにか")
    }
}

なお、companion object内に記述しなくてもOKですが、生成したオブジェクト毎にloggerが生成されてしまいます。パフォーマンスを気にしないのであればこれでも構いません。

kotlin
class LogExample(){
    private val log by KtLog()

    fun nanika(){
        log.debug("なにか")
    }
}

メリットとしては1の方法と違いcompanion objectは継承可能である点と、logの変数を自由に変更できる点です。

結論

おそらく2のほうが使い勝手はいいと思います。
ただ欲を言えばアノテーションを書くだけで注入してほしい・・・。

7
9
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
9