Search code examples
loggingjuliatraceback

How to log `catch_backtrace` to a file


I’d like to catch any errors and log the error message with full traceback to a log file for me to review. My implementation is based on this stack question, currently I get the desired result in my STDOUT, but the log file traceback contains lots of Ptr{Nothing} @0x0000000121cc6b5e which isn’t helpful . Below is a minimal example:

using LoggingExtras, Logging
global_logger(FileLogger("log_file.log"))
# few functions so we get traceback
function bar(b)
    error("Failed with b:$b")
end
function foo(a)
    bar(a)
end
function run(c)
    foo(c)
end
try
    run(2)
catch e
    @error "failure" exception = (e, catch_backtrace())
end

gives a meaningful message in the STDOUT

┌ Error: failure
│   exception =
│    Failed with b:2
│    Stacktrace:
│     [1] error(s::String)
│       @ Base ./error.jl:33
│     [2] bar(b::Int64)
│       @ Main /private/tmp/log_problem/ex.jl:6
│     [3] foo(a::Int64)
│       @ Main /private/tmp/log_problem/ex.jl:10
│     [4] run(c::Int64)
│       @ Main /private/tmp/log_problem/ex.jl:14
│     [5] top-level scope
│       @ /private/tmp/log_problem/ex.jl:17
│     [6] include(mod::Module, _path::String)
│       @ Base ./Base.jl:418
│     [7] exec_options(opts::Base.JLOptions)
│       @ Base ./client.jl:292
│     [8] _start()
│       @ Base ./client.jl:495
└ @ Main /private/tmp/log_problem/ex.jl:19

But in log_file.log I get

┌ Error: failure
│   exception = (ErrorException("Failed with b:2"), Union{Ptr{Nothing}, Base.InterpreterIP}[Ptr{Nothing} @0x0000000121cc6b5e, Ptr{Nothing} @0x000000010a7ed743, Ptr{Nothing} @0x000000010a7ed7af, Ptr{Nothing} @0x000000010a7ed80f, Ptr{Nothing} @0x000000010a7ed835, Ptr{Nothing} @0x000000010896b4a0, Ptr{Nothing} @0x00000001089848df, Ptr{Nothing} @0x0000000108982e26, Ptr{Nothing} @0x000000010898306a, Ptr{Nothing} @0x000000010898341c, Base.InterpreterIP in top-level CodeInfo for Main at statement 1, Ptr{Nothing} @0x000000010899e49f, Ptr{Nothing} @0x000000010899e242, Ptr{Nothing} @0x000000010899f515, Ptr{Nothing} @0x00000001220732fa, Ptr{Nothing} @0x000000010896b4a0, Ptr{Nothing} @0x00000001221b85f5, Ptr{Nothing} @0x0000000121d75a85, Ptr{Nothing} @0x000000010896b4a0, Ptr{Nothing} @0x0000000121e39314, Ptr{Nothing} @0x0000000121683dff, Ptr{Nothing} @0x0000000121683f68, Ptr{Nothing} @0x000000010896b4a0, Ptr{Nothing} @0x00000001089c1d32, Ptr{Nothing} @0x00000001089c1c23])
└ @ Main /private/tmp/log_problem/ex.jl:19

How can I get the log file to contain the same information as the stdout?


Solution

  • The FileLogger uses a SimpleLogger internally, which, as the name suggests, is a simple logger without any formatting. You could instead use a FormatLogger to format exceptions the way you like it.

    If you want the same formatting as in the Julia REPL you can use the same logger, which is the ConsoleLogger, but then you need to handle the opening of the file yourself and pass the open writeable IO to the constructor.