1

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?

1
  • inside your .rmd you can place a hookset that cats warnings / errors knitr::knit_hooks$set( warning = function(x)...cat(x, file = "logfile.txt") or maybe use R's classic sink: sink("out_logfile.txt", append = TRUE, type = "output") and sink("out_logfile.txt", append = TRUE, type = "warning") ... tryCatch( { rmarkdown::render( error = \(e) cat(paste("ERROR:", e$message, "\n")) same for warnings and close your sinks sink() sink(). Did something similar before, maybe it helps. Commented Mar 24 at 17:08

1 Answer 1

2
+25

Here 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:

  1. get a copy of the corresponding old knitr hook so that we might call it in our new hook
  2. make a log file in which to place any corresponding class messages
  3. 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

enter image description here

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.

Reprex files hosted with on GitHub

Sign up to request clarification or add additional context in comments.

1 Comment

I tried both ways. The log file created only printing the console: the warning message will print in output word if i set in the particular chunk warning True But we want warnings produced i all chunks to be written in a log file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.