Debug Logger
posipaki/plugins/debug-loggerdecoratesthis.logand traces an actor's lifecycle and message traffic. Useful for developing, or wired to a ringbuffer for on-demand inspection.
Install
debugLogger() is a factory — call it and put the returned plugin in the
actor's plugins:
import { defineActor } from "posipaki";
import { debugLogger } from "posipaki/plugins/debug-logger";
const actor = defineActor({
plugins: [debugLogger()],
handlers: {},
});
this.log
The plugin decorates the handler context with a Logger, typed automatically
(see the Plugins page on type augmentation):
handlers: {
POKE() {
this.log.info("got a poke");
this.log.debug("state", this.state);
},
},
Logger has six methods:
| method | signature | used for |
|---|---|---|
debug / info / warn / error |
(message, ...args) |
free-form logging |
msg |
(message: Message) |
an incoming message |
lifecycle |
(event, detail?) |
a lifecycle event |
What it observes
Out of the box the plugin hooks the actor and logs:
- lifecycle —
started,stopping,stopped,child-exited - incoming — every message (
onMessage) - outgoing — every emit (
onEmit) - errors — handler/hook throws (
onError)
The plugin only observes errors: it logs them and returns nothing, so it never
changes failure semantics. Lifecycle hook errors stay fatal (see
onError); what an observing handler absorbs is the message-hook
and handler errors.
Options
debugLogger({
ignore: ["TICK"], // message types to skip entirely
factory: (name) => myLogger(name),
msgFilter: (msg) => msg,
});
ignore— message types skipped by bothonMessageandonEmit.factory— a(name) => Loggerfunction. The default prints to the console; swap it for a ringbuffer (or anything else) to gate output at runtime.msgFilter—(msg) => Message | null. Return a (possibly shrunk) message, ornullto drop it before logging.
Shrinking big payloads
The default msgFilter is defaultMsgFilter, which shrinks oversized fields
in place so a single message (a full conversation history, a big tool result)
can't flood the log: strings over 256 chars and arrays over 16 items are
replaced with a summary.
import { defaultMsgFilter } from "posipaki/plugins/debug-logger";
const myFilter = (msg) => {
if (msg.type === "SYSTEM_PROMPT") return null; // drop it
return defaultMsgFilter(msg);
};
Custom factory — a ringbuffer
factory receives the actor's name and returns any Logger. Point it at a
ringbuffer and you keep the last N entries in memory, printing only when asked:
import { debugLogger, type Logger } from "posipaki/plugins/debug-logger";
const ring: Array<[string, unknown]> = [];
const factory = (name: string): Logger => ({
debug: (m, ...a) => ring.push([`${name} ${m}`, a]),
info: (m, ...a) => ring.push([`${name} ${m}`, a]),
warn: (m, ...a) => ring.push([`${name} ${m}`, a]),
error: (m, ...a) => ring.push([`${name} ${m}`, a]),
msg: (msg) => ring.push([`${name} ←`, msg]),
lifecycle: (e, d) => ring.push([`${name} lifecycle ${e}`, d ?? ""]),
});
debugLogger({ factory });
See Plugins for how plugins register hooks and decorations.