
A small logging library for Kotlin/Native.
A small logging library for Kotlin/Native. Console output by default, with optional daily-rolling file logging and optional asynchronous (off-thread) dispatch.
Available on Maven Central. Add the dependency to your Kotlin/Native source set:
repositories {
mavenCentral()
}
kotlin {
sourceSets {
nativeMain {
dependencies {
implementation("io.github.kyyana:kogger:1.0.1")
}
}
}
}Supported targets: linuxX64 and linuxArm64.
class Example {
private val logger = logger() // inferred from the enclosing class
fun run() {
logger.info { "Starting..." }
logger.debug { "address=$address" }
logger.error(throwable) { "Failed to start" }
}
}Messages are lambdas (() -> String), so the string is only built when the level is
actually enabled.
Configure once at startup, before logging:
Kogger.verifyArgs(args) // --trace, --debug, --no-colors
Kogger.enableFileLogging("logs", 30) // optional
Kogger.enableAsyncLogging(1024, BufferOverflow.DROP_OLDEST) // optionalOn shutdown, drain and flush pending logs:
Kogger.shutdown()
shutdown()blocks until the async worker has drained the queue and the file is closed. Call it from a normal execution path (e.g. after the main loop returns), not from inside a POSIX signal handler — coroutine code is not async-signal-safe and will deadlock there. In a signal handler, only flip a flag / stop the loop.
TRACE < DEBUG < INFO < WARN < ERROR < FATAL. Messages below minLevel
(default INFO) are dropped before the message lambda runs.
Each level has its own ANSI color for console output (when colors is enabled):
| Level | Color |
|---|---|
TRACE |
gray |
DEBUG |
cyan |
INFO |
green |
WARN |
yellow |
ERROR |
red |
FATAL |
dark red |
| Property | Default | Meaning |
|---|---|---|
minLevel |
INFO |
Minimum level that gets logged. |
colors |
true |
ANSI colors in console output. |
timeFormatter |
HH:mm:ss.SSS |
Timestamp format. |
loggerProvider |
console (+ file) | The sink that receives every event passing the filter. |
verifyArgs lowers minLevel to TRACE on --trace or DEBUG on --debug
(--trace takes precedence), and disables colors on --no-colors.
The default provider emits one line per event:
[12:34:56.789] [Example/INFO]: Example started
The timestamp follows timeFormatter, Example is the source class, and INFO is the
level. When colors is enabled, the line is wrapped in the level's ANSI color. A custom
provider defines its own format.
loggerProvider is a plain var, so you can replace the default sink with your own —
e.g. to emit JSON, ship logs over the network, or route to another logging backend.
It is a fun interface, so a lambda works:
Kogger.loggerProvider = LoggerProvider { clazz, logType, throwable, instant, message ->
// format and emit however you like
}enableAsyncLogging wraps whatever provider is currently set, so assign your custom
provider before calling it if you want it dispatched off-thread. To reuse the default
file output from a custom provider, write to Kogger.fileWriter (populated by
enableFileLogging):
Kogger.fileWriter?.write(line)RollingFileWriter is not thread-safe. A custom provider that writes to
Kogger.fileWriter from multiple threads must either serialize the writes itself or sit
behind enableAsyncLogging, whose single worker is then the only writer.
logger() -> KotlinLogger -> Kogger (config + provider) -> console (+ file)
Kogger — the global singleton that holds all configuration (minLevel,
colors, timeFormatter) and the active LoggerProvider. Configure it once at
startup; every logger shares it.KotlinLogger — the user-facing API, tagged with its source class. Filters by
Kogger.minLevel, then forwards the event to Kogger.loggerProvider.LoggerProvider — a fun interface that receives a formatted log event. The
default provider formats the line, writes it to the file (if enabled), and prints
it to the console.AsyncLoggerProvider — an optional decorator that wraps another provider and
runs it off-thread.RollingFileWriter — handles file output and rotation.<directory>/latest.log.latest.log (even one from the same day), the current file
is gzip-archived as <directory>/yyyy-MM-dd-N.log.gz (N increments for multiple files
on the same day, e.g. 2026-07-02-1.log.gz, 2026-07-02-2.log.gz, ...).maxArchivedFiles archives, deleting the oldest.AsyncLoggerProvider,
whose single worker is the only writer.Decouples the calling thread from slow log I/O using a classic producer/consumer:
log() wraps the work in a Runnable and trySends it to a Channel — non-blocking,
so callers never wait on disk.Dispatchers.Default consumes the channel and runs each task,
delegating to the wrapped (downstream) provider.BufferOverflow decides what happens when the channel is full. DROP_OLDEST
prioritizes the program's responsiveness over preserving every log line.shutdown() closes the channel (so the worker drains remaining entries) and joins the
worker via runBlocking.enableAsyncLogging must be called after a base provider exists (i.e. after the
default provider is set, optionally with file logging enabled); it wraps the current one.
Licensed under the Apache License, Version 2.0.
A small logging library for Kotlin/Native. Console output by default, with optional daily-rolling file logging and optional asynchronous (off-thread) dispatch.
Available on Maven Central. Add the dependency to your Kotlin/Native source set:
repositories {
mavenCentral()
}
kotlin {
sourceSets {
nativeMain {
dependencies {
implementation("io.github.kyyana:kogger:1.0.1")
}
}
}
}Supported targets: linuxX64 and linuxArm64.
class Example {
private val logger = logger() // inferred from the enclosing class
fun run() {
logger.info { "Starting..." }
logger.debug { "address=$address" }
logger.error(throwable) { "Failed to start" }
}
}Messages are lambdas (() -> String), so the string is only built when the level is
actually enabled.
Configure once at startup, before logging:
Kogger.verifyArgs(args) // --trace, --debug, --no-colors
Kogger.enableFileLogging("logs", 30) // optional
Kogger.enableAsyncLogging(1024, BufferOverflow.DROP_OLDEST) // optionalOn shutdown, drain and flush pending logs:
Kogger.shutdown()
shutdown()blocks until the async worker has drained the queue and the file is closed. Call it from a normal execution path (e.g. after the main loop returns), not from inside a POSIX signal handler — coroutine code is not async-signal-safe and will deadlock there. In a signal handler, only flip a flag / stop the loop.
TRACE < DEBUG < INFO < WARN < ERROR < FATAL. Messages below minLevel
(default INFO) are dropped before the message lambda runs.
Each level has its own ANSI color for console output (when colors is enabled):
| Level | Color |
|---|---|
TRACE |
gray |
DEBUG |
cyan |
INFO |
green |
WARN |
yellow |
ERROR |
red |
FATAL |
dark red |
| Property | Default | Meaning |
|---|---|---|
minLevel |
INFO |
Minimum level that gets logged. |
colors |
true |
ANSI colors in console output. |
timeFormatter |
HH:mm:ss.SSS |
Timestamp format. |
loggerProvider |
console (+ file) | The sink that receives every event passing the filter. |
verifyArgs lowers minLevel to TRACE on --trace or DEBUG on --debug
(--trace takes precedence), and disables colors on --no-colors.
The default provider emits one line per event:
[12:34:56.789] [Example/INFO]: Example started
The timestamp follows timeFormatter, Example is the source class, and INFO is the
level. When colors is enabled, the line is wrapped in the level's ANSI color. A custom
provider defines its own format.
loggerProvider is a plain var, so you can replace the default sink with your own —
e.g. to emit JSON, ship logs over the network, or route to another logging backend.
It is a fun interface, so a lambda works:
Kogger.loggerProvider = LoggerProvider { clazz, logType, throwable, instant, message ->
// format and emit however you like
}enableAsyncLogging wraps whatever provider is currently set, so assign your custom
provider before calling it if you want it dispatched off-thread. To reuse the default
file output from a custom provider, write to Kogger.fileWriter (populated by
enableFileLogging):
Kogger.fileWriter?.write(line)RollingFileWriter is not thread-safe. A custom provider that writes to
Kogger.fileWriter from multiple threads must either serialize the writes itself or sit
behind enableAsyncLogging, whose single worker is then the only writer.
logger() -> KotlinLogger -> Kogger (config + provider) -> console (+ file)
Kogger — the global singleton that holds all configuration (minLevel,
colors, timeFormatter) and the active LoggerProvider. Configure it once at
startup; every logger shares it.KotlinLogger — the user-facing API, tagged with its source class. Filters by
Kogger.minLevel, then forwards the event to Kogger.loggerProvider.LoggerProvider — a fun interface that receives a formatted log event. The
default provider formats the line, writes it to the file (if enabled), and prints
it to the console.AsyncLoggerProvider — an optional decorator that wraps another provider and
runs it off-thread.RollingFileWriter — handles file output and rotation.<directory>/latest.log.latest.log (even one from the same day), the current file
is gzip-archived as <directory>/yyyy-MM-dd-N.log.gz (N increments for multiple files
on the same day, e.g. 2026-07-02-1.log.gz, 2026-07-02-2.log.gz, ...).maxArchivedFiles archives, deleting the oldest.AsyncLoggerProvider,
whose single worker is the only writer.Decouples the calling thread from slow log I/O using a classic producer/consumer:
log() wraps the work in a Runnable and trySends it to a Channel — non-blocking,
so callers never wait on disk.Dispatchers.Default consumes the channel and runs each task,
delegating to the wrapped (downstream) provider.BufferOverflow decides what happens when the channel is full. DROP_OLDEST
prioritizes the program's responsiveness over preserving every log line.shutdown() closes the channel (so the worker drains remaining entries) and joins the
worker via runBlocking.enableAsyncLogging must be called after a base provider exists (i.e. after the
default provider is set, optionally with file logging enabled); it wraps the current one.
Licensed under the Apache License, Version 2.0.