
Shared core logging API with formatter DSL, customizable formatting and tagging, caller-aware resolution, per-line levels, console/file loggers, and extensible logger interfaces.
LoKdroid is a Kotlin Multiplatform logging library with a shared core API for Android, desktop JVM, and iOS, plus Android-specific extensions for file and Logcat-oriented logging.
LoKdroid, log functions, and builder DSL from common code.FormatterBuilder is available from shared code and formats logs on all three platforms.Logcat; desktop JVM and iOS use formatted console output with emoji level markers.View KDoc
The repository uses flat Gradle project paths while keeping grouped folders on disk:
LoKdroid/
├── library/
│ ├── core/ -> Gradle module :core
│ └── domain/ -> Gradle module :domain
└── demoApp/
├── androidApp/ -> Gradle module :androidApp
├── desktopApp/ -> Gradle module :desktopApp
├── sharedUI/ -> Gradle module :sharedUI
└── iosApp/ -> native iOS Xcode host app, not part of the Gradle build
Notes:
library/ and demoApp/ are directories for organization, not Gradle modules.:sharedUI contains the shared Compose Multiplatform screens used by the Android, desktop, and iOS demo hosts.demoApp/iosApp is a native Xcode application that imports the sharedUI framework and hosts Compose UI through MainViewController.Add LoKdroid to your project:
repositories {
mavenCentral()
}Kotlin DSL
dependencies {
implementation("io.github.nikolaykuts:lokdroid:0.1.2-alpha")
}Groovy
dependencies {
implementation 'io.github.nikolaykuts:lokdroid:0.1.2-alpha'
}For a Kotlin Multiplatform project, put the dependency in commonMain when you need the shared API there. FormatterBuilder is part of the shared API and can be used from code that targets Android, desktop JVM, and iOS. Android-specific implementations such as FileLogger, ConsoleAndFileLogger, RemoteLogger, and FileFormat are available only from androidMain.
Initialize LoKdroid before logging starts:
LoKdroid.initialize()androidApp application module from Android Studio../gradlew :desktopApp:run
demoApp/iosApp/iosApp.xcodeproj in Xcode and run the iosApp scheme.The repository already contains a native iOS host app under demoApp/iosApp.
:sharedUI as the sharedUI framework.MainViewControllerKt.initializeLoKdroid().MainViewControllerKt.MainViewController().Minimal integration looks like this on the Swift side:
import SwiftUI
import sharedUI
@main
struct iosAppApp: App {
init() {
MainViewControllerKt.initializeLoKdroid()
}
var body: some Scene {
WindowGroup {
ComposeRootView()
}
}
}logV(message = "some message")
logD(message = "some message")
logI(message = "some message")
logW(message = "some message")
logE(message = "some message")val year: Int = currentDate.year
val month: Int = currentDate.monthValue
val dayOfWeek: java.time.DayOfWeek = currentDate.dayOfWeek
logI {
"Date:"()
"Year: $year"()
"Month: $month"()
"Day of the Week: $dayOfWeek"()
}Inside the IMessageBuilder DSL, the string extension function accepts an optional Level.
The default MessageBuilder uses that value to prepend an emoji marker for the corresponding line.
Shortcuts available inside the builder:
V for Level.Verbose
D for Level.Debug
I for Level.Info
W for Level.Warn
E for Level.Error
logV {
"multi log"()
"some Error"(E)
"some Info"(I)
"some Debug"(D)
"some Verbose"(V)
"some Warn"(W)
}When used with the FormatterBuilder configuration from the next section, the output can look like this:
DesktopMain [Verbose] ⬜ ---> DesktopMainKt.invoke(DesktopMain.kt:24) multi log
🟥 -> some Error
🟩 -> some Info
🟦 -> some Debug
⬜ -> some Verbose
🟨 -> some Warn some custom text
FormatterBuilder is shared and can be configured the same way for Android, desktop JVM, and iOS by passing the built IFormatter into LoKdroid.initialize.
Platform behavior for withLineReference():
MainScreen.kt:42
MainScreen.onClick(MainScreen.kt:42)
Before formatting the line reference, LoKdroid skips its own internal wrapper frames such as LoKdroid, LogManager, and LogFunctions*, then uses the first external frame that remains.
LoKdroid.initialize(
formatter = FormatterBuilder()
.withPointer() // adds "--->"
.space() // adds a space
.withLineReference() // Android: File.kt:123, Desktop/iOS: Class.method(File.kt:123)
.space()
.message() // MANDATORY: injects your original log message
.space()
.custom(text = "some custom text") // appends any custom text
.build()
)ConsoleLogger writes through the platform logging system, so logs appear in Logcat with Android priorities.ConsoleLogger write formatted lines to standard output using the pattern Tag<TAB>[Level] emoji message.⬜, 🟦, 🟩, 🟨, 🟥.tagProvider derives the tag from the caller file name without the .kt extension when source metadata is available.Desktop and iOS example output:
SharedUiScreens [Debug] 🟦 ---> SharedUiScreensKt.invokeMultipleLog(SharedUiScreens.kt:293) Multiple log
fun initialize(
minLevel: Level = Level.Verbose,
logger: ILogger = ConsoleLogger,
formatter: IFormatter = IFormatter { message -> message },
tagProvider: () -> String = { TagProvider.getTag() },
messageBuilderFactory: () -> IMessageBuilder = { MessageBuilder() }
)Available implementations:
ConsoleLogger is available on Android, desktop JVM, and iOS.FileLogger is Android-only and writes messages to a file. It supports Android Studio Logcat import format.ConsoleAndFileLogger is Android-only.RemoteLogger is currently Android-only./** custom implementation */
LoKdroid.initialize(
minLevel = Level.Debug,
logger = { level: Level, tag: String, message: String -> /** your logic */ },
formatter = { message -> "return formatted message: $message" },
tagProvider = { "custom tag" },
messageBuilderFactory = {
object : IMessageBuilder {
override fun build(): String = "build your string"
override operator fun String.invoke(level: Level?) {
// use this block to build multiple message lines
}
}
}
)Platform visibility:
commonMain sees the shared API, including LoKdroid, log functions, ILogger, IFormatter, IMessageBuilder, ConsoleLogger, and FormatterBuilder.androidMain also sees Android-only implementations such as FileLogger, ConsoleAndFileLogger, RemoteLogger, and FileFormat.desktopMain and iosMain use the same shared API surface and platform-specific console behavior under the hood.Console defaults:
SharedUiScreens.SharedUiScreensKt.invoke(...).tagProvider.This project is licensed under the Apache License, Version 2.0. See the LICENSE file for more details.
LoKdroid is a Kotlin Multiplatform logging library with a shared core API for Android, desktop JVM, and iOS, plus Android-specific extensions for file and Logcat-oriented logging.
LoKdroid, log functions, and builder DSL from common code.FormatterBuilder is available from shared code and formats logs on all three platforms.Logcat; desktop JVM and iOS use formatted console output with emoji level markers.View KDoc
The repository uses flat Gradle project paths while keeping grouped folders on disk:
LoKdroid/
├── library/
│ ├── core/ -> Gradle module :core
│ └── domain/ -> Gradle module :domain
└── demoApp/
├── androidApp/ -> Gradle module :androidApp
├── desktopApp/ -> Gradle module :desktopApp
├── sharedUI/ -> Gradle module :sharedUI
└── iosApp/ -> native iOS Xcode host app, not part of the Gradle build
Notes:
library/ and demoApp/ are directories for organization, not Gradle modules.:sharedUI contains the shared Compose Multiplatform screens used by the Android, desktop, and iOS demo hosts.demoApp/iosApp is a native Xcode application that imports the sharedUI framework and hosts Compose UI through MainViewController.Add LoKdroid to your project:
repositories {
mavenCentral()
}Kotlin DSL
dependencies {
implementation("io.github.nikolaykuts:lokdroid:0.1.2-alpha")
}Groovy
dependencies {
implementation 'io.github.nikolaykuts:lokdroid:0.1.2-alpha'
}For a Kotlin Multiplatform project, put the dependency in commonMain when you need the shared API there. FormatterBuilder is part of the shared API and can be used from code that targets Android, desktop JVM, and iOS. Android-specific implementations such as FileLogger, ConsoleAndFileLogger, RemoteLogger, and FileFormat are available only from androidMain.
Initialize LoKdroid before logging starts:
LoKdroid.initialize()androidApp application module from Android Studio../gradlew :desktopApp:run
demoApp/iosApp/iosApp.xcodeproj in Xcode and run the iosApp scheme.The repository already contains a native iOS host app under demoApp/iosApp.
:sharedUI as the sharedUI framework.MainViewControllerKt.initializeLoKdroid().MainViewControllerKt.MainViewController().Minimal integration looks like this on the Swift side:
import SwiftUI
import sharedUI
@main
struct iosAppApp: App {
init() {
MainViewControllerKt.initializeLoKdroid()
}
var body: some Scene {
WindowGroup {
ComposeRootView()
}
}
}logV(message = "some message")
logD(message = "some message")
logI(message = "some message")
logW(message = "some message")
logE(message = "some message")val year: Int = currentDate.year
val month: Int = currentDate.monthValue
val dayOfWeek: java.time.DayOfWeek = currentDate.dayOfWeek
logI {
"Date:"()
"Year: $year"()
"Month: $month"()
"Day of the Week: $dayOfWeek"()
}Inside the IMessageBuilder DSL, the string extension function accepts an optional Level.
The default MessageBuilder uses that value to prepend an emoji marker for the corresponding line.
Shortcuts available inside the builder:
V for Level.Verbose
D for Level.Debug
I for Level.Info
W for Level.Warn
E for Level.Error
logV {
"multi log"()
"some Error"(E)
"some Info"(I)
"some Debug"(D)
"some Verbose"(V)
"some Warn"(W)
}When used with the FormatterBuilder configuration from the next section, the output can look like this:
DesktopMain [Verbose] ⬜ ---> DesktopMainKt.invoke(DesktopMain.kt:24) multi log
🟥 -> some Error
🟩 -> some Info
🟦 -> some Debug
⬜ -> some Verbose
🟨 -> some Warn some custom text
FormatterBuilder is shared and can be configured the same way for Android, desktop JVM, and iOS by passing the built IFormatter into LoKdroid.initialize.
Platform behavior for withLineReference():
MainScreen.kt:42
MainScreen.onClick(MainScreen.kt:42)
Before formatting the line reference, LoKdroid skips its own internal wrapper frames such as LoKdroid, LogManager, and LogFunctions*, then uses the first external frame that remains.
LoKdroid.initialize(
formatter = FormatterBuilder()
.withPointer() // adds "--->"
.space() // adds a space
.withLineReference() // Android: File.kt:123, Desktop/iOS: Class.method(File.kt:123)
.space()
.message() // MANDATORY: injects your original log message
.space()
.custom(text = "some custom text") // appends any custom text
.build()
)ConsoleLogger writes through the platform logging system, so logs appear in Logcat with Android priorities.ConsoleLogger write formatted lines to standard output using the pattern Tag<TAB>[Level] emoji message.⬜, 🟦, 🟩, 🟨, 🟥.tagProvider derives the tag from the caller file name without the .kt extension when source metadata is available.Desktop and iOS example output:
SharedUiScreens [Debug] 🟦 ---> SharedUiScreensKt.invokeMultipleLog(SharedUiScreens.kt:293) Multiple log
fun initialize(
minLevel: Level = Level.Verbose,
logger: ILogger = ConsoleLogger,
formatter: IFormatter = IFormatter { message -> message },
tagProvider: () -> String = { TagProvider.getTag() },
messageBuilderFactory: () -> IMessageBuilder = { MessageBuilder() }
)Available implementations:
ConsoleLogger is available on Android, desktop JVM, and iOS.FileLogger is Android-only and writes messages to a file. It supports Android Studio Logcat import format.ConsoleAndFileLogger is Android-only.RemoteLogger is currently Android-only./** custom implementation */
LoKdroid.initialize(
minLevel = Level.Debug,
logger = { level: Level, tag: String, message: String -> /** your logic */ },
formatter = { message -> "return formatted message: $message" },
tagProvider = { "custom tag" },
messageBuilderFactory = {
object : IMessageBuilder {
override fun build(): String = "build your string"
override operator fun String.invoke(level: Level?) {
// use this block to build multiple message lines
}
}
}
)Platform visibility:
commonMain sees the shared API, including LoKdroid, log functions, ILogger, IFormatter, IMessageBuilder, ConsoleLogger, and FormatterBuilder.androidMain also sees Android-only implementations such as FileLogger, ConsoleAndFileLogger, RemoteLogger, and FileFormat.desktopMain and iosMain use the same shared API surface and platform-specific console behavior under the hood.Console defaults:
SharedUiScreens.SharedUiScreensKt.invoke(...).tagProvider.This project is licensed under the Apache License, Version 2.0. See the LICENSE file for more details.