luv

Workshop wiki

log.lisp

hal/log.lisp

system luv · 8 definitions · on GitHub

One line per event, for the parts of luv that would otherwise be silent.

luvcraft says nothing at all in ordinary operation. That is comfortable until something stops working, and then there is no record of a window that never appeared, a canvas that stopped pumping, or a swapchain rebuilt on every frame. A timestamped, categorised line on standard error costs nothing while things work and is the whole story when they do not.

This is deliberately not a logging framework. There are no levels, no appenders, and no configuration file: a category, a format string, and a stream that ./sly log already tails. Anything that happens once per frame does not belong here -- the trace zones in trace.lisp exist for that.

in-package#:luv
defparameter*log-enabled-p*t"Whether LOG-EVENT writes anything at all."
defparameter*log-categories*t"T to print every category, or a list of the category names to print."
defvar*log-stream*nil

Where log-event writes, or NIL for the calling thread's *ERROR-OUTPUT*.

A Slynk worker rebinds *ERROR-OUTPUT* to its connection, so leaving this NIL means an event logged while answering ./sly appears in that answer, while the canvas and watchdog threads keep writing to the image's own error stream and therefore to ./sly log.

defvar*log-lock*
sb-thread:make-mutex:name"luv log"
"Held only while one line is written, so threads cannot interleave halves."
defconstant+unix-to-universal-time+
encode-universal-time0001119700
"Seconds between the Unix epoch and the Common Lisp universal time epoch."
defunlog-timestamp-string

Return the wall clock as HH:MM:SS.mmm, in the local zone.

multiple-value-bind
secondsmicroseconds
sb-ext:get-time-of-day
multiple-value-bind
decode-universal-time
formatnil"~2,'0D:~2,'0D:~2,'0D.~3,'0D"hourminutesecond
floormicroseconds1000
defunlog-event
categorycontrol&restarguments

Write one timestamped line about category, formatted from control.

category is a keyword naming the subsystem -- :canvas, :watchdog, :vulkan -- so a reader can tell at a glance which machine is talking.

when
let
text
apply#'formatnilcontrolarguments
stream
or*log-stream**error-output*
sb-thread:with-recursive-lock
formatstream"~&luv ~A ~(~A~) ~A~%"stampcategorytext
force-outputstream
values