I have a rmarkdown setup to take input of csv data and saves results in xlsx and word file. I am rendering the rmd file within trycatch to save the warnings created within in a log file. But looks like warning messages are not generated only. I also have added this line to make sure i have a warning message : warning("This is a test warning.")
The code i am using is:
log.path <- paste0(path, "/", "logfile.txt") # Update this to your desired log file path
print(paste("Log file path:", log.path))
# Check if the directory exists, create it if it doesn't
log_dir <- dirname(log.path)
if (!dir.exists(log_dir)) {
dir.create(log_dir, recursive = TRUE)
print(paste("Created directory:", log_dir))
}
# Set the warning option to capture warnings
options(warn = 1) # Set to 1 to turn warnings into messages
# Use tryCatch to handle both warnings and errors
tryCatch(
{
# Render the R Markdown file
rmarkdown::render(
"Data_cleaning.rmd",
params = params_list,
output_file = paste0(GOST_ID, "_Data_cleaning_summary_", Survey_name, ".docx")
)
# Log a message indicating successful rendering
cat("Data cleaning summary rendered successfully.\n", file = log.path, append = TRUE)
},
error = function(err.msg) {
# Add error message to the error log file
write(toString(err.msg), log.path, append=TRUE)
# err.msg <- cond$message # Capture the error message
# cat(paste("Error:", err.msg, "\n"), file = log.path, append = TRUE)
},
warning = function(warningcondition){
# Add warning message to the log file
write(toString(warningcondition), log.path, append=TRUE)
}
)
# Capture warnings separately
options(warn = 1) # Ensure warnings are treated as messages
withCallingHandlers(
{
# Render the R Markdown file again to capture warnings
rmarkdown::render(
"Data_cleaning.rmd",
params = params_list,
output_file = paste0(GOST_ID, "_Data_cleaning_summary_", Survey_name, ".docx")
)
},
warning = function(cond) {
# Capture the warning message
warning.msg <- cond$message
cat(paste("Warning:", warning.msg, "\n"), file = log.path, append = TRUE)
invokeRestart("muffleWarning") # Prevent the warning from being printed to the console
}
)
# Reset warning option to default after tryCatch
options(warn = 0)
Is there any better way to write warnings and errors to an external file while running rmarkdown
I tried many ways to write the warnings to a file. but the messages are not generating when i am rendering rmarkdown. Is there any thing i am missing in this approach?
I have a rmarkdown setup to take input of csv data and saves results in xlsx and word file. I am rendering the rmd file within trycatch to save the warnings created within in a log file. But looks like warning messages are not generated only. I also have added this line to make sure i have a warning message : warning("This is a test warning.")
The code i am using is:
log.path <- paste0(path, "/", "logfile.txt") # Update this to your desired log file path
print(paste("Log file path:", log.path))
# Check if the directory exists, create it if it doesn't
log_dir <- dirname(log.path)
if (!dir.exists(log_dir)) {
dir.create(log_dir, recursive = TRUE)
print(paste("Created directory:", log_dir))
}
# Set the warning option to capture warnings
options(warn = 1) # Set to 1 to turn warnings into messages
# Use tryCatch to handle both warnings and errors
tryCatch(
{
# Render the R Markdown file
rmarkdown::render(
"Data_cleaning.rmd",
params = params_list,
output_file = paste0(GOST_ID, "_Data_cleaning_summary_", Survey_name, ".docx")
)
# Log a message indicating successful rendering
cat("Data cleaning summary rendered successfully.\n", file = log.path, append = TRUE)
},
error = function(err.msg) {
# Add error message to the error log file
write(toString(err.msg), log.path, append=TRUE)
# err.msg <- cond$message # Capture the error message
# cat(paste("Error:", err.msg, "\n"), file = log.path, append = TRUE)
},
warning = function(warningcondition){
# Add warning message to the log file
write(toString(warningcondition), log.path, append=TRUE)
}
)
# Capture warnings separately
options(warn = 1) # Ensure warnings are treated as messages
withCallingHandlers(
{
# Render the R Markdown file again to capture warnings
rmarkdown::render(
"Data_cleaning.rmd",
params = params_list,
output_file = paste0(GOST_ID, "_Data_cleaning_summary_", Survey_name, ".docx")
)
},
warning = function(cond) {
# Capture the warning message
warning.msg <- cond$message
cat(paste("Warning:", warning.msg, "\n"), file = log.path, append = TRUE)
invokeRestart("muffleWarning") # Prevent the warning from being printed to the console
}
)
# Reset warning option to default after tryCatch
options(warn = 0)
Is there any better way to write warnings and errors to an external file while running rmarkdown
I tried many ways to write the warnings to a file. but the messages are not generating when i am rendering rmarkdown. Is there any thing i am missing in this approach?
Share Improve this question asked Mar 18 at 6:35 Sandhya GhildiyalSandhya Ghildiyal 3332 silver badges13 bronze badges 1 |1 Answer
Reset to default 2 +25Here is an approach using knitr output hooks as @Tim G suggests in conjunction with the {logger} package.
For each message class (i.e., message, warnings, or errors) we can:
- get a copy of the corresponding old knitr hook so that we might call it in our new hook
- make a log file in which to place any corresponding class messages
- set the new knitr hook to log any class message to the file and then call the old hook
Note, to set the global knitr chunk option error = TRUE
to continue knitting on error.
---
title: "Untitled"
output: html_document
date: "2025-03-26"
---
```{r setup, include=FALSE}
# set global chunk options
## echo = TRUE to show code in output
## error = TRUE to continue on errors
knitr::opts_chunk$set(echo = TRUE, error = TRUE)
library(logger)
local({
# messages
message_hook_old <- knitr::knit_hooks$get("message")
message_out <- "message.txt"
log_appender(appender_file(message_out), "message")
knitr::knit_hooks$set(message = function(x, options) {
log_info(x, namespace = "message")
message_hook_old(x, options)
})
# warnings
warning_hook_old <- knitr::knit_hooks$get("warning")
warning_out <- "warning.txt"
log_appender(appender_file(warning_out), "warning")
knitr::knit_hooks$set(warning = function(x, options) {
log_warn(x, namespace = "warning")
warning_hook_old(x, options)
})
# errors
error_hook_old <- knitr::knit_hooks$get("error")
error_out <- "error.txt"
log_appender(appender_file(error_out), "error")
knitr::knit_hooks$set(error = function(x, options) {
log_error(x, namespace = "error")
error_hook_old(x, options)
})
})
```
```{r}
message("This is a message.")
```
```{r}
warning("This is a warning.")
```
```{r}
stop("This is an error.")
```
Results
HTML
message.txt
INFO [2025-03-26 15:55:17] ## This is a message.
warning.txt
WARN [2025-03-26 15:55:17] ## Warning: This is a warning.
error.txt
ERROR [2025-03-26 15:55:17] ## Error: This is an error.
.rmd
you can place a hookset that cats warnings / errorsknitr::knit_hooks$set( warning = function(x)...cat(x, file = "logfile.txt")
or maybe use R's classicsink
:sink("out_logfile.txt", append = TRUE, type = "output")
andsink("out_logfile.txt", append = TRUE, type = "warning")
...tryCatch( { rmarkdown::render( error = \(e) cat(paste("ERROR:", e$message, "\n"))
same for warnings and close your sinkssink()
sink()
. Did something similar before, maybe it helps. – Tim G Commented Mar 24 at 17:08