13.6 Logging
A logger created with Logger accepts events that contain information to be logged for interested parties. A log receiver created with LogReceiver represents an interested party that receives logged events asynchronously. Each event has a topic and level of detail, and a log receiver subscribes to logging events at a certain level of detail (and lower) for a specific topic or for all topics. The levels (see Logger.Level) in increasing order of detail are #'none, #'fatal, #'error, #'warning, #'info, and #'debug. The #'none level is intended for specifying receivers, and messages logged at that level are never sent to receivers.
To help organize logged events, a logger can have a default topic and/or a parent logger. Every event reported to a logger is normally propagated to its parent (if any), and the event message is prefixed with the logger’s topic (if any) if the message doesn’t already have a topic. Events that are propagated from a logger to its parent can be filtered by level and topic.
> def r = LogReceiver(~logger: l, ~receive: #'warning)
> r.sync()
Array.snapshot(Array(#'error, "example: something is wrong", #false, #'example))
> l.debug("detailed information") // no receiver interested in debug
> r.sync(~timeout: 0)
#false
On start-up, Rhombus creates an initial logger that is used to record events from the core run-time system. For example, a #'debug event is reported for each garbage collection. For this initial logger, three log receivers are also created: one that writes events to the process’s original error output port, one that writes events to the process’s original output port, and one that writes events to the system log. The level of written events in each case is system-specific, and the default can be changed through environment variables:
If the PLTSTDERR environment variable is defined, it determines the level of the log receiver that propagates events to the original error port.
The environment variable’s value can be a ‹level›: none, fatal, error, warning, info, or debug (from low detail to high detail); all events at the corresponding level of detail or lower are printed. In addition to a ‹level›, the value can contain whitespace-separated specifications of the form ‹level›@‹topic›, which prints events whose topics match ‹topic› only at the given ‹level› or higher (where a ‹topic› contains any character other than whitespace or @. Leading and trailing whitespace is ignored. For example, the value error debug@GC prints all events at the #'error level and higher, but prints events for the topic #'GC at the #'debug level and higher (which includes all levels).
The default is error.
If the PLTSTDOUT environment variable is defined, it determines the level of the log receiver that propagates events to the original output port. The possible values are the same as for PLTSTDERR.
The default is none.
If the PLTSYSLOG environment variable is defined and is not overridden by a command-line flag, it determines the level of the log receiver that propagates events to the system log. The possible values are the same as for PLTSTDERR.
The default is none for Unix or error for Windows and Mac OS.
The Logger.current parameter determines the current logger, and log is a shorthand for Logger.current(). On start-up, the initial value of the parameter is the initial logger. The run-time system sometimes uses the current logger to report events. For example, the compiler sometimes reports #'warning events when it detects an expression that would produce a run-time error if evaluated.
> block:
#'done
error
#'done
class | ||||||||
|
The propagate argument controls which events reported to the logger are propagated to parent. If propagate is an immediate Logger.Level, then it is a shorthand for {#false: propagate}. As a map, propagate maps a topic to a maximum level of detail that is propagated for that topic, and #false is mapped to default maximum level of detail that applies to any topic not explicitly mapped.
context parameter | |
| |
expression | |
The log expression form is a shorthand for Logger.current(). For example, log.error("oops") logs the message "oops" to the current logger.
Each time the log expression form is evaluated or Logger.current() is used to obtain the current logger, the resulting object can be different accoring to ===, but the underlying Racket-level logger (accessible via Logger.handle) remains the same if the logger is not changed; two loggers are == when the underlying Racket logger is the same. Adjusting the Logger.current context parameter also adjusts the current logger at the Racket level.
expression | ||||||||||||
| ||||||||||||
expression | ||||||||||||
| ||||||||||||
expression | ||||||||||||
| ||||||||||||
expression | ||||||||||||
| ||||||||||||
expression | ||||||||||||
| ||||||||||||
|
Each event has a string message and an additional data value, where the additional data defaults to #false.
method | |||||||
|
If add_prefix is true and topic is a symbol, then topic +& ": " +& msg is logged as the event’s message string, instead of just msg.
Use log.show as an alternative to showln for temporary debugging output. The intent of logging the same as Logger.error is to print at a low enough level of detail that a logger is likely to write synchronously to the original error output port.
method | ||||
| ||||
| ||||
method | ||||
| ||||
| ||||
method | ||||
| ||||
| ||||
method | ||||
The Logger.max_at_level method reports the most specific Logger.Level value for which lg.is_at will return #true.
The Logger.all_at_levels method summarizes the possible results of Logger.is_at across all topics. Similar to the ~propagate argument to the Logger constructor, a #false key in the result map indicates a level for all topics no otherwise mapped.
The Logger.level_change_evt method returns a synchronizable event that becomes ready at a point where the result of Logger.all_at_levels could be different than its current result.
class | ||||||||
|
The receive argument is analogous to the ~propagate argument to the Logger constructor, and it determines the events that logger will send to the new receiver. A log receiver’s events are queued internally.
An instance of LogReceiver is a synchronizable event, and it’s synchronization result is an array representation of an event. For example, use the Evt.sync to dequeue an event from the receiver when one is ready. The synchronization result is an immutable array of four values:
a Logger.Level symbol for the level of the event;
a String for the event message;
an arbitrary value for the event’s data; and
a Symbol or #false for the event’s topic.
For example, if a log receiver is interested in events at the #'warning level, it will also receive events at the #'error and #'fatal levels.
property | |
| |
property | |
| |
| |
function | |
| |
function | |