在 R 或 Rstudio 中记录带有错误的控制台历史记录

Logging console history with errors in R or Rstudio

出于教育目的,我们记录了学生在实验期间在 rstudio 控制台中键入的所有命令。此外,如果调用成功或引发错误,我们想存储,以识别那些努力获得正确语法的学生。

我能想到的最好的是这样的:

options(error = function(){
  timestamp("USER ERROR", quiet = TRUE)
})

这会在发生异常时在历史日志中添加 ## ERROR 注释。因此我们可以分析历史文件以查看哪些命令后跟 ## ERROR 注释。

但是 R 的内部历史系统不太适合日志记录,因为它在内存中,大小有限并且需要使用 savehistory() 手动存储。此外,我更愿意将日志存储为每次调用一行,即转义多行命令的换行符。

在 R 或 RStudio 控制台中是否可能有一个钩子用于记录实际执行的命令?这将允许我在数据库中插入每个评估的表达式(和错误)以及用户名和时间戳。

一个可能的解决方案是使用 addTaskCallbacktaskCallbackManager 以及将每个顶级命令写入数据库的函数。回调只会在命令成功完成时触发,因此您仍然需要在出错时调用日志记录函数。

# error handler
logErr <- function() {
  # turn logging callback off while we process errors separately
  tcbm$suspend(TRUE)
  # turn them back on when we're done
  on.exit(tcbm$suspend(FALSE))
  sc <- sys.calls()
  sclen <- length(sc)  # last call is this function call
  if(sclen > 1L) {
    cat("myError:\n", do.call(paste, c(lapply(sc[-sclen], deparse), sep="\n")), "\n")
  } else {
    # syntax error, so no call stack
    # show the last line entered
    # (this won't be helpful if it's a parse error in a function)
    file1 <- tempfile("Rrawhist")
    savehistory(file1)
    rawhist <- readLines(file1)
    unlink(file1)
    cat("myError:\n", rawhist[length(rawhist)], "\n")
  }
}
options(error=logErr)
# top-level callback handler
log <- function(expr, value, ok, visible) {
  cat(deparse(expr), "\n")
  TRUE
}
tcbm <- taskCallbackManager()
tcbm$add(log, name = "log")

这不是一个完整的解决方案,但我希望它足以让您入门。这是输出的示例。

> f <- function() stop("error")
f <- function() stop("error") 
> hi
Error: object 'hi' not found
myError:
 hi 
> f()
Error in f() : error
myError:
 f()
stop("error")