How to save Logging output to a log file?

Hi!

I would like to save the output of Julia 0.7 Logging macros @warn, @error, @debug and @info into a log file. How can I do that?

Thanks in advance,

using Logging

logger = SimpleLogger(open("log1.txt", "w+"))

with_logger(logger) do
    @info(" here is some context specific logging")
end

global_logger(logger)

@info("All logs will use the global logger by default.")

see here.

The docs could definitely use some improvement in this area, by the way. Took me a little while the first time I figured out the above.

7 Likes

Also a highly desirable default that seems to be missing is something like MultiLogger which spits out logs in multiple places. Right now it looks like you’d have to implement your own, which is unfortunate since this is probably one of the most common use cases (at least to stdout and a file).

If anyone figures out a really simple way to do this, please let me know.

6 Likes

That stuff seems really useful, but doesn’t write anything to the file on Julia v0.7.0 on my Mac though. Am I the only one with that issue?

Version 0.7.0 (2018-08-08 06:46 UTC) Official http://julialang.org/ release x86_64-apple-darwin14.5.0

Please, do everyone a favour and try to improve the documentation. This is something most of us need at some point.

1 Like

Just as a complement to @ExpandingMan’s example; you need to flush or close before anything is printed to file, example:

julia> using Logging

julia> io = open("log.txt", "w+");

julia> logger = SimpleLogger(io);

julia> with_logger(logger) do
           @info(" here is some context specific logging")
       end

shell> cat log.txt

julia> flush(io);

shell> cat log.txt
┌ Info:  here is some context specific logging
└ @ Main REPL[7]:2

julia> global_logger(logger);

julia> @info("All logs will use the global logger by default.");

shell> cat log.txt
┌ Info:  here is some context specific logging
└ @ Main REPL[7]:2

julia> close(io);

shell> cat log.txt
┌ Info:  here is some context specific logging
└ @ Main REPL[7]:2
┌ Info: All logs will use the global logger by default.
└ @ Main REPL[12]:1
5 Likes

Thanks @ExpandingMan and @fredrikekre! That works perfectly. I tested it using Ubuntu and Julia 1.0

I was thinking that maybe the logging macros should call flush any time they are invoked. Is that sensible?
It will be sad to lose log messages if the program ends abruptly before it reaches the close, or to write a big program inside an enormous with_logger clause.

1 Like

Not really. That might make sense for files, but not other IO types.

The real problem here is that there are a handful of default loggers that really should be in Logging that aren’t. For example, a FileLogger would make sense (to make sure flush is always called), multi-logger, perhaps a few others. It should be easy enough to define these on your own but they should definitely be included by default.

Since nobody who developed Logging has chimed in on this yet, perhaps it would be appropriate to open an issue in the julia repo asking for more default loggers.

3 Likes

I’m currently in the process of developing a package providing (at first) a simple FileLogger and a general IOLogger, with a File/IO distinction on a LogLevel-basis. I’d be willing to provide the code to base once I’m done with a basic functioning core, but from what I’ve seen in the issues/files, the Logging interface seems to be not 100% finished, so maybe it being a package for now is best.

I still have to write tests, some documentation and fix bugs shown by testing, so it’ll be a while until it’s done.

2 Likes

@Sukera, do you have a repository for IOLogging.jl? Leaving flushing up to the user is key to speed.

Not publicy available yet, probably sometime next week.

Only the files created by the FileLogger are automatically flushed after writing to them, since you theoretically want to read from them as soon as possible. General IOLogging is not flushed, since those are not generally flushable. There’s always the option to just give file IO to an IOLogger and do the flushing manually - the FileLogger is just for convenience and closing guarantees.

Thanks, Sukera. I’d open an issue on the repo if it was available now. I’m looking forward to probably implementing IOLogging in my own code. There’s a custom logger for monitoring of multiple sockets / processes in JuliaWeb/WebSockets.jl. It’s there for historical reasons and was never quite up to Base standard. The ‘origin’ of a logging line is inelegantly dealt with without using macros.

If you are looking at what may be desirable of a logging API for building networked applications, the version for Julia 0.6 may possibly be of help as a use case. It does deal with colorful output where possible, truncating, timestamps, ‘origin’ of the logging line in case of shared output, and readable header pairs, while avoiding type piracy on the show methods. There’s also a PR under work for 0.7.