This seems to do the job. I can do:
using Logging
using Dates
include("MyLogger.jl")
# --- custom logging with time-stamp included
lg = MyLogger()
with_logger(lg) do
@info "a context specific log message"
end
which yields
┌ 2021-06-23T18:00:36.118
│ Info: a context specific log message
└ @ Main --- REPL[6]:2
The custom logger definition is as follows.
struct MyLogger <: AbstractLogger
stream::IO
min_level::LogLevel
message_limits::Dict{Any,Int}
end
MyLogger(stream::IO=stderr, level=Logging.Info) = MyLogger(stream, level, Dict{Any,Int}())
Logging.shouldlog(logger::MyLogger, level, _module, group, id) =
get(logger.message_limits, id, 1) > 0
Logging.min_enabled_level(logger::MyLogger) = logger.min_level
Logging.catch_exceptions(logger::MyLogger) = false
function Logging.handle_message(logger::MyLogger, level, message, _module, group, id,
filepath, line; maxlog=nothing, kwargs...)
if maxlog !== nothing && maxlog isa Integer
remaining = get!(logger.message_limits, id, maxlog)
logger.message_limits[id] = remaining - 1
remaining > 0 || return
end
buf = IOBuffer()
iob = IOContext(buf, logger.stream)
levelstr = level == Logging.Warn ? "Warning" : string(level)
msglines = split(chomp(string(message)), '\n')
println(iob, "┌ ", now()) # ----------------------------------[ inserting time-stamp]
println(iob, "│ ", levelstr, ": ", msglines[1])
for i in 2:length(msglines)
println(iob, "│ ", msglines[i])
end
for (key, val) in kwargs
println(iob, "│ ", key, " = ", val)
end
println(iob, "└ @ ", something(_module, "nothing"), " --- ",
something(filepath, "nothing"), ":", something(line, "nothing"))
write(logger.stream, take!(buf))
nothing
end