# Undead Logging Logging for stupid idiots like me * Pluggable event listeners * Per-source hushing, global log type hushing * Log timing control * Time display modes ```ts import Logging from "@proxnet/undead-logging" const log = new Logging("Main"); log.i("Hello World!"); ``` Disable a source: ```ts // .. logging source is in the scope log.visible = false; log.debug("I can't be seen!"); // no output ``` Change a source's name: ```ts // .. logging source "Main" is in the scope log.n("Network is networking"); log.source = "Main2"; log.n("Something happened"); // output: // 2024-11-14T01:21:40.350Z Main [NETWORK] Network is networking // 2024-11-14T01:21:40.350Z Main2 [NETWORK] Something happened ``` Disable a type of message globally: ```ts import Logging, { MessageTypeVisibility } from "@proxnet/undead-logging"; // .. logging source "Main" is in the scope MessageTypeVisibility.Error = false; // somewhere else, could be a different script log.i("I am visible"); log.error("I am not visible"); // output: // 2024-11-14T01:21:40.350Z Main [INFO] I am visible ``` ## Event Listeners Event listeners are called when a message is logged on any logging source An event callback can either receive messages as either: * Whole lines, including formatting, colors, excluding newlines or * Individual `msg` (string), `type` (MessageType), `source` (string), and `time` (Date) arguments Callback ran when a message is logged anywhere: ```ts LoggingListeners.onmsg('basic', msg => { // `msg` is a string containing the entire line w/ formatting }); ``` Callback ran when a message is logged anywhere (this time components are split up): ```ts LoggingListeners.onmsg('type', (msg, type, source, time) => { // msg: string // type: MessageType - import { MessageType } from "@proxnet/undead-logging"; // source: string // time: Date }); ``` Remove callback: ```ts const cb = msg => { /* do something with msg: string */ }; LoggingListeners.onmsg('basic', cb); LoggingListeners.offmsg('basic', cb); ``` ## Time display modes You can display four different formats for time: * UTC * Unix time (in milliseconds) * Local [process] time (in milliseconds, from the `performance` API) * RoundedLocal: Same as above, but rounded to the nearest whole ms Set the time format: ```ts import { LoggingConfiguration, TimeFormat } from "@proxnet/undead-logging"; LoggingConfiguration.timeFormat = TimeFormat.Local; // or LoggingConfiguration.timeFormat = TimeFormat.Utc; ``` ## (advanced) Logging timing You can control when log functions are executed using `LoggingConfiguration.logTiming`. Logs are sent synchronously by default. You can optionally defer logs with `setImmediate` using `LogTiming.Deferred` ```ts LoggingConfiguration.logTiming = LogTiming.Sync; // or LoggingConfiguration.logTiming = LogTiming.Deferred; ``` You might prefer to defer logs in asynchronous situations where order does not matter and
you'd like to prevent slowing down I/O.
You might also prefer to reset all sources to synchronous logging during app shutdown.
This can help debug issues with how your app closes. (see example below) ## Global resets Every source is tracked by this module in a `Set`. You can reset every source's log timing or time format with `LoggingConfiguration.reset(something)`.
The corresponding property will be updated on `LoggingConfiguration`: ```ts import Logging, { LoggingConfiguration, LogTiming } from "@proxnet/undead-logging"; const log = new Logging("Logger"); log.logTiming = LogTiming.Sync; // the default LoggingConfiguration.resetLogTiming = LogTiming.Deferred; // both are LogTiming.Deferred log.d(`My log timing: LogTiming.${LogTiming[log.logTiming]}`); log.d(`Global: LogTiming.${LogTiming[LoggingConfiguration.logTiming]}`); ``` This is useful when you want to use synchronous logging during a shutdown: ```ts // something is keeping the event loop alive (HTTP server, a database, some I/O?) LoggingConfiguration.logTiming = LogTiming.Deferred; const log = new Logging("Main"); Deno.addSignalListener('SIGINT', () => { LoggingConfiguration.resetLogTiming = LogTiming.Sync; }); ``` See [`tests/shutdown.ts`.](./tests/shutdown.ts) ## [Benchmarks](./BENCH.md) ## Contributing Are you crazy? This ol' thing is just.. "meh" at most. You're sure? ... anyway, create an account on gitea.proxnet.dev, fork, then PR.