futile.logger 向 stderr 发出警告

futile.logger warn to stderr

如何将所有级别为“warn”的日志发送到 stderr 而不是 stdout,但仍将所有“info”和“debug”日志保留在 stdout 中?我的设置如下所示:

library(futile.logger)
options(warn=1)

logFileName <- paste0(outdir, "/", projectID, ".log")
flog.appender(appender.tee(logFileName))
flog.threshold(DEBUG)
flog.carp(TRUE)

appender 函数负责将日志行发送到输出 目的地;您需要定义一个自定义附加程序。

futile.logger中,appender只接收日志行,不接收日志 与之关联的级别。您可以尝试根据 线,并根据它选择目的地。这样做的确切逻辑 将取决于您的布局功能。使用默认选项 (layout.simple()) 该逻辑可能如下所示:

appender.custom <- function(file) {
  function(line) {
    level <- regmatches(line, regexpr("\w+(?= \[)", line, perl = TRUE))
    dest <- if (get(level) > WARN) stdout() else stderr()
    cat(line, file = dest, sep = "")
    cat(line, file = file, append = TRUE, sep = "")
  }
}

然后你只需将这个自定义 appender 换成 appender.tee():

library(futile.logger)

logFileName <- tempfile(fileext = ".log")
flog.appender(appender.custom(logFileName))
#> NULL
flog.threshold(DEBUG)
#> NULL

local({
  flog.debug("Debug message.")
  flog.info("Info message.")
  flog.warn("Warning message.")
  flog.error("Error message.")
})
#> DEBUG [2020-11-17 16:52:31] Debug message.
#> INFO [2020-11-17 16:52:31] Info message.

cat(readLines(logFileName), sep = "\n")
#> DEBUG [2020-11-17 16:52:31] Debug message.
#> INFO [2020-11-17 16:52:31] Info message.
#> WARN [2020-11-17 16:52:31] Warning message.
#> ERROR [2020-11-17 16:52:31] Error message.
unlink(logFileName)

以上,捕获的输出不包括stderr,但这里是截图 非活动控制台中输出的样子:

从长远来看,解决这个问题的方法可能是一个功能请求 包作者还将消息的日志级别传递给附加程序 函数。

或者,如果您不打算坚持 futile.logger, 您可以使用 log4r 来为 appender 提供级别。你会 仍然需要自定义 appender,但无需尝试解析级别:

library(log4r)
#> 
#> Attaching package: 'log4r'
#> The following object is masked from 'package:base':
#> 
#>     debug

custom_appender <- function(layout = log4r::default_log_layout()) {
  WARN <- log4r::as.loglevel("WARN")
  function(level, ...) {
    msg <- layout(level, ...)
    level <- log4r::as.loglevel(level)
    dest <- if (level >= WARN) stderr() else stdout()
    cat(msg, file = dest, sep = "")
  }
}

log_file <- tempfile(fileext = ".log")
appenders <- list(file_appender(log_file), custom_appender())
logger <- logger("DEBUG", appenders = appenders)

local({
  debug(logger, "Debug message.")
  info(logger, "Info message.")
  warn(logger, "Warning message.")
  error(logger, "Error message.")
})
#> DEBUG [2020-11-17 16:52:31] Debug message.
#> INFO  [2020-11-17 16:52:31] Info message.

cat(readLines(log_file), sep = "\n")
#> DEBUG [2020-11-17 16:52:31] Debug message.
#> INFO  [2020-11-17 16:52:31] Info message.
#> WARN  [2020-11-17 16:52:31] Warning message.
#> ERROR [2020-11-17 16:52:31] Error message.
unlink(log_file)