
Memory-mapped circular logging providing cheap, crash-resilient writes; background snapshots append to daily rotated files, with async flush, retention, truncation warning and startup recovery.
A Kotlin Multiplatform logging library backed by mmap.
Log lines are written into a memory-mapped file, so writes are cheap and survive a process kill: dirty pages stay in the kernel page cache and are flushed to disk. A background worker copies snapshots out of the mapping and appends them to daily log files.
Attribution: This library was primarily written by AI (DeepSeek V4 Pro and DeepSeek Flash). The human author mainly provided the design specification in
docs/architecture.md.
| Platform | Target | mmap implementation |
|---|---|---|
| Android | androidTarget |
MappedByteBuffer |
| JVM (desktop) | jvm |
MappedByteBuffer |
| iOS |
iosArm64 / iosSimulatorArm64 / iosX64
|
platform.posix.mmap |
// Android
Loga.init(context, LogConfig(retentionDays = 7))
// JVM / iOS
Loga.init(LogConfig(logDirectory = "/path/to/logs"))
Loga.i("Network", "request finished")
Loga.e("Network", "request failed")
Loga.flush()LogConfig(
logDirectory = null, // defaults per platform
bufferSize = 400 * 1024, // mmap buffer size
level = Level.DEBUG, // minimum level
formatter = DefaultFormatter, // "L/TAG: msg\n"
retentionDays = 7, // delete files older than this
flushIntervalMillis = 5_000, // background flush interval; 0 disables
isDebug = true, // true: file + console; false: file only
appenders = null, // null = derived from isDebug; pass a list to override
logUncaughtExceptions = true, // log and flush uncaught exceptions before the process dies
)Formatter — customize the log line format.Appender — customize output targets (default: mmap file + platform console).See docs/architecture.md for the full design and
docs/tech-stack.md for the technology overview.
Key properties:
dataStart + logLen; when full the buffer
is flushed and cleared. A line larger than the whole buffer is truncated with
a warning.magic | logLen | logPathLen | logPath). On startup the dirty tail left by a
previous process is written back before the mapping is rebuilt.yyyy_MM_dd.txt; rotation is driven by a
cached day boundary so the hot path only does one comparison.retentionDays are deleted on init and on
each rotation.kill -9) does not lose logs.force() / msync is called../gradlew :loga:jvmTest
./gradlew :loga:compileKotlinIosArm64The Android target requires an installed Android SDK platform (API 36) with accepted licenses. If the system SDK is not writable, install a local one:
sdkmanager --sdk_root=.android-sdk "platforms;android-36" "build-tools;36.0.0"
ANDROID_HOME=$PWD/.android-sdk ./gradlew :loga:assemble.android-sdk/ is git-ignored.
A Kotlin Multiplatform logging library backed by mmap.
Log lines are written into a memory-mapped file, so writes are cheap and survive a process kill: dirty pages stay in the kernel page cache and are flushed to disk. A background worker copies snapshots out of the mapping and appends them to daily log files.
Attribution: This library was primarily written by AI (DeepSeek V4 Pro and DeepSeek Flash). The human author mainly provided the design specification in
docs/architecture.md.
| Platform | Target | mmap implementation |
|---|---|---|
| Android | androidTarget |
MappedByteBuffer |
| JVM (desktop) | jvm |
MappedByteBuffer |
| iOS |
iosArm64 / iosSimulatorArm64 / iosX64
|
platform.posix.mmap |
// Android
Loga.init(context, LogConfig(retentionDays = 7))
// JVM / iOS
Loga.init(LogConfig(logDirectory = "/path/to/logs"))
Loga.i("Network", "request finished")
Loga.e("Network", "request failed")
Loga.flush()LogConfig(
logDirectory = null, // defaults per platform
bufferSize = 400 * 1024, // mmap buffer size
level = Level.DEBUG, // minimum level
formatter = DefaultFormatter, // "L/TAG: msg\n"
retentionDays = 7, // delete files older than this
flushIntervalMillis = 5_000, // background flush interval; 0 disables
isDebug = true, // true: file + console; false: file only
appenders = null, // null = derived from isDebug; pass a list to override
logUncaughtExceptions = true, // log and flush uncaught exceptions before the process dies
)Formatter — customize the log line format.Appender — customize output targets (default: mmap file + platform console).See docs/architecture.md for the full design and
docs/tech-stack.md for the technology overview.
Key properties:
dataStart + logLen; when full the buffer
is flushed and cleared. A line larger than the whole buffer is truncated with
a warning.magic | logLen | logPathLen | logPath). On startup the dirty tail left by a
previous process is written back before the mapping is rebuilt.yyyy_MM_dd.txt; rotation is driven by a
cached day boundary so the hot path only does one comparison.retentionDays are deleted on init and on
each rotation.kill -9) does not lose logs.force() / msync is called../gradlew :loga:jvmTest
./gradlew :loga:compileKotlinIosArm64The Android target requires an installed Android SDK platform (API 36) with accepted licenses. If the system SDK is not writable, install a local one:
sdkmanager --sdk_root=.android-sdk "platforms;android-36" "build-tools;36.0.0"
ANDROID_HOME=$PWD/.android-sdk ./gradlew :loga:assemble.android-sdk/ is git-ignored.