
Flavored logging offering story-driven primitives: single-event notes and contextual scrolls, best-effort non-suspending variants, customizable note/scroll/entry savers, and scroll lifecycle enrichment via margins.
A flavored Kotlin Multiplatform logging library
Scribe is a Kotlin Multiplatform logging library built around the ideas from loggingsucks.com, so structured logs can model both single events and longer contextual flows.
| Documentation Page |
note(...) and contextual logging with newScroll(...)
NoteSaver, ScrollSaver, and EntrySaver
Margin
Scribe objects for applications and imported librariesAdd Scribe to your commonMain dependencies:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("com.rafambn:scribe:0.4.0")
}
}
}Create a Scribe object, hire its runtime, and emit a note:
object AppScribe : Scribe() {
override val shelves: List<Saver<*>> = listOf(
NoteSaver { note ->
println("[${note.level}] ${note.tag}: ${note.message}")
}
)
}
AppScribe.hire(channel = Channel(capacity = 256))
AppScribe.note(
tag = "payments",
message = "starting checkout",
level = Urgency.INFO,
)Use a scroll when you need shared context for a longer flow:
object BillingScribe : Scribe() {
override val shelves: List<Saver<*>> = listOf(
ScrollSaver { scroll -> println(scroll) }
)
override val imprint = mapOf(
"service" to JsonPrimitive("billing"),
"environment" to JsonPrimitive("production"),
)
}
BillingScribe.hire(channel = Channel(capacity = 256))
val scroll = BillingScribe.newScroll(id = "checkout-42")
scroll["gateway"] = JsonPrimitive("stripe")
scroll["attempt"] = JsonPrimitive(1)
scroll["retry"] = JsonPrimitive(false)
scroll.seal(BillingScribe, success = true)Each Scribe object has independent configuration and delivery lifecycle. A Scroll is a mutable JSON-element map initialized by newScroll(...); pass the runtime that should enrich and deliver it to scroll.seal(scribe, ...). Each seal(...) call emits a separate SealedScroll snapshot.
Choose the saver that matches your output flow:
val noteSaver = NoteSaver { note -> println(note) }
val scrollSaver = ScrollSaver { scroll -> println(scroll) }
val entrySaver = EntrySaver { record -> println(record) }A flavored Kotlin Multiplatform logging library
Scribe is a Kotlin Multiplatform logging library built around the ideas from loggingsucks.com, so structured logs can model both single events and longer contextual flows.
| Documentation Page |
note(...) and contextual logging with newScroll(...)
NoteSaver, ScrollSaver, and EntrySaver
Margin
Scribe objects for applications and imported librariesAdd Scribe to your commonMain dependencies:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("com.rafambn:scribe:0.4.0")
}
}
}Create a Scribe object, hire its runtime, and emit a note:
object AppScribe : Scribe() {
override val shelves: List<Saver<*>> = listOf(
NoteSaver { note ->
println("[${note.level}] ${note.tag}: ${note.message}")
}
)
}
AppScribe.hire(channel = Channel(capacity = 256))
AppScribe.note(
tag = "payments",
message = "starting checkout",
level = Urgency.INFO,
)Use a scroll when you need shared context for a longer flow:
object BillingScribe : Scribe() {
override val shelves: List<Saver<*>> = listOf(
ScrollSaver { scroll -> println(scroll) }
)
override val imprint = mapOf(
"service" to JsonPrimitive("billing"),
"environment" to JsonPrimitive("production"),
)
}
BillingScribe.hire(channel = Channel(capacity = 256))
val scroll = BillingScribe.newScroll(id = "checkout-42")
scroll["gateway"] = JsonPrimitive("stripe")
scroll["attempt"] = JsonPrimitive(1)
scroll["retry"] = JsonPrimitive(false)
scroll.seal(BillingScribe, success = true)Each Scribe object has independent configuration and delivery lifecycle. A Scroll is a mutable JSON-element map initialized by newScroll(...); pass the runtime that should enrich and deliver it to scroll.seal(scribe, ...). Each seal(...) call emits a separate SealedScroll snapshot.
Choose the saver that matches your output flow:
val noteSaver = NoteSaver { note -> println(note) }
val scrollSaver = ScrollSaver { scroll -> println(scroll) }
val entrySaver = EntrySaver { record -> println(record) }