rloggingnamespaces

Logging to file fails in R package logger if called from inside of a function


I am new to the R package logger. However, it looks very useful and the code that I have to maintain uses it. The following code prepares logging to the console and logging to a file.

.start_logger = function(){
     unloadNamespace('logger')
     library('logger')
     my_logfile <- tempfile()
     ### file
     logger::log_threshold('DEBUG', index = 1)
     logger::log_appender(appender_file(my_logfile), index = 1)
     
     ### console ----
     log_threshold('INFO', index = 2)
     logger::log_appender(appender_console, index = 2)
     
     logger::log_with_separator("start calculation")
     logger::log_tictoc('main', namespace = 'main')
     log_separator()
 return(my_logfile)
 }

I want to call that function with

my_logfile = .start_logger()

I face 2 interesting issues:

  1. If I run the code in a fresh session outside of a function, then the file where I want to log to can not be found. If I run the code inside of a function, I get the following error from the call of logger::log_with_separator("start calculation")

Error in force(file) : object 'my_logfile' not found

If I run the code without the function, then the logging works:

unloadNamespace('logger')
library('logger')
my_logfile <- tempfile()

logger::log_threshold('DEBUG', index = 1)
logger::log_appender(appender_file(my_logfile), index = 1)

### console ----
log_threshold('INFO', index = 2)
logger::log_appender(appender_console, index = 2)

logger::log_with_separator("start calculation")
logger::log_tictoc('main', namespace = 'main')
log_separator()
  1. If I have run the code outside of a function successfully once, then also the version with starting the logger inside of a function works.

I guess it has something to do with namespaces or such, concerning the tempfile that I use for logging. Could you please give me any hints on how to make the version with the function call work?

EDIT: Further research showed me that assinging the variable my_logfile to the global environment solves the issue. But how is this done more elegantly/correctly? So replace

my_logfile <- tempfile()

with

my_logfile <<- tempfile()

.

EDIT: This turned out to be a bug. If you encounter this error, you can either use the solutions offered here or hope that the bug has been fixed in a newer version of the package (https://github.com/daroczig/logger/issues/157).

sessionInfo() R version 4.1.2 (2021-11-01) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows Server x64 (build 14393)

Matrix products: default

locale: [1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252 LC_MONETARY=English_United States.1252 [4] LC_NUMERIC=C
LC_TIME=English_United States.1252

attached base packages: [1] stats graphics grDevices utils
datasets methods base

other attached packages: [1] logger_0.3.0

loaded via a namespace (and not attached): [1] compiler_4.1.2 tools_4.1.2 glue_1.7.0


Solution

  • The appender_file(my_logfile) call uses a bit of non-standard evaluation to lazily evaulate variables names. You can bypass that by using do.call for force evaluation of that temp variable. This seems to work

    .start_logger = function(){
      unloadNamespace('logger')
      library('logger')
      my_logfile <- tempfile()
      ### file
      logger::log_threshold('DEBUG', index = 1)
      logger::log_appender(do.call("appender_file", list(my_logfile)), index = 1)
      
      ### console ----
      log_threshold('INFO', index = 2)
      logger::log_appender(appender_console, index = 2)
      
      logger::log_with_separator("start calculation")
      logger::log_tictoc('main', namespace = 'main')
      log_separator()
      return(my_logfile)
    }