-
Notifications
You must be signed in to change notification settings - Fork 279
Logging #478
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
Logging #478
Changes from all commits
1d8c2f8
c3f1d83
dcca887
2eda4d4
e31988c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| using Logging, Dates | ||
|
|
||
|
|
||
| #### | ||
| #### Custom LogLevels | ||
| #### | ||
| _custom_log_level_docs = """ | ||
| Severity Order: | ||
| Debug < Diagnostic < Simulation < Setup < Info | ||
|
|
||
| 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 Simulation = Logging.LogLevel(-250) | ||
| const Setup = Logging.LogLevel(-125) | ||
|
|
||
|
|
||
| #### | ||
| #### ModelLogger | ||
| #### | ||
| _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 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By the way, you will have noticed how this way of using custom levels isn't really composable, and doesn't really work well with the default Here's my current attempt to clean up that situation (comments welcome): JuliaLang/julia#33960 |
||
| else | ||
| string(level) | ||
| end | ||
| 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]") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
| formatted_message = "$message --- $msg_timestamp $level_name $file_name:$line_number" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚀 |
||
| println(iob, formatted_message) | ||
| write(logger.stream, take!(buf)) | ||
| return nothing | ||
| end | ||
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was mimicking what was done Base/Logging for the macros.
https://github.com/JuliaLang/julia/blob/46ce4d79337bdd257ee2e3d2f4bb1c55ff0a5030/base/logging.jl#L132