Categories
Android Apps Architecture iOS Kotlin Multiplatform Multiplatform Mobile

Kotlin Multiplatform logging libraries

When developing with any platform, the existence of libraries is assumed. This is to delegate common tasks to out project code, in order to reduce development time and avoid common pitfalls already solved by other developers. Kotlin Multiplatform(KMM) is no different.

Available libraries

Since Kotlin is becoming more popular among Android/JVM developers, one might expect libraries from Java are available. This is unfortunately not the case, and will become the biggest hurdle when dealing with KMM.

If the programmer is familiar with Log.d in Android, or print in iOS, then the use of a new 3rd party library is required to achieve the same functionality. This goes for all of the libraries, like Volley or Core Data.

Finding libraries

When browsing libraries in AAKira, attention should be brought to platform badges:

Here, Android and iOS are available, but not JVM.

Missing library support

As KMM is a promising platform, other libraries are adding support over time. Realm DB and Koin have made some recent contributions.

Native code

Access to iOS/Android native code is available. But using that would defeat the multiplatform purpose of reusability. Native code would be needed for each platform.

Logging libraries

For logging purposes, multiple libraries are available. They share a similar architecture, where common library is used in common code, and some initialisation needs to be done iOS/Android.

Out of the available 5+ libraries, we choose to test the 3 with the most stars

Napier(175 ⭐️, android, ios, jvm, js)

Setup

Add the library to common module

val commonMain by getting {
    dependencies {
        implementation("com.github.aakira:napier:1.4.1")
    }
}

Common code

Napier companion object is used to access logging methods

val message = "Hello, ${platform.platform}!"
Napier.i(message)

iOS

Setup is relatively complicated. Platform code needs to be created in KMM project and called from iOS/Kotlin

// Kotlin platform code
expect class Platform() {
    fun setupLogging()
}

actual class Platform actual constructor() {
    actual fun setupLogging() {
        Napier.base(DebugAntilog())
    }
}

// Swift
GreetingKt.platform.setupLogging()

Static logging function needs to be manually created and then that can be used in Swift

// Kotlin
fun i(message: String) {
    Napier.i(message)
}

// Swift
GreetingKt.i(message: "hello from Swift")

Result

Github commit

Kermit(133 ⭐️, android, ios)

Setup

Add the library to common module

val commonMain by getting {
    dependencies {
        api("co.touchlab:kermit:0.1.8")
    }
}

Common code

Create the kermit instance. Common println logger is used by default, but that can be configured.

val kermit = Kermit()

class Greeting {
	...

Send the log

val message = "Hello, ${Platform().platform}!"
kermit.i { message }

iOS

Since there is a Kermit instance in common code, it can be accessed statically from iOS

GreetingKt.kermit.i {
    "Hello from Swift"
}

Result

Github commit

Multiplatform-Log(44 ⭐️, android, iOS)

Building with this project fails

Notable mentions

Cabret-Log(131 ⭐️)

Annotation based logger, where log will be emitted every time a function is called.

kotlin-logging(1.4k⭐️)

The most popular Kotlin logging library is not yet configured for mobile

Could not resolve io.github.microutils:kotlin-logging:2.0.2.
Doesn't say anything about org.jetbrains.kotlin.native.target (required 'ios_arm64')

Conclusion

When coming from Android or iOS development, most previously used libraries need to be set aside in Kotlin Multiplatform. Because of this, the dependency graph needs to be considered carefully for a successful result. Fortunately KMM platform is gaining popularity, and more libraries are becoming available.

For logging purposes, one might consider Kermit for its ease of configurability in both Kotlin and iOS, and the custom logger feature.

Napier might be considered for its static Napier.d access, but rejected for its difficult iOS configuration.

Discuss: