Logging to console and file

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
using Logging

# Open a textfile for writing
io = open("log.txt", "w+")

# Create a simple logger
logger = SimpleLogger(io)

# Log a task-specific message
with_logger(logger) do
    @info("a context specific log message")
end

# Write all buffered messages to the file
flush(io)

# Set the global logger to logger
global_logger(logger)

# This message will now also be written to the file
@info("a global log message")

# Close the file
close(io)

Despite the 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.

2 Likes

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).

1 Like

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 (@error and 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.

1 Like

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 :slight_smile:

Writing your own FileLogger that flushes file io automatically is relatively easy, so I’d recommend trying that. Arguably we should have that in Logging though.

2 Likes

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.

https://github.com/oxinabox/LoggingExtras.jl

https://github.com/Seelengrab/IOLogging.jl

2 Likes

I tested both LoggingExtras and 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.

2 Likes