-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Some logging printing improvements #25111
Conversation
fredrikekre
commented
Dec 15, 2017
•
edited
Loading
edited
- use user customizable colors in logging
- nice box drawing chars
- print line info after key value pairs
- always put the line info on its own line for multiline messages
- don't show the loglevel in the location info since it is already printed in the beginning of the message
- use showerror to print exceptions rather than their string representation
cc @c42f |
Can we spell out the whole words of "info," "warning," and "error"? I, W, and E is pretty non-descriptive. |
Agree: I understand why you want a single-letter prefix, but it's a bit cryptic. However, as I understand it, perhaps the plan is to add a |
Having the names short makes the text align nicely and the colors should make it obvious what the intention is. |
You can still get alignment with something like
|
would be nice to have a different color for the location |
Or this:
|
Thanks, it's great to have some more people looking at formatting (and no surprise that it's the first thing people want to change :-) ). I like the look of the unicode bracketing. As for where to put this - I've been trying to avoid features in Regarding the prefix being variable width - IMO it's a critical point that the metadata should be nonintrusive and not create additional lines. Otherwise I predict that people will want what they get from See also how How about I create a straw man PR which ports |
TBH I don't see the changes here as features, this is just clearing things up, and just because the
That would be nice, perhaps it should be a |
Is it really REPL-specific? Don't you want to use the same kind of output if you're running a script in the terminal without a REPL? |
base/logging.jl
Outdated
msg = "Exception while generating log record:\n" | ||
str = join(" " .* split(sprint(showerror, err), "\n"), "\n") | ||
msg *= str | ||
handle_message(logger, Error, msg, _module, group, id, filepath, line) |
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 don't think this should be done inside dispatch_message
as that will bake in display logic in a way which can't be overridden. Rather, I think it should be part of the logger. See for example https://github.com/JuliaLang/julia/pull/25136/files#diff-f1d5a62767988822d6e6fd5db69f5ea9R79
I've thrown together something over at #25136. It's a bit rough and ready, but can serve as a point of reference if nothing else. But regardless of that these changes to prettify Sorry about the lack of documentation. I was still working on it when #24490 got merged - it's still on my todo list! |
My suggestions (from #25138):
I really like the boxed printing! |
I really don't like the idea of having However, it's important that warnings and errors be easy to see. Perhaps we just don't need consistency here between levels, and we can prepend {WARNING,ERROR} but append {INFO,DEBUG} (after all, this is not the one and only true format - it's for maximum readability in the repl). This also lets us kill off another character in the prefix, and just go with the colored bracketing on the left hand side. |
I disagree, I actually appreciate the |
What's the function of |
It tells you that you're seeing in informational log message rather than normal output of your program. |
Sure but I think that will be quite adequately conveyed by having the |
Ok, well, give it a shot and let's see how it looks! |
Indeed! It might just be ugly, we'll see. |
One Important note is that not everywhere color is enabled and there are also colorblind people, so we shouldn't rely on color to much and without color the single character prefix is less distinct. Having this configurable would be great. |
which are all related and subtly different. I think there are lots of formats that communicate some but not all of these, and it would be nice to have one that communicated all of them. |
I also think there's a strong case to be made for keeping these log messages simple and uniform. If we want to get more elaborate, we can experiment with that in external loggers and then import features if they work out really well in the future. |
I'll add that the first time I saw |
100% agree. Just print the fully spelled out |
Seems that the conclusion is to write out the full names as previously. I will rebase and fixup the PR when I get some time over. |
base/logging.jl
Outdated
handle_message(logger, Error, msg, _module, group, id, filepath, line; exception=err) | ||
msg = "Exception while generating log record:\n" | ||
msg *= join(" " .* split(sprint(showerror, err), "\n"), "\n") | ||
handle_message(logger, Error, msg, _module, group, id, filepath, line) |
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 still think this small part here should be reverted - it's in the wrong place because it's not the job of the log dispatch machinery to do formatting. Formatting is the job of the installed Logger. Doing formatting here is also inconsistent with the convention I've followed for exception logging elsewhere in Base
.
If you want a replacement, it's quite easy to get equivalent but more general functionality by improving the way we print key value pairs in SimpleLogger
when they're Exception
s.
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.
That's what I did at first, but it felt weird to generate part of the message here and part of the message in handle_message
. It is also nice not to have special casing inside handle_message
based on typeof(val)
.
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.
Perhaps the full try-catch should me moved to handle_message
instead?
end | ||
for (key,val) in pairs(kwargs) | ||
print_with_color(color, iob, "│ ", bold=true) | ||
println(iob, " ", key, " = ", val) |
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.
In particular - if you want exceptions to be readable, it's the printing of val
on this line here which should be beefed up.
Other than the issue with where exception formatting is done, this looks good to me. I think it's appropriate to live without right justification for |
Should we merge this now and fix the mentioned implementation issue after or wait to tweak that? |
After thinking about it a bit more I think that the current implementation is correct; If we get an exception we should generate the full message (i.e. Also, it is really weird to special case based on the key-value pair. If we special case on the key, (i.e. if If we special case on the value (i.e. |
I think the disconnect here is because you're thinking of log records in terms of what you see (ie, as text), but having them as structured data is much more powerful. For example, consider log filtering and reduction. You might want to filter logs by the exception type they contain - if the exception has already been transformed into text, the logger is limited to some regex matching or some such. If the exception is present as data, you can simply filter the attached exceptions using Elsewhere in Base, I've consistently emitted errors as follows (and as suggested in the logging macro docstring):
It's very easy to make something readable out of this by having a function |
I struggled with this for a while when designing the system. I eventually came to the conclusion that formatting based on the type of the value was the correct thing. For example suppose you have two exceptions to attach to the same
Sure, and that's correct. I'm not sure what else you could possibly want from this - if you explicitly attach an exception, you should see it, right? I won't pretend I have all the answers to how formatting should work in all cases here, but the crucial point is that |
Perhaps add a keyword argument to |
What's wrong with passing it as a key value pair? Using a plain key value pair simplifies the data model and is consistent with the way users should pass exceptions. (Unless we were to add a special way for them to pass exceptions, but I just don't see that as necessary.) If we want to distinguish cases where the log generation itself failed, how about flagging this by setting |
Fine, we can call |
Thanks, I know I'm being pretty inflexible on what might seem like a small matter, I just feel this is an important matter of consistency for the design as a whole. Please bear with me while I try to get the design out of my head and into some documentation / examples.
Good question. The reason for having For example, suppose I've got a long running process which is behaving strangely and needs to be debugged without restarting. So I turn on debug logging to see what's happening, but someone has a buggy For the message generation closure, if you look at the way it's called you'll see it's somewhat complicated. I think this is a bit ugly and I wanted to avoid making it a public interface. There might be some room for improvement here. For example, if the closure was changed to take no arguments, but to return the message and the key value pairs, perhaps it would be simple enough to defer message generation completely by passing the closure to |
I understand the try-catch that then prints to |
- use user customizable colors - nice box drawing chars - print line info after key value pairs - always put the line info on its own line for multiline messages - indent key-value pair - print line info in grey
There's a reason to have both. Consider someone had written @info "Current value" a÷b This is fine until the unexpected happens and If this call to |
This is a very familiar problem... Good luck! |
Could we have a last resort logging function that does something really simple like log "something went wrong with the logging infrastructure" and make sure that we test that this works somehow? |
Well, we could have an extra layer of try-catch, though that seems a little excessive? Or we could be more conservative about formatting inside the first retry? Ultimately there's only so much we can do because the user is free to install an arbitrarily broken logger. When I talk about "last resort" I'm talking about this case. |
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 reckon we merge this, it's quite an improvement on the current formatting.
@@ -483,23 +483,30 @@ function handle_message(logger::SimpleLogger, level, message, _module, group, id | |||
logger.message_limits[id] = remaining - 1 | |||
remaining > 0 || return | |||
end | |||
levelstr = string(level) |
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.
Changing this could end up a bit misleading for custom log levels.
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.
@c42f would you be OK with renaming Warn
to Warning
? The reason for this change is that all the other levels are nouns, and I prefer we print Warning
over Warn
.
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.
Yes, it's Warn
vs Warning
which is the sticking point here. The upside of the current naming is that Warn
is consistent with @warn
, and all the standard levels are four or five characters long.
So it seems impossible to have complete consistency without renaming to @warning
in which case I'd rather just leave it as it currently is. Of course, we can just special case the printing more or less as you've done, but taking into account custom levels. I agree it's not entirely satisfying.
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.
Warning
seems very standarded to use, looking at random pictures of logging on google... Forcing the levelstr
to be the same as the macro used seems a bit inflexible imo. Why can't we use @warn
and print it as Warning
?
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.
Certainly, we can print it differently for logging output, absolutely no problem with that. I thought the issue was about the named constant Logging.Warn::LogLevel
.
For achieving "Warning" printed in the output we can have
string(Logging.Warn) == "Warning"
- seems too inconsistent to really consider.- Rename
Logging.Warn
->Logging.Warning
(which I thought was being suggested above). I'm not so keen on that, for the reasons of consistency with the spelling of@warn
. - Just special case the output formatting, as is done already. This seems the best of the lot IMO, though not entirely satisfying.
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.
Perhaps I was confused about what @fredrikekre was suggesting. Sorry if I was misunderstanding.
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.
No probs, I really wish we could get together in the same room to discuss where this stuff is going. It's super slow and easy to get confused / talk at cross purposes in text.
Option (2) is a reasonable way out if you want to try it @fredrikekre and see how it feels? I'm not really sure where the best compromise of (2) vs (3) lies. They both have some inconsistencies, unfortunately.
Thanks.
I agree that this should be sent to the logger, and understand the second call to |
+2, this printing is much nicer. I hate to rain on the parade, but the fact is there are many cases in src/ and base/ where we print |
True, but could be resolved pretty easily with a search-and-replace for "WARNING" and "ERROR". |
Do people prefer |
I'm fine with titlecase. All caps was a bit screamy. Color should be plenty for people to notice. |
@JeffBezanson I'm working on it. Please have a look at #25257 for the first installment which fixes the cases in parsing/lowering. I've also got a second installment which provides tools to do the same in the other parts of |