This vignette describes how to use the luzlogr package, which provides flexible but lightweight logging facilities for R scripts.
To install this package, use R’s install.packages()
function or the “Packages” pane in RStudio. To install the latest,
developmental version of this package from GitHub:
devtools
package installed from
CRAN and loaded.install_github("bpbond/luzlogr")
Three functions - openlog()
, printlog()
,
closelog()
- provide logging of script output. They’re
simple to use:
The resulting log file test.log
looks like this (not
including the initial ##
characters):
## Thu Oct 24 02:42:22 2024 Opening test.log
## Thu Oct 24 02:42:22 2024 message
## Thu Oct 24 02:42:22 2024 Closing test.log flags = 0
## -------
## R version 4.4.1 (2024-06-14)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.1 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so; LAPACK version 3.12.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=C
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## time zone: Etc/UTC
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] luzlogr_0.2.1 rmarkdown_2.28
##
## loaded via a namespace (and not attached):
## [1] assertthat_0.2.1 digest_0.6.37 R6_2.5.1 fastmap_1.2.0
## [5] xfun_0.48 maketools_1.3.1 cachem_1.1.0 knitr_1.48
## [9] htmltools_0.5.8.1 buildtools_1.0.0 lifecycle_1.0.4 cli_3.6.3
## [13] sass_0.4.9 jquerylib_0.1.4 compiler_4.4.1 sys_3.4.3
## [17] tools_4.4.1 evaluate_1.0.1 bslib_0.8.0 yaml_2.3.10
## [21] jsonlite_1.8.9 rlang_1.1.4
By default individual lines are prefixed with a timestamp, end with a carriage return, and the entire log starts with an open message and ends with a close one.
Any printable object can be written to a log. For example:
(Notice in this case we’ve told closelog()
not to append
sessionInfo()
output, as it does by default.)
## Thu Oct 24 02:42:22 2024 Opening test.log
## Thu Oct 24 02:42:22 2024 message 1 2
## Thu Oct 24 02:42:22 2024
## speed dist
## 1 4 2
## 2 4 10
## 3 7 4
## 4 7 22
## 5 8 16
## 6 9 10
##
## Thu Oct 24 02:42:22 2024 Closing test.log flags = 0
By design, luzlogr
is intended to be simple and easy to
use. Nonetheless, it does provide additional features, including:
In many circumstances, we want messages to have different priorities or levels associated with them. Each logfiles has a minimum priority level, set when it’s opened, making it easy to produce logs with varying levels of detail–for example, under development versus release conditions.
By default, luzlogr logs have a minimum levels of
-Inf
: in other words, they’ll accept every single message
sent to them via printlog()
, which produces messages with a
default level of zero. We can change the log’s level, however, and this
will then affect which messages appear in the log.
openlog("test.log", loglevel = 0)
printlog("This message will appear", level = 0)
printlog("So will this (level 0 by default)")
printlog("This will not", level = -1)
closelog(sessionInfo = FALSE)
produces
## Thu Oct 24 02:42:22 2024 Opening test.log
## Thu Oct 24 02:42:22 2024 This message will appear
## Thu Oct 24 02:42:22 2024 So will this (level 0 by default)
## Thu Oct 24 02:42:22 2024 Closing test.log flags = 0
Notice that the third message didn’t get logged. If we change the
loglevel
parameter in openlog()
to -1 or
lower, however, all these messages will appear.
Another way to differentiate messages is by flagging them.
Note that in all the above examples, when the log is closed, a
flags = 0
message is printed. But we can change that:
openlog("test.log")
printlog("A normal message")
printlog("A flagged message!", flag = TRUE)
flaglog("Another")
closelog(sessionInfo = FALSE)
## Thu Oct 24 02:42:22 2024 Opening test.log
## Thu Oct 24 02:42:22 2024 A normal message
## ** Flagged message: **
## Thu Oct 24 02:42:22 2024 A flagged message!
## ** Flagged message: **
## Thu Oct 24 02:42:22 2024 Another
## Thu Oct 24 02:42:22 2024 Closing test.log flags = 2
So far, only messages sent via printlog()
appear in the
log. We might, however, want to capture everything1 produced
by a script. To do this, use the sink = TRUE
option of
openlog()
.
If an error occurs in your script, any log files will by default
remain open. If using a single log file, it’s easy to put a statement
such as suppressWarnings(closelog())
at the start of your
script. Alternatively, you can tell luzlogr to close
all open logs if an error occurs:
Logs can also be sent to any R connection: a pipe, compressed file, URL, etc.
con <- gzfile("test.log.gz")
openlog(con)
printlog("Sending to a compressed logfile")
closelog(sessionInfo = FALSE)
Note that luzlogr won’t close a connection that was
already open at the time of the openlog()
call.
If you’re logging to log A and open log B (without closing A),
subsequent printlog()
messages will go to B. When you close
B, logging switches back to A (i.e., there’s a stack of logs that gets
pushed/popped when necessary).
If you need to append to an existing log, use
append = TRUE
when calling openlog()
. By
default, existing logfiles are erased upon opening.
This concludes the Introduction to luzlogr vignette.
Almost. Messages, warnings, and errors will not appear;
but see ?sink
and its type = "message"
parameter.↩︎