Skip to content

Commit 20229ff

Browse files
omusoxinabox
andauthored
Support function-like objects in FormatLogger (#102)
* Support function-like objects in `FormatLogger` * Rename `log_args` to `log` * Set project version to 1.2.0 * Add comment to `BasicLogFormatter` Co-authored-by: Frames White <[email protected]> * Remove backwards compatible field access * Make `FormatLogger` parametric * Docstring and comment updates --------- Co-authored-by: Frames White <[email protected]>
1 parent e215be9 commit 20229ff

File tree

4 files changed

+51
-24
lines changed

4 files changed

+51
-24
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "LoggingExtras"
22
uuid = "e6f89c97-d47a-5376-807f-9c37f3926c36"
33
authors = ["Frames White <[email protected]>", "Collaborators <https://github.com/JuliaLogging/LoggingExtras.jl/graphs/contributors>"]
4-
version = "1.1.0"
4+
version = "1.2.0"
55

66
[deps]
77
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"

src/Sinks/datetime_rotation.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ function DatetimeRotatingFileLogger(f::Union{Function,Nothing}, dir, filename_pa
7171
end
7272

7373
similar_logger(::SimpleLogger, io) = SimpleLogger(io, BelowMinLevel)
74-
similar_logger(l::FormatLogger, io) = FormatLogger(l.f, io, l.always_flush)
74+
similar_logger(l::FormatLogger, io) = FormatLogger(l.formatter, io, l.always_flush)
7575
function reopen!(drfl::DatetimeRotatingFileLogger)
7676
if drfl.current_file !== nothing
7777
# close the old IOStream and pass the file to the callback

src/Sinks/formatlogger.jl

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
1-
2-
struct FormatLogger <: AbstractLogger
3-
f::Function
1+
struct FormatLogger{T} <: AbstractLogger
2+
formatter::T
43
stream::IO
54
always_flush::Bool
65
end
76

87
"""
9-
FormatLogger(f::Function, io::IO=stderr; always_flush=true)
8+
FormatLogger(formatter, io::IO=stderr; always_flush=true)
109
1110
Logger sink that formats the message and finally writes to `io`.
12-
The formatting function should be of the form `f(io::IOContext, log_args::NamedTuple)`
13-
where `log_args` has the following fields:
11+
The formatting function or callable object should be of the form
12+
`formatter(io::IOContext, log::NamedTuple)` where `log` has the following fields:
1413
`(level, message, _module, group, id, file, line, kwargs)`.
15-
See [`LoggingExtras.handle_message_args`](@ref) for more information on what field is.
14+
15+
See [`LoggingExtras.handle_message_args`](@ref) for more information on what each field is.
1616
1717
# Examples
1818
```julia-repl
1919
julia> using Logging, LoggingExtras
2020
21-
julia> logger = FormatLogger() do io, args
22-
println(io, args._module, " | ", "[", args.level, "] ", args.message)
21+
julia> logger = FormatLogger() do io, log
22+
println(io, log._module, " | ", "[", log.level, "] ", log.message)
2323
end;
2424
2525
julia> with_logger(logger) do
@@ -30,31 +30,31 @@ Main | [Info] This is an informational message.
3030
Main | [Warn] This is a warning, should take a look.
3131
```
3232
"""
33-
function FormatLogger(f::Function, io::IO=stderr; always_flush=true)
34-
return FormatLogger(f, io, always_flush)
33+
function FormatLogger(formatter, io::IO=stderr; always_flush=true)
34+
return FormatLogger(formatter, io, always_flush)
3535
end
3636

3737
"""
38-
FormatLogger(f::Function, path::AbstractString; append=false, always_flush=true)
38+
FormatLogger(formatter, path::AbstractString; append=false, always_flush=true)
3939
40-
Logger sink that formats the message and writes it to the file at `path`. This is similar
41-
to `FileLogger` except that it allows specifying the printing format.
40+
Logger sink that formats the message and writes it to the file at `path`. This is similar
41+
to [`FileLogger`](@ref) except that it allows specifying the printing format.
4242
4343
To append to the file (rather than truncating the file first), use `append=true`.
4444
If `always_flush=true` the stream is flushed after every handled log message.
4545
"""
46-
function FormatLogger(f::Function, path::AbstractString; append::Bool=false, kw...)
46+
function FormatLogger(formatter, path::AbstractString; append::Bool=false, kw...)
4747
io = open(path, append ? "a" : "w")
48-
return FormatLogger(f, io; kw...)
48+
return FormatLogger(formatter, io; kw...)
4949
end
5050

5151
function handle_message(logger::FormatLogger, args...; kwargs...)
52-
log_args = handle_message_args(args...; kwargs...)
52+
log = handle_message_args(args...; kwargs...)
5353
# We help the user by passing an IOBuffer to the formatting function
5454
# to make sure that everything writes to the logger io in one go.
5555
iob = IOBuffer()
5656
ioc = IOContext(iob, logger.stream)
57-
logger.f(ioc, log_args)
57+
logger.formatter(ioc, log)
5858
write(logger.stream, take!(iob))
5959
logger.always_flush && flush(logger.stream)
6060
return nothing

test/runtests.jl

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,16 +197,28 @@ end
197197
end
198198
end
199199

200+
# Intentionally not subtype `Function` here to test function-like object support
201+
Base.@kwdef struct BasicLogFormatter
202+
include_module::Bool=true
203+
end
204+
205+
function (formatter::BasicLogFormatter)(io::IO, log::NamedTuple)
206+
if formatter.include_module
207+
print(io, log._module, " | ")
208+
end
209+
println(io, "[", log.level, "] ", log.message)
210+
end
211+
200212
@testset "FormatLogger" begin
201213
io = IOBuffer()
202-
logger = FormatLogger(io) do io, args
214+
logger = FormatLogger(io) do io, log
203215
# Put in some bogus sleep calls just to test that
204216
# log records writes in one go
205-
print(io, args.level)
217+
print(io, log.level)
206218
sleep(rand())
207219
print(io, ": ")
208220
sleep(rand())
209-
println(io, args.message)
221+
println(io, log.message)
210222
end
211223
with_logger(logger) do
212224
@sync begin
@@ -231,7 +243,7 @@ end
231243
mktempdir() do dir
232244
f = joinpath(dir, "test.log")
233245

234-
logger = FormatLogger(f) do io, args
246+
logger = FormatLogger(f) do io, log
235247
println(io, "log message")
236248
end
237249

@@ -242,6 +254,21 @@ end
242254
l = read(f, String)
243255
@test startswith(l, "log message")
244256
end
257+
258+
# test function-like objects/functor are supported
259+
io = IOBuffer()
260+
with_logger(FormatLogger(BasicLogFormatter(; include_module=true), io)) do
261+
@info "test message"
262+
end
263+
str = String(take!(io))
264+
@test str == "$(@__MODULE__()) | [Info] test message\n"
265+
266+
io = IOBuffer()
267+
with_logger(FormatLogger(BasicLogFormatter(; include_module=false), io)) do
268+
@warn "test message"
269+
end
270+
str = String(take!(io))
271+
@test str == "[Warn] test message\n"
245272
end
246273

247274
@testset "LevelOverrideLogger" begin

0 commit comments

Comments
 (0)