I tried the example in the documentation a couple of times but I can’t get Julia to write to both console and file. The code in the documentation:
# Load the logging module
# Open a textfile for writing
io = open("log.txt", "w+")
# Create a simple logger
logger = SimpleLogger(io)
# Log a task-specific message
@info("a context specific log message")
# Write all buffered messages to the file
# Set the global logger to logger
# This message will now also be written to the file
@info("a global log message")
# Close the file
The message will now also be written to the file comment, the only thing that gets written to the file is:
┌ Info: a context specific log message
└ @ Main /Users/adrian/Downloads/logtest.jl:12
Not sure if you’re using Juno, but if you are, then it’s kinda expected (although unfortunate) that setting the global logger must be executed separately.
Your example works fine in a “normal” environment.
Oh yes, I was trying in Juno. Indeed, running
$ julia logtest.jl works as expected. Thanks!
Now that I think about this again I’m not sure why this is the behaviour I went with though. This might be supported in the next Atom release (see here).
I will probably write a longer discourse thread on the topic of the logger, it seems a bit iffy. I can’t get consistent behaviour even within my scripts (running it from the REPL). Most common result is that eventually nothing gets outputted to file nor to the console. Also, attempting to access the vars used for logging (like the ones related to the buffer) sometimes leads to Julia crashing.
Design-wise, I don’t really get how it’s meant to be used. As a library author I want to use one logging command, ie
@error ... and have this command tapping into whatever logging configuration the user app has defined. The fact that logging to console works with just
@error but logging to file also requires
flush doesn’t feel right.
First of all, it requires knowing where is it logging, which is not a concern of the library author (hopefully in the near future we’ll also be able to log to external logging services, we don’t want to expose the internals of that with
api_flush or whatever). Second, it turns all calls to logging into two commands (
flush). Third, how am I to know what is the optimum flushing moment? Will the buffer overflow and cause the app to crash if the user doesn’t flush the buffer in time? In a web app, when am I supposed to flush? At the end of each request or should I set up a timed thread to do the flushing? What if the user uses my library at the REPL?
I’m happy to see that Julia is adding native logging capabilities. My experience is that logging is a very nasty problem that requires careful design. In Genie I used about 4 logging libraries so far and they all had their problems and limitations - I wasted an unholy amount of time tweaking logging libraries and I’m still not happy. I’m looking forward to a powerful native logger. Logging is key to understanding and debugging long time running server applications.
That really depends on what logger is used, no? I think most of your issues stem from the fact that you’re using the
SimpleLogger, which probably is too, well, simple for your needs
Writing your own
FileLogger that flushes file io automatically is relatively easy, so I’d recommend trying that. Arguably we should have that in
Indeed. I will attempt to write that for Genie - hopefully I’ll be able to contribute it to Julia’s Logger.
Dropping these, in case other Julians might stumble upon this thread. There are a few efforts for extending
Logging. I haven’t tested them yet but they look promising. I’ll report back once I try them.
I tested both
IOLogging and found that
LoggingExtras works perfectly for logging to multiple backends at once. It also provides additional features, such as the ability to filter log messages by user-defined rules. Added bonus, it seems extendable enough to allow adding other logging backends, such as system or web services.