Log to database

Viewed 41

Trying to redirect message, warning, and error to a database, I came up with a kind of decorator function:

with_db_log <- function(expr, con=NULL) {
    stopifnot(!is.null(con))
    do_log <- function(lvl, cnd) {
        if(inherits(con, "try-error")) return()
        dat <- data.frame(
            ts=strftime(Sys.time(), "%Y-%m-%d %H:%M:%S"),
            lvl=lvl,
            msg=trimws(conditionMessage(cnd)),
            stringsAsFactors=FALSE
        )
        DBI::dbWriteTable(con, name="log", value=dat, append=TRUE) 
    }
    
    tryCatch(
        error = function(cnd) {
            do_log(lvl="error", cnd=cnd)
            invisible(structure(conditionMessage(cnd), class = "try-error", condition = cnd))
        },
        withCallingHandlers(
            message = function(cnd) {do_log(lvl="message", cnd=cnd)},
            warning = function(cnd) {do_log(lvl="warning", cnd=cnd)},
            expr
        )
    )
}
    

where con is a living database connection. Now to redirect errors, warnings and diagnostic messages, I can do

with_db_log(con=my_db_connection, 
    my_function(my_param)
)

and the database table log with columns ts, lvl and msg gets updated.

(I used stackoverflow to write the code, but can not find the link anymore.)

However, it seems not to work in all cases: sometimes the msg field remains empty. It is not so easy for me to find out what cases these are. I suspect that there is a problem with the code above:

msg=trimws(conditionMessage(cnd))

but I can not find what the problem is.

Is there a better way to extract a log message from a condition? Any hints appreciated.

0 Answers
Related