LoggingExtras.jl - How to add custom log macro

@debug, @info, @warn, @error are by default, I would like to add log macro, f.e. @fatal. How can I do it with LoggingExtras.jl? @fredrikekre Thank you

I only tried following code (did not work for LoggingExtras.jl):

macro fatal(exprs...)
    quote
       @logmsg LogLevel(100) $(map(x -> esc(x), exprs)...)
   end
end
@fatal "My custom"

Perhaps just use what @info etc do: julia/logging.jl at 468b1571b3676528feb1e44fd497b3bb9b55ef42 Β· JuliaLang/julia Β· GitHub

1 Like

@fredrikekre Thank you for you advice, but I already tried it. It didn’t worked.

Following code doesn’t work:

macro  fatal(exs...)
    logmsg_code((@_sourceinfo)..., :Fatal,  exs...)
end

Output was:

UndefVarError: @_sourceinfo not defined

How should I implement it?

I haven’t really looked at the issue, but I believe error is thrown since @_sourceinfo is not exported.

macro  fatal(exs...)
    logmsg_code((Base.CoreLogging.@_sourceinfo)..., :Fatal,  exs...)
end

@LinasBa Thank you so much, now I’m closer to the goal:

using Logging, LoggingExtras

macro fatal(exs...)
    Base.CoreLogging.logmsg_code((Base.CoreLogging.@_sourceinfo)..., :Info,  exs...)
end

@fatal "My message"

Output:

UndefVarError: Info not defined

Any ideas?

You should probably provide module name for :Info as well.

Base.CoreLogging.:Info

But this gets new error thrown.

1 Like

This was much more complicated than I thought, but this seems to work correctly with all escaping and location information

function maybe_make_kwargs(ex)
    if ex isa Expr && ex.head === :(=) ||
       ex isa Expr && ex.head === :...
        return ex
    else
        Expr(:(=), ex, esc(ex))
    end
end

macro fatal(exs...)
    location = LineNumberNode(__source__.line, __source__.file)
    level = Base.CoreLogging.LogLevel(1001)
    message = esc(exs[1])
    kwargs = map(maybe_make_kwargs, exs[2:end])
    Expr(:macrocall, Base.CoreLogging.var"@logmsg", location, level, message, kwargs...)
end

Testing:

julia> x = 123;

julia> @fatal "hello" x y = 456
β”Œ LogLevel(1001): hello
β”‚   x = 123
β”‚   y = 456
β”” @ Main REPL[4]:1

julia> function f()
           x = 678
           @fatal "hello from f" x y = 321
       end;

julia> f()
β”Œ LogLevel(1001): hello from f
β”‚   x = 678
β”‚   y = 321
β”” @ Main REPL[5]:3

julia> module A
           import ..Main: @fatal
           a = 111
           g() = @fatal "hello from module A $a" a y = 444
       end;

julia> A.g()
β”Œ LogLevel(1001): hello from module A 111
β”‚   a = 111
β”‚   y = 444
β”” @ Main.A REPL[7]:4
1 Like

Thank you very much. It is working. I would like to add small question. Is it possible to change macro name in console output? LogLevel(1001) β†’ Fatal

Current:

β”Œ LogLevel(1001): hello from f
β”‚   x = 678
β”‚   y = 321
β”” @ Main REPL[5]:3

Desired:

β”Œ Fatal: hello from f
β”‚   x = 678
β”‚   y = 321
β”” @ Main REPL[5]:3

See JuliaLang/julia#33418. Currently you have to do that yourself in a FormatLogger or similar:

julia> using LoggingExtras, Logging

julia> logger = FormatLogger(stderr) do io, args
           levelstr = args.level == Logging.LogLevel(100) ? "Fatal" : string(args.level)
           println(io, levelstr, ": ", args.message)
       end;

julia> global_logger(logger);

julia> @logmsg LogLevel(100) "hello"
Fatal: hello
1 Like