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.

Introduction to luzlogr

Ben Bond-Lamberty

2024-02-26

This vignette describes how to use the luzlogr package, which provides flexible but lightweight logging facilities for R scripts.

Installing

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:

  1. Make sure you have the devtools package installed from CRAN and loaded.
  2. install_github("bpbond/luzlogr")

Basics

Three functions - openlog(), printlog(), closelog() - provide logging of script output. They’re simple to use:

library(luzlogr)
openlog("test.log")
printlog("message")
closelog()

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.7

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:

openlog("test.log")
printlog("message", 1, 2)
printlog(head(cars))
closelog(sessionInfo = FALSE)

(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 = 0

More involved examples

By design, luzlogr is intended to be simple and easy to use. Nonetheless, it does provide additional features, including:

Priority levels

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 = 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.

Flagging messages

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 = 2

Capturing all output

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().

Errors and logs

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:

options(luzlogr.close_on_error = TRUE)

Logging to a connection

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.

Switching logs

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.


  1. Almost. Messages, warnings, and errors will not appear; but see ?sink and its type = "message" parameter.↩︎

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.