Configuring Logging in Applications?

Configuring Logging in Applications?

So we've provided examples of many different ways that Memento.jl can be extended, but what are some common examples for configuring Memento out of the box, without extending any components.

Logging to a File

I want all my log messages coming from MyPkg to be saved to a local file. Easy, just add a DefaultHandler with the desired filename to the specific child logger.

push!(getlogger("MyPkg"), DefaultHandler("noisy.log"))

If you want trace and debug level logging as well then just set the level on that logger.

setlevel!(getlogger("MyPkg"), "trace")

This will send trace messages to all handlers attached to the MyPkg logger, but these want be emitted from the root logger where the default level is info.

Silence Loggers

Have some noisy dependencies that you'd like to silence? Maybe the package owner needs to make some info messages debug only? Until that's fixed you can always silence info logs from the package in you application.

setlevel!(getlogger("NoisyPkg"), "notice")

All trace, debug and info messages from NoisyPkg and submodules will no longer propagate to the root logger and emit logs to the console.

Selective Debugging

Found a bug and need to enable selective debug logging around where the error occurs? There are two ways you can do this in Memento. The simplest option is to call setlevel! for all loggers along the desired path.

setlevel!.(Memento.getpath(getlogger("MyPkg")), "debug")

In this example, Logger(root) and Logger(MyPkg) are now set to debug, and debugging messages will propagate along that path to the root default handler.

Pros:

Cons:

Alternatively, if you want only debug level messages for a specific logger and you don't want any extra logs from the parents then you'll need to modify that logger's level and add a custom handler.

mypkg_logger = getlogger("MyPkg")
setlevel!(mypkg_logger, "debug")
handler = DefaultHandler(
    stdout,
    DefaultFormatter("[{date} | {level} | {name}]: {msg}")
)
push!(mypkg_logger, handler)

This will log all debug or higher messages to this new custom handler.

NOTE: This may result in duplicate logs as the custom handler will emit info, notice, warn, etc logs, but those will also propagate up to the root logger. To avoid this you may wish to add a custom filter to your custom handler to only log debug messages.

push!(handler, Memento.Filter(r -> getlevel(r) == "debug"))

Pros:

Cons:

Integration with Base Julia Logging

Want to use Memento's logger hierarchy, formatter, filters or handlers with the base logging macros (e.g., @info, @warn)? You just need to pass substitute=true to Memento.config! and Memento will start intercepting any logs generated by those macros.

Memento.config!("info"; fmt="[{date} | {level} | {name}]: {msg}", substitute=true)
@info("Hello World!")