-
This commit is contained in:
@@ -1,90 +1,151 @@
|
||||
#lang scribble/manual
|
||||
|
||||
@(require (for-label racket/base
|
||||
racket/date
|
||||
racket/logging
|
||||
racket-sprintf))
|
||||
|
||||
@defmodule{simple-log}
|
||||
|
||||
@title{Logging}
|
||||
@(require (for-label racket/base))
|
||||
|
||||
@title{simple-log}
|
||||
@author[@author+email["Hans Dijkema" "hans@dijkewijk.nl"]]
|
||||
|
||||
@section{Overview}
|
||||
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.
|
||||
|
||||
Small wrapper around @racket[logger] with per-logger callbacks.
|
||||
@section{API}
|
||||
|
||||
A logger consists of a @racket[logger], a
|
||||
@racket[log-receiver] (level @racket['debug]), a mutable
|
||||
callback list, five logging procedures, and a background thread
|
||||
dispatching messages.
|
||||
@defmodule["simple-log"]
|
||||
|
||||
@section{Definition}
|
||||
@defform*[((sl-def-log id)
|
||||
(sl-def-log id parent))]{
|
||||
|
||||
@defform*[((def-log id)
|
||||
(def-log id parent))]{
|
||||
Defines a logger with topic @racket['id] and creates:
|
||||
|
||||
Defines a logger @racket[id]. If @racket[parent] is omitted,
|
||||
@racket[(current-logger)] is used.
|
||||
|
||||
Creates:
|
||||
|
||||
@itemlist[
|
||||
#:style 'compact
|
||||
@item{@racket[(make-logger 'id parent)]}
|
||||
@item{@racket[(make-log-receiver ... 'debug)]}
|
||||
@item{callback list}
|
||||
@item{procedures @racket[dbg-id], @racket[info-id],
|
||||
@racket[warn-id], @racket[err-id], @racket[fatal-id]}
|
||||
@itemlist[#:style 'compact
|
||||
@item{@racket[dbg-id]}
|
||||
@item{@racket[info-id]}
|
||||
@item{@racket[warn-id]}
|
||||
@item{@racket[err-id]}
|
||||
@item{@racket[fatal-id]}
|
||||
]
|
||||
|
||||
Starts a thread that @racket[sync]s on the receiver and forwards
|
||||
messages to callbacks.
|
||||
}
|
||||
|
||||
@section{Logging functions}
|
||||
|
||||
@defproc[(dbg-id [msg string?] [arg any/c] ...) void?]
|
||||
@defproc[(info-id [msg string?] [arg any/c] ...) void?]
|
||||
@defproc[(warn-id [msg string?] [arg any/c] ...) void?]
|
||||
@defproc[(err-id [msg string?] [arg any/c] ...) void?]
|
||||
@defproc[(fatal-id [msg string?] [arg any/c] ...) void?]
|
||||
|
||||
Formats with @racket[(apply format (cons msg args))] and calls
|
||||
@racket[log-message].
|
||||
|
||||
Attached data:
|
||||
Each procedure has shape:
|
||||
|
||||
@racketblock[
|
||||
(list (iso-timestamp) 'id)
|
||||
(proc msg arg ...)
|
||||
]
|
||||
|
||||
@section{Callbacks}
|
||||
The message is formatted via @racket[format] and emitted with a timestamp
|
||||
(@litchar{YYYY-MM-DDTHH:MM:SS}) and topic @racket['id].
|
||||
|
||||
@defform[(log-to id name callback)]{
|
||||
If @racket[parent] is omitted, the current logger is used.
|
||||
|
||||
Registers @racket[callback] under @racket[name]. Existing entry
|
||||
with same name is replaced.
|
||||
A background thread is started that receives log events and forwards them
|
||||
to the registered callbacks.
|
||||
}
|
||||
|
||||
Callback signature:
|
||||
@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[
|
||||
(λ (topic level dt msg) ...)
|
||||
(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[
|
||||
"<topic>:<level>:<timestamp>:<message>"
|
||||
]
|
||||
}
|
||||
|
||||
@section{Output helpers}
|
||||
@defproc[(sl-log-to-display) void?]{
|
||||
|
||||
@defform[(log-to-display id)]{
|
||||
Registers a callback that writes log lines to the current output port
|
||||
using @racket[displayln].
|
||||
|
||||
Registers @racket['display]. Output:
|
||||
Format:
|
||||
|
||||
@verbatim{topic:level:timestamp:message}
|
||||
@racketblock[
|
||||
"<topic>:<level>:<timestamp>:<message>"
|
||||
]
|
||||
}
|
||||
|
||||
@defform[(log-to-file id filename)]{
|
||||
@defproc[(sl-log-to-file&display [filename path-string?]) void?]{
|
||||
|
||||
Registers @racket['file]. File opened with
|
||||
@racket[#:exists 'replace]. One line per message, flushed.
|
||||
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.
|
||||
@@ -1,109 +0,0 @@
|
||||
#lang scribble/manual
|
||||
|
||||
@(require (for-label racket/base
|
||||
racket/date
|
||||
racket/logging
|
||||
racket-sprintf))
|
||||
|
||||
@title{Logging}
|
||||
|
||||
@author[@author+email["Hans Dijkema" "hans@dijkewijk.nl"]]
|
||||
|
||||
@section{Overview}
|
||||
|
||||
Small wrapper around @racket[logger] with per-logger callbacks.
|
||||
|
||||
A logger consists of a @racket[logger], a
|
||||
@racket[log-receiver] (level @racket['debug]), a mutable
|
||||
callback list, five logging procedures, and a background thread
|
||||
dispatching messages.
|
||||
|
||||
@section{Definition}
|
||||
|
||||
@defform*[([(def-log id)]
|
||||
[(def-log id parent)])]{
|
||||
|
||||
Defines a logger @racket[id]. If @racket[parent] is omitted,
|
||||
@racket[(current-logger)] is used.
|
||||
|
||||
Creates:
|
||||
|
||||
@itemlist[
|
||||
#:style 'ordered
|
||||
@item{@racket[(make-logger 'id parent)]}
|
||||
@item{@racket[(make-log-receiver ... 'debug)]}
|
||||
@item{callback list}
|
||||
@item{procedures @racket[dbg-id], @racket[info-id],
|
||||
@racket[warn-id], @racket[err-id], @racket[fatal-id]}
|
||||
]
|
||||
|
||||
Starts a thread that @racket[sync]s on the receiver and forwards
|
||||
messages to callbacks.
|
||||
}
|
||||
|
||||
@section{Logging}
|
||||
|
||||
@defproc[(dbg-id [msg string?] [arg any/c] ...) void?]
|
||||
@defproc[(info-id [msg string?] [arg any/c] ...) void?]
|
||||
@defproc[(warn-id [msg string?] [arg any/c] ...) void?]
|
||||
@defproc[(err-id [msg string?] [arg any/c] ...) void?]
|
||||
@defproc[(fatal-id [msg string?] [arg any/c] ...) void?]
|
||||
|
||||
Formats with @racket[(apply format (cons msg args))] and calls
|
||||
@racket[log-message].
|
||||
|
||||
Attached data:
|
||||
|
||||
@racketblock[
|
||||
(list (iso-timestamp) 'id)
|
||||
]
|
||||
|
||||
@section{Callbacks}
|
||||
|
||||
@defform[(log-to id name callback)]{
|
||||
|
||||
Registers @racket[callback] under @racket[name]. Existing entry
|
||||
with same name is replaced.
|
||||
|
||||
Callback signature:
|
||||
|
||||
@racketblock[
|
||||
(λ (topic level dt msg) ...)
|
||||
]
|
||||
}
|
||||
|
||||
@section{Output helpers}
|
||||
|
||||
@defform[(log-to-display id)]{
|
||||
|
||||
Registers @racket['display]. Output:
|
||||
|
||||
@verbatim{topic:level:timestamp:message}
|
||||
}
|
||||
|
||||
@defform[(log-to-file id filename)]{
|
||||
|
||||
Registers @racket['file]. File opened with
|
||||
@racket[#:exists 'replace]. One line per message, flushed.
|
||||
}
|
||||
|
||||
@section{Timestamp}
|
||||
|
||||
@defproc[(iso-timestamp) string?]{
|
||||
|
||||
Returns @verbatim{YYYY-MM-DDTHH:MM:SS} using
|
||||
@racket[seconds->date] and @racket[sprintf].
|
||||
}
|
||||
|
||||
@section{Execution}
|
||||
|
||||
Per logger thread:
|
||||
|
||||
@itemlist[
|
||||
#:style 'ordered
|
||||
@item{@racket[sync] receiver}
|
||||
@item{extract level, msg, data}
|
||||
@item{dispatch callbacks}
|
||||
]
|
||||
|
||||
Callbacks run sequentially in that thread.
|
||||
Reference in New Issue
Block a user