Skip to content
Merged
Changes from 3 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
72 changes: 72 additions & 0 deletions src/logger.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import Logging, Dates
export ModelLogger, shouldlog, min_enabled_level, catch_exceptions, handle_message


# -------------------------------------------------------------------------------------
# Custom LogLevels
Comment thread
arcavaliere marked this conversation as resolved.
Outdated
_custom_log_level_docs = """

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Out of curiousity, why assign the docstring to a variable?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Severity Order:
Debug < Diagnostic < Info < Setup < Warn < Error

Usage:
@logmsg Logging.LogLevel "Log Message"

@logmsg comes from Base/Logging
LogLevel can be any Base/Logging.LogLevel
Log Message can be any expression that evaluates to a string (preferably human readable!)
"""

const Diagnostic = Logging.LogLevel(-500) # Sits between Debug and Info
const Setup = Logging.LogLevel(500)

# ------------------------------------------------------------------------------------
# ModelLogger
Comment thread
arcavaliere marked this conversation as resolved.
Outdated
_model_logger_docs = """

ModelLogger(stream::IO, level::LogLevel)

Based on Logging.SimpleLogger it tries to log all messages in the following format

message --- [dd/mm/yyyy HH:MM:SS] log_level source_file:line_number

The logger will handle any message from Diagnostic up by default.
"""
struct ModelLogger <: Logging.AbstractLogger

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Yes, this is the correct way to do this :-)

stream::IO
min_level::Logging.LogLevel
message_limits::Dict{Any,Int}
end
ModelLogger(stream::IO=stderr, level=Diagnostic) = ModelLogger(stream, level, Dict{Any,Int}())

Logging.shouldlog(logger::ModelLogger, level, _module, group, id) = get(logger.message_limits, id, 1) > 0

Logging.min_enabled_level(logger::ModelLogger) = logger.min_level

Logging.catch_exceptions(logger::ModelLogger) = false

function level_to_string(level::Logging.LogLevel)
if level == Diagnostic "Diagnostic"
elseif level == Setup "Setup"
elseif level == Logging.Warn "Warning"
else string(level)
end
Comment thread
arcavaliere marked this conversation as resolved.
Outdated
end

function Logging.handle_message(logger::ModelLogger, 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)
level_name = level_to_string(level)
module_name = something(_module, "nothing")
file_name = something(filepath, "nothing")
line_number = something(line, "nothing")
msg_timestamp = Dates.format(Dates.now(), "[dd/mm/yyyy HH:MM:SS]")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is how the system is meant to be used :-)

As you have found out, you can get timestamps for every message in your application by customizing the logging backend rather than messing with the @info statements themselves.

formatted_message = "$message --- $msg_timestamp $level_name $file_name:$line_number"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🚀

println(iob, formatted_message)
write(logger.stream, take!(buf))
nothing
Comment thread
arcavaliere marked this conversation as resolved.
Outdated
end