1

I am developing a master function to call other scripts/functions in R and would like to capture all outputs (i.e. print, cat, message, stop) into a web API (e.g. RESTAPI with POST method). Some dummy codes to demonstrate my ideas

url <- "https://example.com/api/log"
capture.output({
   print("print")
   cat("cat")
   message("message")
   stop("stop")
}, file=url)

I am not sure how to use an URL in the connection. It will be wonderful if I can capture the output types (i.e. print, message and stop) and in real time (i.e. redirect output just after generating).

The web api will store three piece of information * timestamp: can be handled by webapi * type: (print, message or stop) * log: the actual message

Thanks for any suggestions.

Bangyou
  • 9,462
  • 16
  • 62
  • 94

1 Answers1

0

Following the suggestion for this question: How do I save warnings and errors as output from a function?.

Now I can capture the message, warning, error using tryCatch and store the log type and time in a list.

factory <- function(fun) {
    function(...) {
        warn <- err <- msg <- NULL
        res <- withCallingHandlers(
            tryCatch(fun(...), error=function(e) {
                new_e <- err
                new_e[[length(new_e) + 1]]  <- list(time = Sys.time(),
                                                    type = "error",
                                                    log =  conditionMessage(e))
                err <<- new_e
                NULL
            }), warning=function(w) {
                new_w <- warn
                new_w[[length(new_w) + 1]]  <- list(time = Sys.time(),
                               type = "warning",
                               log =  conditionMessage(w))

                warn <<- new_w
                invokeRestart("muffleWarning")
            }, message = function(m) {
                new_w <- msg
                new_w[[length(new_w) + 1]]  <- list(time = Sys.time(),
                                                    type = "message",
                                                    log =  conditionMessage(m))
                msg <<- new_w

                invokeRestart("muffleMessage")
            })
        list(res, warn=warn, err=err, msg=msg)
    }

}
test <- function(){
    print("AAAAAAA")
    message("BBBBBB")
    print("CCCC")
    warning("DDDDDDDDDDD")
    Sys.sleep(1)
    warning("EEEEEEEEEEEEEEE")
    #stop("FFFFFFFFFFFFF")
    warning("GGGGGGGGGGGGGG")
    return(NULL)

}

a <- factory(test)()


The results are shown below

> a
[[1]]
NULL

$warn
$warn[[1]]
$warn[[1]]$`time`
[1] "2019-10-21 22:02:39 AEST"

$warn[[1]]$type
[1] "warning"

$warn[[1]]$log
[1] "DDDDDDDDDDD"


$warn[[2]]
$warn[[2]]$`time`
[1] "2019-10-21 22:02:40 AEST"

$warn[[2]]$type
[1] "warning"

$warn[[2]]$log
[1] "EEEEEEEEEEEEEEE"


$warn[[3]]
$warn[[3]]$`time`
[1] "2019-10-21 22:02:40 AEST"

$warn[[3]]$type
[1] "warning"

$warn[[3]]$log
[1] "GGGGGGGGGGGGGG"



$err
NULL

$msg
$msg[[1]]
$msg[[1]]$`time`
[1] "2019-10-21 22:02:39 AEST"

$msg[[1]]$type
[1] "message"

$msg[[1]]$log
[1] "BBBBBB\n"

In the next step, I can use httr function to call RESTAPI to store the logs in the database. Alternatively, the message can be directly stored into database when the messages are generated through updating the factory function.

The only problem is the function cannot capture print and cat. However, this question Why is message() a better choice than print() in R for writing a package? suggestion message function is better than print and cat functions. It might be not a big issue for current stage.

Bangyou
  • 9,462
  • 16
  • 62
  • 94