Skip to content

Getting Started

Add Scribe to commonMain

Use the library from shared code in your Kotlin Multiplatform module:

kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation("com.rafambn:scribe:0.1.0")
        }
    }
}

Create a Minimal Scribe

The smallest setup is a single saver. A NoteSaver only receives Note events:

val scribe = Scribe(
    shelf = NoteSaver { note ->
        println("[${note.level}] ${note.tag}: ${note.message}")
    }
)

Emit a Single Event

Use note(...) when you can suspend and want delivery through the internal queue:

scribe.note(
    tag = "payments",
    message = "starting checkout",
    level = Urgency.INFO,
)

If you need best-effort fire-and-forget behavior, use flingNote(...):

scribe.flingNote(
    tag = "payments",
    message = "checkout queued",
    level = Urgency.DEBUG,
)

With the saver above, the log output looks like this:

[INFO] payments: starting checkout

Track a Flow with Scroll

Scroll is for multi-step operations where context accumulates before a final result is emitted.

val scribe = Scribe(
    shelf = ScrollSaver { scroll ->
        println(scroll)
    },
    imprint = mapOf(
        "service" to JsonPrimitive("billing"),
        "environment" to JsonPrimitive("production"),
    )
)

val scroll = scribe.unrollScroll(id = "checkout-42")
scroll.writeString("gateway", "stripe")
scroll.writeNumber("attempt", 1)
scroll.writeBoolean("retry", false)
scroll.seal(success = true)

The emitted SealedScroll would look like this in JSON:

{
  "scrollId": "checkout-42",
  "success": true,
  "errorMessage": null,
  "context": {
    "service": "billing",
    "environment": "production"
  },
  "data": {
    "gateway": "stripe",
    "attempt": 1,
    "retry": false
  }
}

Then in the saver you can manage this output whatever you want to save to you database or send to the cloud.

Choose the Right Saver

val noteSaver = NoteSaver { note -> println(note) }
val scrollSaver = ScrollSaver { scroll -> println(scroll) }
val entrySaver = EntrySaver { entry -> println(entry) }
  • NoteSaver handles only Note
  • ScrollSaver handles only SealedScroll
  • EntrySaver handles both