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)
如何将所有级别为“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)