#lang scribble/manual @(require (for-label racket/base)) @title{simple-log} @author[@author+email["Hans Dijkema" "hans@dijkewijk.nl"]] A small logging layer on top of Racket’s logger system. A log definition creates a logger plus five convenience procedures. Messages are formatted with @racket[format], timestamped, and dispatched asynchronously to the registered callbacks. @section{API} @defmodule["simple-log"] @defform*[((sl-def-log id) (sl-def-log id name) (sl-def-log id name parent))]{ Defines a logger with topic @racket['id] and creates: @itemlist[#:style 'compact @item{@racket[dbg-id]} @item{@racket[info-id]} @item{@racket[warn-id]} @item{@racket[err-id]} @item{@racket[fatal-id]} ] Note. If name is given, id @racket[dbg-prefix], etc. will be generated instead of @racket[dbg-id], etc. Each procedure has shape: @racketblock[ (proc msg arg ...) ] The message is formatted via @racket[format] and emitted with a timestamp (@litchar{YYYY-MM-DDTHH:MM:SS}) and topic @racket['id]. If @racket[parent] is omitted, the @racket[#f] is used as "parent logger". A background thread is started that receives log events and forwards them to the registered callbacks. } @defform[(sl-log-to name callback)]{ Registers @racket[callback] under the symbolic name derived from @racket[name]. @racket[name] is an identifier (not a runtime value). It is converted at macro expansion time to a symbol and used as key in the callback registry. Invocation shape: @racketblock[ (callback topic level timestamp message) ] with: @itemlist[#:style 'compact @item{@racket[topic] — logger topic (symbol)} @item{@racket[level] — level (symbol)} @item{@racket[timestamp] — @litchar{YYYY-MM-DDTHH:MM:SS}} @item{@racket[message] — formatted string} ] An existing callback with the same name is replaced. } @defproc[(sl-log-to-file [filename path-string?]) void?]{ Registers a callback that writes log lines to @racket[filename]. The file is opened with @racket['replace]. Format: @racketblock[ ":::" ] } @defproc[(sl-log-to-display) void?]{ Registers a callback that writes log lines to the current output port using @racket[displayln]. Format: @racketblock[ ":::" ] } @defproc[(sl-log-to-file&display [filename path-string?]) void?]{ Equivalent to combining @racket[sl-log-to-display] and @racket[sl-log-to-file]. } @defproc[(sl-set-log-level [l (or/c 'debug 'dbg 'info 'warning 'warn 'error 'err 'fatal)]) symbol?]{ Sets the module-wide log level and returns the normalized symbol. Aliases: @itemlist[#:style 'compact @item{@racket['dbg] → @racket['debug]} @item{@racket['warn] → @racket['warning]} @item{@racket['err] → @racket['error]} ] Other values raise an exception. Note: this value is stored globally. The receiver installed by @racket[sl-def-log] itself operates at level @racket['debug]. } @defproc[(sl-log-level) symbol?]{ Returns the current module-wide log level (default @racket['debug]). } @section{Generated procedures} A call to @racket[sl-def-log] creates five procedures. For example: @racketblock[ (sl-def-log my-module) ] creates: @defproc[#:link-target? #f (dbg-my-module [msg string?] [arg any/c] ...) void?]{Debug log.} @defproc[#:link-target? #f (info-my-module [msg string?] [arg any/c] ...) void?]{Info log.} @defproc[#:link-target? #f (warn-my-module [msg string?] [arg any/c] ...) void?]{Warning log.} @defproc[#:link-target? #f (err-my-module [msg string?] [arg any/c] ...) void?]{Error log.} @defproc[#:link-target? #f (fatal-my-module [msg string?] [arg any/c] ...) void?]{Fatal log.} All use @racket[format] and emit asynchronously.