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):
## Mon Feb 26 20:29:31 2024  Opening test.log  
## Mon Feb 26 20:29:31 2024  message  
## Mon Feb 26 20:29:31 2024  Closing test.log flags = 0  
## ------- 
## R version 4.3.2 (2023-10-31) 
## Platform: aarch64-apple-darwin20 (64-bit) 
## Running under: macOS Sonoma 14.3.1 
##  
## Matrix products: default 
## BLAS:   /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib  
## LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.11.0 
##  
## locale: 
## [1] C/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8 
##  
## time zone: America/New_York 
## tzcode source: internal 
##  
## attached base packages: 
## [1] stats     graphics  grDevices utils     datasets  methods   base      
##  
## other attached packages: 
## [1] luzlogr_0.2.1 
##  
## loaded via a namespace (and not attached): 
##  [1] assertthat_0.2.1  digest_0.6.34     R6_2.5.1          fastmap_1.1.1     
##  [5] xfun_0.40         cachem_1.0.8      knitr_1.45        htmltools_0.5.6   
##  [9] rmarkdown_2.25    cli_3.6.1         sass_0.4.8        jquerylib_0.1.4   
## [13] compiler_4.3.2    rstudioapi_0.15.0 tools_4.3.2       evaluate_0.21     
## [17] bslib_0.5.1       yaml_2.3.7        rlang_1.1.1       jsonlite_1.8.7By 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.)
## Mon Feb 26 20:29:31 2024  Opening test.log  
## Mon Feb 26 20:29:31 2024  message 1 2  
## Mon Feb 26 20:29:31 2024   
##   speed dist 
## 1     4    2 
## 2     4   10 
## 3     7    4 
## 4     7   22 
## 5     8   16 
## 6     9   10 
##  
## Mon Feb 26 20:29:31 2024  Closing test.log flags = 0By 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
## Mon Feb 26 20:29:31 2024  Opening test.log  
## Mon Feb 26 20:29:31 2024  This message will appear  
## Mon Feb 26 20:29:31 2024  So will this (level 0 by default)  
## Mon Feb 26 20:29:31 2024  Closing test.log flags = 0Notice 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)## Mon Feb 26 20:29:31 2024  Opening test.log  
## Mon Feb 26 20:29:31 2024  A normal message  
## ** Flagged message: ** 
## Mon Feb 26 20:29:31 2024  A flagged message!  
## ** Flagged message: ** 
## Mon Feb 26 20:29:31 2024  Another  
## Mon Feb 26 20:29:31 2024  Closing test.log flags = 2So 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.↩︎