Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FirstMatchLogger #24

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -79,6 +79,7 @@ This package introduces 6 new loggers.
The `TeeLogger`, the `TransformerLogger`, 3 types of filtered logger, and the `FileLogger`.
All of them just wrap existing loggers.
- The `TeeLogger` sends the logs to multiple different loggers.
- The `FirstMatchLogger` also sends the logs to multiple different loggers but to only at most one logger for each log.
- The `TransformerLogger` applies a function to modify log messages before passing them on.
- The 3 filter loggers are used to control if a message is written or not
- The `MinLevelLogger` only allowes messages to pass that are above a given level of severity
@@ -100,6 +101,12 @@ It is up to those loggers to determine if they will accept it.
Which they do using their methods for `shouldlog` and `min_enabled_level`.
Or you can do, by wrapping them in a filtered logger as discussed below.

## `FirstMatchLogger`

The `FirstMatchLogger` sends the log messages to multiple places, like `TeeLogger`.
Unlike, `TeeLogger`, it only sends a log to at most one logger that can handle the
log message. The first match in the list of loggers is used.

## `FileLogger`
The `FileLogger` does logging to file.
It is just a convience wrapper around the base julia `SimpleLogger`,
2 changes: 1 addition & 1 deletion src/LoggingExtras.jl
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ import Base.CoreLogging:
AbstractLogger, SimpleLogger,
handle_message, shouldlog, min_enabled_level, catch_exceptions

export TeeLogger, TransformerLogger, FileLogger,
export TeeLogger, FirstMatchLogger, TransformerLogger, FileLogger,
ActiveFilteredLogger, EarlyFilteredLogger, MinLevelLogger


34 changes: 30 additions & 4 deletions src/tee.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
struct TeeLogger{T<:NTuple{<:Any, AbstractLogger}} <: AbstractLogger
abstract type AbstractTeeLogger <: AbstractLogger end

struct TeeLogger{T<:NTuple{<:Any, AbstractLogger}} <: AbstractTeeLogger
loggers::T
end

@@ -26,14 +28,38 @@ function handle_message(demux::TeeLogger, args...; kwargs...)
end
end

function shouldlog(demux::TeeLogger, args...)
function shouldlog(demux::AbstractTeeLogger, args...)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldlog, min_enabled_level, and catch_exceptions for FirstMatchLogger are all identical to TeeLogger so I created an abstract type. Is it OK?

any(comp_shouldlog(logger, args...) for logger in demux.loggers)
end

function min_enabled_level(demux::TeeLogger)
function min_enabled_level(demux::AbstractTeeLogger)
minimum(min_enabled_level(logger) for logger in demux.loggers)
end

function catch_exceptions(demux::TeeLogger)
function catch_exceptions(demux::AbstractTeeLogger)
any(catch_exceptions(logger) for logger in demux.loggers)
end


struct FirstMatchLogger{T<:NTuple{<:Any,AbstractLogger}} <: AbstractTeeLogger
loggers::T
end

"""
FirstMatchLogger(loggers...)
For each log message, invoke the first logger in `loggers` that
matches with it; i.e., `min_enabled_level` is less than or equal to
the log level and `shouldlog` returns `true`.
"""
function FirstMatchLogger(loggers::Vararg{AbstractLogger})
return FirstMatchLogger(loggers)
end

function handle_message(logger::FirstMatchLogger, args...; kwargs...)
for logger in logger.loggers
if comp_handle_message_check(logger, args...; kwargs...)
return handle_message(logger, args...; kwargs...)
end
end
end
25 changes: 25 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -31,6 +31,31 @@ using Base.CoreLogging: BelowMinLevel, Debug, Info, Warn, Error
end


@testset "FirstMatch" begin
@testset "contructor" begin
@testset "mixed types" begin
@test FirstMatchLogger(TestLogger(), NullLogger()) isa FirstMatchLogger
end

@testset "errors if given nonloggers" begin
@test_throws Exception FirstMatchLogger(stdout, stderr)
end
end
@testset "basic use with compositional levels" begin
testlogger_info = TestLogger(min_level=Info)
testlogger_warn = TestLogger(min_level=Warn)

with_logger(FirstMatchLogger(testlogger_warn, testlogger_info)) do
@info "info1"
@warn "warn1"
@info "info2"
end
@test length(testlogger_info.logs) == 2
@test length(testlogger_warn.logs) == 1
end
end


@testset "File" begin
mktempdir() do dir
filepath = joinpath(dir, "log")