Wrap fn, so it will save arguments on failure.
DebugFnW(saveDest, fn)
where to write captured state (determined by type): NULL random temp file, character temp file, name globalenv() variable, and function triggers callback.
function to call
wrapped function that saves state on error.
dump.frames
, DebugFn
, DebugFnW
, DebugFnWE
, DebugPrintFn
, DebugFnE
, DebugPrintFnE
Operator idea from: https://gist.github.com/nassimhaddad/c9c327d10a91dcf9a3370d30dff8ac3d .
Please see: vignette("DebugFnW", package="wrapr")
.
saveDest <- paste0(tempfile('debug'),'.RDS')
f <- function(i) { (1:10)[[i]] }
df <- DebugFnW(saveDest,f)
# correct run
df(5)
#> [1] 5
# now re-run
# capture error on incorrect run
tryCatch(
df(12),
error = function(e) { print(e) })
#> <simpleError in value[[3L]](cond): wrapr::DebugFnW: wrote '/var/folders/7f/sdjycp_d08n8wwytsbgwqgsw0000gn/T//RtmpZ4IuL6/debug11ef47be7a65f.RDS' on catching 'Error in (1:10)[[i]]: subscript out of bounds'
#> You can reproduce the error with:
#> 'p <- readRDS('/var/folders/7f/sdjycp_d08n8wwytsbgwqgsw0000gn/T//RtmpZ4IuL6/debug11ef47be7a65f.RDS'); do.call(p$fn, p$args)'>
# examine details
situation <- readRDS(saveDest)
str(situation)
#> List of 4
#> $ fn :function (i)
#> ..- attr(*, "srcref")= 'srcref' int [1:8] 3 6 3 32 6 32 3 3
#> .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x7fba0bbe8470>
#> $ args :List of 1
#> ..$ : num 12
#> $ namedargs: language df(12)
#> $ fn_name : chr "f"
# fix and re-run
situation$args[[1]] <- 6
do.call(situation$fn,situation$args)
#> [1] 6
# clean up
file.remove(saveDest)
#> [1] TRUE
f <- function(i) { (1:10)[[i]] }
curEnv <- environment()
writeBack <- function(sit) {
assign('lastError', sit, envir=curEnv)
}
attr(writeBack,'name') <- 'writeBack'
df <- DebugFnW(writeBack,f)
tryCatch(
df(12),
error = function(e) { print(e) })
#> <simpleError in value[[3L]](cond): wrapr::DebugFnW: wrote error to user function: 'writeBack' on catching 'Error in (1:10)[[i]]: subscript out of bounds'
#> You can reproduce the error with:
#> 'do.call(p$fn, p$args)' (replace 'p' with actual variable name)>
str(lastError)
#> List of 4
#> $ fn :function (i)
#> ..- attr(*, "srcref")= 'srcref' int [1:8] 22 6 22 32 6 32 22 22
#> .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x7fba0a5f7bd8>
#> $ args :List of 1
#> ..$ : num 12
#> $ namedargs: language df(12)
#> $ fn_name : chr "f"