Using tryCatchLog with futile.logger: write to file instead of console - r

I am using tryCatchLog and want to send all warnings and error messages to a log file. I do not want any output to the console.
In the documentation for tryCatchLog I came across this code snippet:
library(futile.logger)
# log to a file (not the console which is the default target of futile.logger).
# You could also redirect console output into a file if start your R > script with a shell script using Rscript!
flog.appender(appender.file("my_app.log"))
The vignette for tryCatchLog includes the following code snippet to change the logging behavior and send errors to a file instead of the console:
library(futile.logger)
flog.appender(appender.file("app.log"))
flog.threshold(ERROR) # TRACE, DEBUG, INFO, WARN, ERROR, FATAL
try(log(-1)) # the warning will not be logged!
This suggests to me that I can simply re-direct the messages to a log file using flog.apppender(appender.file()). However, instead of writing to a file I get the following output on the console:
NULL
NULL
Warning in log(-1) : NaNs produced
[1] NaN
The vignette for tryCatchLog provides this code example in the Best Practice section:
library(futile.logger)
library(tryCatchLog)
options(keep.source = TRUE) # source code file name and line number tracking
options("tryCatchLog.write.error.dump.file" = TRUE) # dump for post-mortem analysis
flog.appender(appender.file("my_app.log")) # to log into a file instead of console
flog.threshold(INFO) # TRACE, DEBUG, INFO, WARN, ERROR, FATAL
tryCatchLog(source("your_main_script.R"))
Adapting the last line of code to tryCatchLog(log("this will produce an error")) to make the example easier, I am still not writing to a log file but to the console:
NULL
NULL
Error in log("this will produce an error") : non-numeric argument to mathematical function
Looking at the documentation of futile.logger and examples on stackoverflow also did not help me. Based on them, I thought the following should write the error message to a file. I am using try() as a stand-in for more involved versions of tryCatchLog() to make sure that it is not an issue with tryCatchLog.
library(futile.logger)
flog.appender(appender.file(file.path(getwd(),'logs.txt')))
flog.threshold(WARN) # TRACE, DEBUG, INFO, WARN, ERROR, FATAL
try(log(-1)) # this will create a warning
try(log("this will create an error")) # this will create an error
The command neither creates a log file nor appends an existing one.
Instead, flog.appender() and flog.threshold() return NULL (to the console). And the warning and error message are also printed to the console. Presumably, I am missing something when linking the logger to the file (hence the NULL return value?).
How can I redirect all warnings and errors caught by tryCatchLog to a file (with futile.logger) without ANY output to the console?

