[][src]Crate delog

Deferred logging, for instance for printf()-debugging (a.k.a tracing)

This is an implementation of the log::Log trait, suitable for use in both embedded and desktop environments.

Compared to existing approaches such as ufmt, cortex-m-funnel and defmt, we pursue different values and requirements, namely:

  • compatibility with the standard core::fmt traits and the standard log library API. This means that, while libraries may "upgrade" their logging capabilities by using delog as drop-in replacement for their logging calls (see below), any existing library that already uses log is compatible. This, for our use cases, is a huge win, as opposed to using up "weirdness budget" and requiring custom tooling for something that is often trivial, throw-away, simple logging.
  • it follows that one can easily drop a trace!("{:?}", &suspicious_object) call at any time for any object that has a (possibly automatically derived) Debug trait implementation – without passing around structures and keeping on top of lifetimes.
  • deferred logging: This is a typical "shared memory" logger, calls to info! etc. are not directly sent to their final output, but instead are stored in a circular buffer that is "drained" by calling flush on the logger at a convenient moment, for instance in an idle loop.
  • immediate mode logging: Sometimes one wants to bypass the deferred flushing of logs, this is possible using either the little-known target argument to info! and friends with "!" as parameter, or using the additional immediate_info! and friends macros.
  • ability to set log levels per library, at compile-time. This can be easily retro-fitted on existing log-based libraries, by adding the requisite features in Cargo.toml and replacing log with delog (see gate-tests for examples of this).
  • the outcome is that one can leave useful logging calls in the library code, only to activate them in targeted ways at build time, exactly as needed.
  • helper macros to easily output binary byte arrays and slices in hexadecimal representations, which wrap the data in newtypes with custom fmt::UpperHex etc. implementations.

Non-goals:

  • ultimate speed or code size: Our intention are "normal" logs, not the use of logging/tracing to for stream binary data to the host. While admittedly the core::fmt-ing facilities are not as efficient as one might hope, in our use cases we have sufficient flash and RAM to use these (and some hope that, someday, eventually, maybe, the formatting machinery will be revisited and improved at the root level, namely the language itself.)

That said, we believe there is opportunity to extend delog in the defmt direction by using, e.g., the fmt::Binary trait, newtypes and sentinel values to embed raw binary representations of data in time-critical situations without formatting, deferring the extraction and actual formatting to some host-side mechanism.

Features

The flushers and semihosting features mostly exist to share code within the examples, including the example feature. Without them, dependencies are quite minimal, and compilation fast.

The fallible and immediate features (default on) activate the try_*! and *_now! macros, respectively.

Warning

The current circular buffer implementation (v0.1.0) is definitely unsound on desktop. For embedded use, atomics are required (so no Cortex-M0/M1, and no plans to support non-atomic platforms, which are likely to also be too resource-constrained to support the bloat inherent in core::fmt). While we think the implemented circular buffer algorithm works for the "nested interrupt" setup of NVICs, it has not been tested much. The hope is that the worst case scenario is some slightly messed up log outputs.

Outlook

We plan to iterate towards a v0.2.0 soon, making use of a separate "flusher" for the "immediate" logging path. For instance, when logging via serial-over-USB, one might want immediate logs to pend a separate RTIC interrupt handler that blocks until the logs are pushed and read (allowing one to debug the boot process of a firmware), or one might want to just write to RTT (or even semihosting xD) for these, during development.

Re-exports

pub use log as upstream;

Modules

example

An example deferred logger, generated as delog!(Delogger, 4096, StdoutFlusher).

flushers

Typical flushers in various environments.

hex

Convenient Display and other traits for binary data.

render

A lone helper function to render formatting arguments.

Macros

debug

Logs a message at the debug level.

debug_now

Immediate version of debug!.

delog

Generate a deferred logger with specified capacity and flushing mechanism.

error

Logs a message at the error level.

error_now

Immediate version of error!.

hex_str

Compactly format byte arrays and slices as hexadecimals.

hexstr

More compactly format byte arrays and slices as hexadecimals.

info

Logs a message at the info level.

info_now

Immediate version of info!.

local_debug

Local version of debug!.

local_delog

Generate logging macros that can be gated by library.

local_error

Local version of error!.

local_info

Local version of info!.

local_log

Local version of log!.

local_trace

Local version of trace!.

local_warn

Local version of warn!.

log

The standard logging macro.

log_enabled

Determines if a message logged at the specified level in that module will be logged.

log_now

Immediate version of log!.

trace

Logs a message at the trace level.

trace_now

Immediate version of trace!.

try_debug

Fallible version of debug!.

try_debug_now

Fallible immediate version of debug!.

try_error

Fallible version of error!.

try_error_now

Fallible immediate version of error!.

try_info

Fallible version of info!.

try_info_now

Fallible immediate version of info!.

try_log

Fallible version of log!.

try_log_now

Fallible immediate version of log!.

try_trace

Fallible version of trace!.

try_trace_now

Fallible immediate version of trace!.

try_warn

Fallible version of warn!.

try_warn_now

Fallible immediate version of warn!.

upstream

The standard logging macro.

warn

Logs a message at the warn level.

warn_now

Immediate version of warn!.

Structs

Statistics

Statistics on logger usage.

Enums

Level

An enum representing the available verbosity levels of the logger.

LevelFilter

An enum representing the available verbosity level filters of the logger.

Traits

Delogger

Semi-abstract characterization of the deferred loggers that the delog! macro produces.

Flusher

A way to pass on logs, user supplied.

TryLog

Fallible, panic-free version of the log::Log trait.

TryLogWithStatistics

TryLog with some usage statistics on top.

Functions

dequeue

The core "read from circular buffer" method. Marked unsafe to discourage use!

enqueue

The core "write to circular buffer" method. Marked unsafe to discourage use!

try_enqueue

The fallible "write to circular buffer" method. Marked unsafe to discourage use!

trylogger

Returns a reference to the logger (as TryLogWithStatistics implementation)