如何过滤消息

在此教程中,我们将看到如何基于元数据(level, module等)和日志消息内容来过滤消息。在如何启用 @debug 消息发送消息到多个位置中有如何基于日志级别过滤消息的示例。

在日志系统消息管道中,可以分两个阶段过滤消息。在第一阶段,只有元数据是已知的(level, module, group, 和 id)。特别是消息字符串本身尚未构建,如果创建日志消息的成本很高,则在此阶段进行过滤可能会更有效。例如,在

@info "The value of some_expensive_call is: $(some_expensive_call(args...))"

中,在早期阶段还未发生对 some_expensive_call 的调用。当有更多信息可用时,例如完整的消息字符串、文件和行以及任何关键字参数,消息也可以稍后过滤。

早期过滤使用 EarlyFilteredLogger

可以使用 LoggingExtras.jl 包中的 EarlyFilteredLogger 来完成早期阶段的过滤。EarlyFilteredLogger 需要一个谓词函数和一个记录器作为输入参数。如果谓词返回 true,则消息被传递给包装的记录器,否则被忽略。谓词函数的唯一输入是一个命名元组,请参阅 LoggingExtras.shouldlog_args

这是一个记录器的示例,它只接受 (i)Logging.Info 级别(Logging.Info <= level < Logging.Warn)的消息和 (ii) 来自 Foo 模块的消息:

using Logging, LoggingExtras

# Define the Foo module
module Foo
    info() = @info "Information from Foo"
    warn() = @warn "Warning from Foo"
end
using .Foo

# Create the logger
logger = EarlyFilteredLogger(global_logger()) do args
    r = Logging.Info <= args.level < Logging.Warn && args._module === Foo
    return r
end

# Test it
with_logger(logger) do
    @info "Information from Main"
    @warn "Warning from Main"
    Foo.info()
    Foo.warn()
end
[ Info: Information from Foo

如您所见,唯一没有被过滤器丢弃的是来自 Foo 模块的 @info 消息!

Note

MinLevelLogger 只是 EarlyFilteredLogger 的一个特例,它只检查消息的日志级别是否高于配置的级别。

TeeLogger 一起,我们现在可以为消息创建任意路由。这是一个更复杂的例子:

using Logging, LoggingExtras

logger = TeeLogger(
    global_logger(),
    EarlyFilteredLogger(
        args -> args._module === WebServer,
        TeeLogger(
            EarlyFilteredLogger(
                args -> args.level < Logging.Info,
                FileLogger("debug.log"),
            ),
            EarlyFilteredLogger(
                args -> Logging.Info <= args.level < Logging.Warn,
                FileLogger("info.log"),
            ),
            EarlyFilteredLogger(
                args -> Logging.Warn <= args.level,
                FileLogger("warnings_and_errors.log"),
            ),
        )
    ),
)

此记录器将所有消息发送到当前的全局记录器和 EarlyFilteredLogger. 然后 EarlyFilteredLogger 丢弃所有不是来自 WebServer 模块的消息,并将剩余的消息发送到新的 TeeLogger. 此TeeLogger 会将消息发送到三个 EarlyFilteredLoggers,它们只保留特定级别的消息并将这些消息发送到对应于该级别的 FileLogger。这意味着,"debug.log" 只有来自 WebServer(第一个过滤器)并且具有 debug 日志级别的消息。类似地, "info.log" 中只会有 info 日志级别的消息,任何更高级别(warn, error)的消息都将位于 "warnings_and_errors.log" 中。

后期过滤使用 ActiveFilteredLogger

如果基于级别、模块、组和 id 的过滤不够,可以使用 ActiveFilteredLogger,它也来自 LoggingExtras.jl 包。此记录器类似于 EarlyFilteredLogger,唯一的区别是传给谓词函数的命名元组包含更多数据,请参阅 LoggingExtras.handle_message_args。以下是根据消息字符串内容进行过滤的记录器示例:

using Logging, LoggingExtras

logger = ActiveFilteredLogger(global_logger()) do args
    return args.message == "Hello there!" || args.message == "General Kenobi!"
end

with_logger(logger) do
    @info "I find your lack of faith disturbing."
    @info "Hello there!"
    @info "General Kenobi!"
    @info "Power! Unlimited power!"
end
[ Info: Hello there!
[ Info: General Kenobi!