Skip to content

Commit

Permalink
Merge pull request #43 from Arkoniak/42-show-errorlevel-names
Browse files Browse the repository at this point in the history
feat: log level names (#42)
  • Loading branch information
Arkoniak authored Feb 19, 2024
2 parents e0dc981 + ff8ebbc commit 6582ae1
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "MiniLoggers"
uuid = "93f3dd0f-005d-4452-894a-a31841fa4078"
authors = ["Andrey Oskin and contributors"]
version = "0.5.2"
version = "0.5.3"

[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Expand Down
11 changes: 7 additions & 4 deletions src/jsonlogger.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
struct JsonLogger{AM <: AbstractMode, IOT1 <: IO, IOT2 <: IO, DFT <: DateFormat} <: AbstractMiniLogger
struct JsonLogger{AM <: AbstractMode, IOT1 <: IO, IOT2 <: IO, DFT <: DateFormat, F} <: AbstractMiniLogger
io::IOT1
ioerr::IOT2
errlevel::LogLevel
Expand All @@ -12,6 +12,7 @@ struct JsonLogger{AM <: AbstractMode, IOT1 <: IO, IOT2 <: IO, DFT <: DateFormat}
flush_threshold::Int
lastflush::Base.RefValue{Int64}
lock::ReentrantLock # thread-safety of message_limits Dict
levelname::F
end

"""
Expand All @@ -29,6 +30,7 @@ Supported keyword arguments include:
* `squash_delimiter`: (default: "\\t"): defines which delimiter to use when squashing multilines messages.
* `flush_threshold::Union{Integer, TimePeriod}` (default: 0): if this argument is nonzero and `flush` is `true`, then `io` is flushed only once per `flush_threshold` milliseconds. I.e. if time between two consecutive log messages is less then `flush_threshold`, then second message is not flushed and will have to wait for the next log event.
* `dtformat` (default: "yyyy-mm-dd HH:MM:SS"): if `datetime` parameter is used in `format` argument, this dateformat is applied for output timestamps.
* `levelname` (default `string`): allows to redefine output of log level names. Should be function of the form `levelname(level::LogLevel)::String`
* `format`: defines which keywords should be used in the output. If defined, should be a string which defines the structure of the output json. It should use keywords, and allowed keywords are:
* `timestamp`: timestamp of the log message
* `level`: name of log level (Debug, Info, etc)
Expand All @@ -44,7 +46,7 @@ Format string should consists of comma separated tokens. In it's simplest form,
By default, `format` is `timestamp,level,basename,line,message`.
"""
function JsonLogger(; io = stdout, ioerr = stderr, errlevel = Error, minlevel = Info, append = false, message_limits = Dict{Any, Int}(), flush = true, format = "timestamp,level,basename,line,message", dtformat = dateformat"yyyy-mm-dd HH:MM:SS", flush_threshold = 0, squash_delimiter = "\t")
function JsonLogger(; io = stdout, ioerr = stderr, errlevel = Error, minlevel = Info, append = false, message_limits = Dict{Any, Int}(), flush = true, format = "timestamp,level,basename,line,message", dtformat = dateformat"yyyy-mm-dd HH:MM:SS", flush_threshold = 0, squash_delimiter = "\t", levelname = string)
tio = getio(io, append)
tioerr = io == ioerr ? tio : getio(ioerr, append)
lastflush = Dates.value(Dates.now())
Expand All @@ -60,7 +62,8 @@ function JsonLogger(; io = stdout, ioerr = stderr, errlevel = Error, minlevel =
squash_delimiter,
getflushthreshold(flush_threshold),
Ref(lastflush),
ReentrantLock())
ReentrantLock(),
levelname)
end

function handle_message(logger::JsonLogger, level, message, _module, group, id,
Expand All @@ -87,7 +90,7 @@ function handle_message(logger::JsonLogger, level, message, _module, group, id,
if val == "timestamp"
print(iob, "\"", tsnow(logger.dtformat), "\"")
elseif val == "level"
print(iob, "\"", string(level), "\"")
print(iob, "\"", logger.levelname(level), "\"")
elseif val == "filepath"
print(iob, "\"", filepath, "\"")
elseif val == "basename"
Expand Down
11 changes: 7 additions & 4 deletions src/minilogger.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
struct MiniLogger{AM <: AbstractMode, IOT1 <: IO, IOT2 <: IO, DFT <: DateFormat} <: AbstractMiniLogger
struct MiniLogger{AM <: AbstractMode, IOT1 <: IO, IOT2 <: IO, DFT <: DateFormat, F} <: AbstractMiniLogger
io::IOT1
ioerr::IOT2
errlevel::LogLevel
Expand All @@ -12,6 +12,7 @@ struct MiniLogger{AM <: AbstractMode, IOT1 <: IO, IOT2 <: IO, DFT <: DateFormat}
flush_threshold::Int
lastflush::Base.RefValue{Int64}
lock::ReentrantLock # thread-safety of message_limits Dict
levelname::F
end

getmode(mode) = mode
Expand Down Expand Up @@ -49,6 +50,7 @@ Supported keyword arguments include:
* `flush` (default: `true`): whether to `flush` IO stream for each log message. Flush behaviour also affected by `flush_threshold` argument.
* `flush_threshold::Union{Integer, TimePeriod}` (default: 0): if this argument is nonzero and `flush` is `true`, then `io` is flushed only once per `flush_threshold` milliseconds. I.e. if time between two consecutive log messages is less then `flush_threshold`, then second message is not flushed and will have to wait for the next log event.
* `dtformat` (default: "yyyy-mm-dd HH:MM:SS"): if `datetime` parameter is used in `format` argument, this dateformat is applied for output timestamps.
* `levelname` (default `string`): allows to redefine output of log level names. Should be function of the form `levelname(level::LogLevel)::String`
* `format` (default: "[{timestamp:func}] {level:func}: {message}"): format for output log message. It accepts following keywords, which should be provided in curly brackets:
* `timestamp`: timestamp of the log message
* `level`: name of log level (Debug, Info, etc)
Expand All @@ -66,7 +68,7 @@ Colour information is applied recursively without override, so `{{line} {module:
If part of the format is not a recognised keyword, then it is just used as is, for example `{foo:red}` means that output log message contain word "foo" printed in red.
"""
function MiniLogger(; io = stdout, ioerr = stderr, errlevel = Error, minlevel = Info, append = false, message_limits = Dict{Any, Int}(), flush = true, format = "[{timestamp:func}] {level:func}: {message}", dtformat = dateformat"yyyy-mm-dd HH:MM:SS", flush_threshold = 0, message_mode = Squash(), squash_delimiter = "\t")
function MiniLogger(; io = stdout, ioerr = stderr, errlevel = Error, minlevel = Info, append = false, message_limits = Dict{Any, Int}(), flush = true, format = "[{timestamp:func}] {level:func}: {message}", dtformat = dateformat"yyyy-mm-dd HH:MM:SS", flush_threshold = 0, message_mode = Squash(), squash_delimiter = "\t", levelname = string)
tio = getio(io, append)
tioerr = io == ioerr ? tio : getio(ioerr, append)
lastflush = Dates.value(Dates.now())
Expand All @@ -82,7 +84,8 @@ function MiniLogger(; io = stdout, ioerr = stderr, errlevel = Error, minlevel =
squash_delimiter,
getflushthreshold(flush_threshold),
Ref(lastflush),
ReentrantLock())
ReentrantLock(),
levelname)
end


Expand Down Expand Up @@ -156,7 +159,7 @@ function handle_message(logger::MiniLogger, level, message, _module, group, id,
end
end
elseif val == "level"
levelstr = string(level)
levelstr = logger.levelname(level)
printwcolor(iob, levelstr, c)
elseif val == "basename"
printwcolor(iob, basename(filepath), c)
Expand Down
41 changes: 41 additions & 0 deletions test/test05_levelnames.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module LevelNamesTest
using MiniLoggers
using Logging: LogLevel, BelowMinLevel, Debug, Info, Warn, Error, AboveMaxLevel
using ReTest

function levelname(level::LogLevel)
if level == Debug "MYDEBUG"
elseif level == Info "MYINFO"
else "LOG"
end
end

@testset "MiniLogger Level Names" begin
buf = IOBuffer()
iob = IOContext(buf, stdout)

with_logger(MiniLogger(io = iob, minlevel = MiniLoggers.Debug, format = "level", levelname = levelname)) do
@info ""
@debug ""
@warn ""
end

s = String(take!(buf))
@test s == "MYINFO\nMYDEBUG\nLOG\n"
end

@testset "JsonLogger Level Names" begin
buf = IOBuffer()
iob = IOContext(buf, stdout)

with_logger(JsonLogger(io = iob, minlevel = MiniLoggers.Debug, format = "level", levelname = levelname)) do
@info ""
@debug ""
@warn ""
end

s = String(take!(buf))
@test s == "{\"level\":\"MYINFO\"}\n{\"level\":\"MYDEBUG\"}\n{\"level\":\"LOG\"}\n"
end

end # module

2 comments on commit 6582ae1

@Arkoniak
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

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

Registration pull request created: JuliaRegistries/General/101181

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.5.3 -m "<description of version>" 6582ae19df9432dc047c0abe42959152eb03468c
git push origin v0.5.3

Please sign in to comment.