The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
NDJSON schema: a "json" sink’s ts is
now ISO-8601 to the millisecond with a UTC offset
("2026-01-02T03:04:05.000+0000") instead of a bare epoch
number, and every record carries a run_id so one run can be
picked out of a shared file. The id is derived from the wall clock, the
pid and a session counter, so it never perturbs the RNG stream; it is
refreshed per with_logging() call and per
logtree_reset().
Verbosity is now a rendering gate only. A warning
suppressed by logtree_threshold("error") still reaches the
logtree_summary() digest (it already elevated its step’s
close glyph). summary = TRUE/FALSE still pin
and exclude a line as before.
New sink registry: logtree_sink(fn) registers any
function of one argument and returns an id, logtree_sinks()
lists ids in firing order, and logtree_sink_remove(id)
unregisters, handing back the removed functions so the removal can be
undone. logtree_sink_file() now returns an id too; the
console sink lives under the reserved id "console". A sink
that throws is skipped with a single warning rather than breaking the
fanout. logtree_reset() still leaves sinks alone – they are
configuration, and removal is the explicit path.
New memory sink for asserting on your own logging:
logtree_sink_memory(max = 1000) buffers events and
logtree_sink_memory_events(id) reads them back as a data
frame, one row per event – so a test can ask did this pipeline log
what it should without pattern-matching console glyphs. Its columns
are a "json" sink’s columns, enforced by a shared
event_record(), so a replayed log file and the same run
read from memory cannot disagree.
Per-sink verbosity: logtree_sink_file(),
logtree_sink() and logtree_sink_memory() take
threshold =, so a log file can capture everything without
dragging the console down with it. The global
logtree_threshold() is the default for sinks that do not
pin one, read afresh per event. Step open/close lines are never
gated.
New logtree_mute() / logtree_unmute()
and a logtree.silent option read at load: gates the fanout
while leaving the registry untouched, so a library can silence its own
test suite without discarding its sink configuration. Both return the
state they replaced. A muted run is still recorded (the flag is
checked after the digest sees the event), so
logtree_summary() still prints when called; only the
unasked-for with_logging() run-summary line is suppressed.
Depth bookkeeping is untouched, and the flag survives
logtree_reset().
New trace slot: an opt-in call-site column saying
where in your code a line came from.
list(trace = list(show = "problems")) annotates
warning/error leaves and interrupted steps; show = TRUE
covers every line that can carry one; show also takes
statuses directly ("error",
c("error", "interrupted"), "running"). An
ordinary close line never carries one – its site is its own open line’s.
The same filter governs the logtree_summary() digest, and
logtree_summary(trace = ) pins it for a single call the way
gap and rule do; it can only narrow what was
captured, which is what capture = TRUE is for (record
everywhere, print nothing – a quiet tree with an annotated digest or
"json" sink). Content is a template over {fn},
{file}, {line} (default
"{file}:{line} {fn}()"), styled by
color = list(base=, location=, fn=); the location is
printed relative to the working directory and emitted as a terminal
hyperlink. It is appended to the message, so it wraps with it and never
shears the tree. logtree_sink_file() gains a
trace argument. {file}/{line}
need keep.source (absent under plain Rscript);
runs whose placeholders are all missing are dropped rather than rendered
as NA. show is FALSE in all five
presets, and with it off nothing is captured. Two call sites were fixed
to make this honest: an error caught by with_logging() now
traces to the condition’s own call rather than to the calling handler,
and a logger line now uses the .topcall it
passes in rather than tracing to layout_logtree().
New timestamp slot: an opt-in wall-clock column in
front of every line.
list(timestamp = list(format = "%H:%M:%S")) switches it on;
NULL (all five presets) is off. Width is measured from a
rendered sample, not the format string, since "%B" is five
columns in March and eight in December. It counts against the wrapping
budget, and a wrapped message’s continuation rows carry a blank column –
one event happened once. The with_logging() run-summary
line is stamped; the logtree_summary() digest is not, since
it replays events that already happened.
logtree_sink_file() gains a timestamp
argument.
New elapsed slot for the time column on close lines:
show = FALSE drops it, min hides anything
faster than a threshold (silencing 0.00s noise),
color styles it, and slow +
slow_color restyle the ones worth noticing. The run-summary
line takes the colouring but never the hiding rules. Defaults leave
output unchanged.
New done slot: a step’s own close line is styled
separately from log_success() leaves, which keep
success. Every preset ships the same glyph in both, so
default output is unchanged.
The word a step prints when it closes is themeable via a
text field on a status slot, read from the closing status’s
slot and falling back to done’s then "Done" –
so list(done = list(text = "Complete")) renames every close
line and list(error = list(text = "Failed")) only the
failures. text = "" drops the word; {label}
and {elapsed} are expanded, and a template placing
{elapsed} itself owns that column.
New crumb slot (glyph,
color, path_color) for
logtree_summary() breadcrumbs: path nodes carry an emphasis
and the separator its own dimmer style, while a leaf’s message stays
unstyled. An angle quote in the unicode and emoji presets, plain
> in ascii.
New summary slot (gap,
rule, line): logtree_summary()
now sets its digest off from the tree with a blank gap and a
cli rule labelled with the counts, so it reads as its own
block. gap and rule override the layout for a
single call (rule = FALSE restores the old plain header, a
string titles the rule).
Two new horizontal knobs on logtree_theme():
glyph_gap (spaces between a line’s status glyph and its
message, applied to every line kind so the message column stays aligned)
and connector_gap (spaces between a leaf or close
line’s connector and its glyph). connector_gap tracks
col_gap unless set, so compact = "tight" can
keep rail columns flush while leaf glyphs still get air
(|- i msg rather than |-i msg); it never
touches a step’s open line or a group header, and does not compound with
depth. Both default to existing behaviour.
New "ci" preset: bracketed word glyphs
([step], [info], [debug],
[ok], [done], [warn],
[fail], [break]) over pure-ASCII connectors
with no colour, so a captured build log survives a runner that strips
ANSI and mangles UTF-8 and a failure greps as [fail]. Each
word declares its true width, so the message column still lines up;
unlike ascii, the corner (\-) differs from the
branch (|-).
New "minimal" preset: no tree connectors at all –
depth is carried by indentation alone (two columns per level), so output
stays legible where box-drawing characters do not survive. Also a
lighter glyph vocabulary, dimmed elapsed times, no group marker and
wordless close lines. The trade: info, debug
and interrupted all render the middle dot and are told
apart by colour.
Console output now wraps by default: long messages are
word-wrapped at cli::console_width() instead of running off
the right edge. logtree_theme(wrap = ) governs it –
TRUE follows the terminal (measured at render time, so a
mid-run resize is picked up), a number pins a width, FALSE
restores the old behaviour. Continuation lines indent to the message
column and carry the rails down, so a wrapped message still reads as one
node. An unbreakable token is split by display width, and a budget
narrower than the tree is deep degrades to no wrapping. It covers the
digest and run-summary lines too; file sinks are never wrapped.
with_logging(warnings = TRUE) routes R’s own
conditions into the tree: warning() becomes a
log_warn() leaf and message() a
log_info() leaf, at the depth where they happened.
warnings = "warning" routes only the one kind. Off by
default, deliberately: routing means muffling – a
routed condition no longer reaches warnings(), the caller’s
handlers or stderr. A routed warning also elevates its enclosing step,
so wrapping noisy third-party code will turn steps yellow. In global
mode the routing applies only while logtree steps are open.
The logger integration declares the version it
needs: Suggests: logger (>= 0.3.0).
logtree_logger() uses logger::appender_void,
which arrived in 0.3.0; guards previously checked only whether
logger was installed, so an older one failed with
'appender_void' is not an exported object in examples, the
vignette and tests instead of being skipped. Guards check the version
now, and logtree_logger() refuses an old
logger up front.
logtree_theme() swaps a preset only when one is
named. A call passing just overrides or
compact used to re-resolve the theme default
and silently reset everything to "unicode". Such a call now
merges onto the active theme, as documented; a bare
logtree_theme() is a no-op.
An unknown slot in a logtree_theme() override is now
an error naming the slot and listing the valid ones, instead of failing
inside modifyList() with
is.list(x) is not TRUE.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.