A structured logging library for Luau that runs on both Lute and Roblox.
Note
Archivist is pre-release and under active development. The API may change before v1.
- Dual runtime: one library, first-class support for Lute (CLI) and Roblox
- Log levels:
trace,debug,info,warn,err, filtered by a minimum level LOG_LEVEL: level resolution from the environment on Lute,_G.LOG_LEVELon Roblox- Colorful output: ANSI-colored console output on Lute; plain
print/warnon Roblox - Structured records: every entry is a
LogRecordobject (timestamp, level, name, args) that sinks can consume - Sinks: route records anywhere: console, files (Lute), or your own callback (e.g. an in-app log viewer)
- Dev/prod deferral: sequential
print-like output in dev; in prod, records batch and each sink is written once per batch instead of once per record
Add to your loom.config.luau dependencies:
Archivist = {
rev = "v0.1.0",
sourceKind = "github",
source = "https://github.com/flipbook-labs/archivist",
},Then run lute pkg install.
[dependencies]
Archivist = "flipbook-labs/archivist@0.1.0"local Archivist = require("@pkg/Archivist")
local logger = Archivist.createLogger("MyModule")
logger.info("loaded", 3, "stories")
logger.info("structured data:", { port = 8080, ready = true })
logger.warn("something looks off")
logger.err("something broke")
-- Children share the parent's sinks and attach fields to every record:
local child = logger.child("requests", { requestId = "abc123" })
child.debug("handling request")
-- Prod mode batches: these queue and flush to each sink as ONE write.
local batched = Archivist.createLogger("Telemetry", { mode = "Prod" })
batched.info("queued 1")
batched.info("queued 2")
batched.flush() -- optional; pending batches also flush on defer and at exit
-- Show everything, regardless of LOG_LEVEL:
local verbose = Archivist.createLogger("MyModule", { level = "Trace" })The default console formatter emits the level and message:
[info] loaded 3 stories
Add the built-in middleware when you want logger names or timestamps:
local logger = Archivist.createLogger("MyModule", {
middleware = {
Archivist.middleware.name,
Archivist.middleware.timestamp,
},
})Middleware runs in declaration order. Each function receives the formatted line and a context containing the structured record, platform, color setting, and a color-aware style helper. It can prepend, append, or replace text.
The logger-level middleware option configures its default console sink. When you provide sinks, pass middleware to the pretty formatter instead:
local formatter = Archivist.createPrettyFormatter({
middleware = {
Archivist.middleware.name,
},
})
local logger = Archivist.createLogger("MyModule", {
sinks = {
Archivist.createConsoleSink({ formatter = formatter }),
},
})local logger = Archivist.createLogger("App", {
sinks = {
-- The runtime's console: colored stdout on Lute, print/warn on Roblox.
Archivist.createConsoleSink(),
-- Any custom destination, e.g. an in-app log viewer panel:
Archivist.createCallbackSink(function(record)
LogsStore.addLine(record)
end),
-- A JSON-lines log file (Lute only):
Archivist.createFileSink({ path = "logs/app.log" }),
-- Ship batches to an external platform; bring your own HTTP client:
Archivist.createTransportSink({
batchSize = 50,
send = function(records)
httpClient.post(INGEST_URL, records)
end,
}),
},
})Formatters control how text-oriented sinks render records: createPrettyFormatter (human-readable, optional ANSI color and middleware) and createJsonFormatter (one JSON object per line). Sinks that consume records structurally (createCallbackSink, createTransportSink) bypass formatting entirely.
The minimum level resolves from, in order: the level option, the LOG_LEVEL
environment variable (Lute), _G.LOG_LEVEL (Roblox), then defaults to info.
Archivist.getLogger(name) returns a per-name cached logger so modules can
share one configured logger without threading it through requires.
Archivist uses Rokit for toolchain management.
rokit install
lute run example # run the demo script under Lute
lute test # run the unit tests
lute run build # build the Roblox model (Archivist.rbxm)