The output of try() has nothing to do with futile.logger().
If you configure a file appender in futile.logger you still have to write your log output using the flog.* functions (that's how logging works):
library(futile.logger)
flog.info("this is an info log output")
# INFO [2021-12-08 19:51:13] this is an info log output
flog.warn("this is an warning log output")
# WARN [2021-12-08 19:51:14] this is an warning log output
flog.error("this is an error log output")
# ERROR [2021-12-08 19:51:14] this is an error log output
I guess what you want is kinda output redirection of the standard or error output (eg. via capture.output) but this function does not add logging information like a timestamp and does not support severity level management ("info", "warn", "error"...).
If you want to use try*() in combination with logging you can use the CRAN package tryCatchLog which does exactly what you want (and supports futile.logger too):
library(tryCatchLog)
tryLog(log(-1)) # this will create a warning
tryLog(log("this will create an error")) # this will create an error

Related

R sink(): Error, cannot split the message connection

I am trying to log the errors and warnings of an R script into an external file. At the same time I want to be able to see the errors and warnings in the console in RStudio (useful to develop and debug). I am trying to use the following code:
logfile <- file("my_file_path", open="wt")
sink(logfile, type="message", split = TRUE)
But when I try to split the message connection using the funciton sink() I get the following error:
Error in sink(logfile, type = "message", split = TRUE) :
cannot split the message connection
Is there any workaround or alternative solution?
Thanks
So, I tried using split = T in sink.
But, it's not doing what we want it to do. It's either redirecting output to log file or throwing an error which you pointed and is not printing errors or warning messages to RStudio console.
There's a work around to your problem which might solve your problem.
I tried using this:-
# path to your log file
file_path <- "path/documents/log/log.txt"
# open a connection to your log file
file_con <- file(file_path, open = "a")
## capture warning messages and errors to log file
sink(file_con, type = "message")
## to get error and warning message
sum(a)
warning("this is a warning message. please ignore")
## revert output back to the console and close the file connection
sink(type = "message")
close(file_con)
# get all the errors and warnings from log file
readLines(file_path)
It gave an output to console:-
[1] "Error: object 'a' not found"
[2] "Warning message:"
[3] "this is a warning message. please ignore "
So, the above piece of code diverted the error and warning message to log file and printed it in console too.
You can use sink normally and then use readLines to print your error and warning messages to console.

R starts up with error message

I am asking this question out of curiosity. I have noticed that whenever I boot R, the instance starts up with this error message
As you can see, R boots with the error message "object 'a' not found" Is there any reason for this?
R reads and executes several files at startup, most prominently the ~/.Rprofile file (That is, the file .Rprofile in your home directory). Check these files to see if they contain anything weird.
You can quickly check whether .Rprofile is the culprit by running R with the --vanilla command line argument: this argument prevents the user profile to be read, thus the error should vanish.

Error handling in R in RStudio -- don't invoke debugger?

I'm trying to create error messages similar to those you can find in R package dplyr that don't invoke RStudio's debugger and simply stop and print an informative message.
So for example in RStudio if you use:
library(dplyr)
group_by(blah)
You get an informative error but the debugger is not invoked so the "interruption" to the user is minimal, they realize the issue and fix the code. But when I use
myfunc<-function(val){
if(val>3) stop("This is error", call.=FALSE)
}
myfunc(4)
The debugger is triggered and it's more unpleasant. How do I simply give a nice error message with out starting the debugger? What is the difference in how dplyr is creating error messages and mine? I did look at the GitHub repo but wasn't sure.

New error when knitting get_engine(options$engine)

I have an .Rmd file that previously had knitted without any problems. Now I am getting the following error when executing this instruction
confusionMatrix(prediction1, ssTesting$classe)
The error is
Error in get_engine(options$engine) : Unknown language engine 'test' (must be registered via knit_engines$set())
If I execute each chunk independently the error does not occur.
It only happens if I knit.
The error is independent of using version R-3.1.2 or R-3.2.1. I also set all the cache options to FALSE and made sure that all the libraries were correct but the error keeps appearing.
A simple typo in the beginning of the chunk ... ```{rtest.mod1} instead of ```{r test.mod1}
Hard to see but simple to fix.

Can you make R print more detailed error messages?

I've often been frustrated by R's cryptic error messages. I'm not talking about during an interactive session, I mean when you're running a script. Error messages don't print out line numbers, and it's often hard to trace the offending line, and the reason for the error (even if you can find the location).
Most recently my R script failed with the the incredibly insightful message: "Execution halted." The way I usually trace such errors is by putting a lot of print statements throughout the script -- but this is a pain. I sometimes have to go through the script line by line in an interactive session to find the error.
Does anyone have a better solution for how to make R error output more informative?
EDIT: Many R-debugging things work for interactive sessions. I'm looking for help on command-line scripts run through Rscript. I'm not in the middle of an R session when the error happens, I'm at the bash shell. I can't run "traceback()"
Try some of the suggestions in this post:
General suggestions for debugging in R
Specifically, findLineNum() and traceback()/setBreakpoint().
#Nathan Well add this line sink(stdout(), type="message") at the beginning of the script and you should get in console message both script content and output along with error message so you can see it as in interactive mode in the console. (you can then also redirect to a log file if you prefer keeping the console "clean")
Have a look at my package tryCatchLog (https://github.com/aryoda/tryCatchLog).
While it is impossible to improve the R error messages directly you can save a lot of time by identifying the exact code line of the error and have actual variables at the moment of the error stored in a dump for "post mortem" analysis!
The main advantages of the tryCatchLog function over tryCatch are
easy logging of errors, warnings and messages into a file or console
warnings do not stop the program execution (tryCatch stops the execution if you pass a warning handler function)
identifies the source of errors and warnings by logging a stack trace with a reference to the source file name and line number (since traceback does not contain the full stack trace)
allows post-mortem analysis after errors by creating a dump file with all variables of the global environment (workspace) and each function called (via dump.frames) - very helpful for batch jobs that you cannot debug on the server directly to reproduce the error!
This will show a more detailed traceback, but not the line number:
options(error = function() {traceback(2, max.lines=100); if(!interactive()) quit(save="no", status=1, runLast=T)})
One way inside a script to get more info on where the error occurred is to redirect R message to the same stream as errors :
sink(stdout(), type="message")
This way you get both messages and errors in the same output so you see which line raised the error...

Resources