简体   繁体   English

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

[英]Logging console history with errors in R or Rstudio

For educational purposes we are logging all commands that students type in the rstudio console during labs.出于教育目的,我们记录了学生在实验期间在 rstudio 控制台中键入的所有命令。 In addition we would like to store if call was successful or raised an error, to identify students which struggling to get the syntax right.此外,我们希望存储调用是否成功或引发错误,以识别那些努力使语法正确的学生。

The best I can come up with is something like this:我能想到的最好的东西是这样的:

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

This adds an ## ERROR comment on the history log when an exception occurs.这会在发生异常时在历史日志中添加## ERROR注释。 Thereby we could analyze history files to see which commands were followed by an ## ERROR comment.因此,我们可以分析历史文件以查看哪些命令后跟## ERROR注释。

However R's internal history system is not well suited for logging because it is in-memory, limited size and needs to be stored manually with savehistory() .然而,R 的内部历史系统不太适合记录日志,因为它在内存中,大小有限并且需要使用savehistory()手动存储。 Also I would prefer to store log one-line-per-call, ie escape linebreaks for multi-line commands.此外,我更愿意存储每次调用一行的日志,即为多行命令转义换行符。

Is there perhaps a hook or in the R or RStudio console for logging actual executed commands?是否有钩子或在 R 或 RStudio 控制台中用于记录实际执行的命令? That would allow me to insert each evaluated expression (and error) in a database along with a username and timestamp.这将允许我在数据库中插入每个评估的表达式(和错误)以及用户名和时间戳。

A possible solution would be to use addTaskCallback or the taskCallbackManager with a function that writes each top-level command to your database.一个可能的解决方案是将addTaskCallbacktaskCallbackManager与一个将每个顶级命令写入数据库的函数一起使用。 The callback will only fire on the successful completion of a command, so you would still need to call a logging function on an error.回调只会在命令成功完成时触发,因此您仍然需要在出现错误时调用日志记录函数。

# 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")

This isn't a complete solution, but I hope it gives you enough to get started.这不是一个完整的解决方案,但我希望它能让您开始使用。 Here's an example of what the output looks like.下面是输出的示例。

> 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") 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM