KMPLogger is a Kotlin Multiplatform (KMP) logging library that provides a unified logging mechanism for applications targeting Android, iOS, and JVM.
The logger default implementation logs to the platform's native console (Logcat on Android, os_log on iOS, println on JVM), so if some modules use a different logger, their logs will still show up as expected.
dependencies {
implementation("software.amazon.app.kmplogger:kmp-logger-log:0.0.1")
}For Android applications, ensure your compileSdk and targetSdk are set to 36 or higher:
android {
compileSdk = 36
defaultConfig {
targetSdk = 36
// ...
}
}If you need to override the default configuration of the Logger, it is best done at application
startup before any logging occurs. If not configured, default values will be used. Logger can only
be configured once; subsequent calls throw IllegalStateException.
The logging behavior is defined by the minimum log level, a tag prefix, and the logging strategy.
Configuration options:
-
minLogLevel: Minimum severity threshold for processing logs- Default:
LogLevel.VERBOSE - Messages below this level are ignored
- Default:
-
prefix: Optional tag prefix for all log messages- Default: null (no prefix)
- Format when set: "$prefix: $tag"
- Must not be blank if provided else throws
IllegalArgumentException
-
logStrategy: Defines how logs are processed and output- Default:
DefaultLoggingStrategy(logs to the standard output like console or logcat) - Can be customized for different output destinations
- Default:
// Basic configuration
Logger.configure(
minLogLevel = LogLevel.INFO,
prefix = "MyApp"
)
// Custom logging strategy
Logger.configure(
logStrategy = FileLoggingStrategy("app.log")
)class LogTest {
fun greet() {
logger.v { "Hello, this is log from KMPLogger!" }
// JVM -> VERBOSE: (LogTest) Hello, this is log from KMPLogger!
// Android -> V/LogTest: Hello, this is log from KMPLogger!
logger.d { "Hello, this is log from KMPLogger!" }
// JVM -> DEBUG: (LogTest) Hello, this is log from KMPLogger!
// Android -> D/LogTest: Hello, this is log from KMPLogger!
logger.e(throwable = exception) { "test exception" }
// JVM -> ERROR: (LogTest) test exception
// Exception: java.lang.IllegalStateException: test
// at ...
// Android -> E/LogTest: test exception
// java.lang.IllegalStateException: test
// at ...
}
}
fun standalone() {
Logger("Standalone").i { "Hello, this is log from KMPLogger!" }
// JVM -> INFO: (Standalone) Hello, this is log from KMPLogger!
// Android -> I/Standalone: Hello, this is log from KMPLogger!
}We built KMPLogger to address several needs when logging across Kotlin Multiplatform projects targeting Android, iOS, and JVM:
-
Zero-cost when disabled. Log messages use an inlined string-producing lambda. If logging is disabled for a given level, the lambda is never evaluated, so string interpolation and concatenation have no performance cost in production builds.
-
Automatic tag with no stacktrace. The
loggerextension property onAnyextracts the class name viathis::classat the call site without creating a stacktrace. This gives you a meaningful tag for free while avoiding the overhead of stack walking that other libraries use. -
True multiplatform, native output. Each platform logs through its native mechanism — Logcat on Android,
os_logon iOS, andprintlnon JVM. This means logs integrate with each platform's tooling (filtering in Logcat, Console.app on macOS/iOS, etc.) without extra setup. -
Optional by design. KMPLogger writes to the same native output as any other logger on each platform. Modules that use a different logging library still have their logs appear in the same place. There's no requirement for all modules to adopt KMPLogger — it coexists peacefully.
-
Simple API surface. One method per log level (
v,d,i,w,e) with a lambda for the message. No overload explosion. Throwables are an optional named parameter rather than a separate set of methods. -
Pluggable strategy. The
LoggingStrategyinterface lets you redirect logs to files, remote services, or custom formatters without changing call sites. The default writes to the platform console. -
Configure once, use everywhere. Global configuration (minimum level, tag prefix, strategy) is set once at app startup and enforced across all loggers. Attempting to reconfigure throws, preventing accidental mid-run changes that could cause inconsistent behavior.
-
Value class implementation.
Loggeris a@JvmInline value classwrapping a tag string, so creating logger instances allocates nothing on the heap. This makes theAny.loggerpattern viable even in hot paths.
See CONTRIBUTING for more information.
This project is licensed under the Apache-2.0 License.