Skip to content

Remove Memento and add support for Logging.jl - #99

Merged
odow merged 2 commits into
masterfrom
od/logging
Apr 23, 2026
Merged

odow merged 2 commits into
masterfrom
od/logging

Conversation

@odow

@odow odow commented Apr 14, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #98

This PR removes Memento in favour of the Logging.jl standard library. The API for silence! and logger_config! are unchanged.

There is a new file src/core/logging.jl which contains the logic for logging.

Throughout the rest of the package, the changes are:

  • Memento.error(_LOGGER, becomes @_error(
  • Memento.warn(_LOGGER, becomes @_warn(
  • Memento.info(_LOGGER, becomes @_info(
  • Memento.debug(_LOGGER, becomes @_debug(

The benefit of this approach is that it is self-contained and backward compatible within a package. It doesn't require the entire InfrastructureModels ecosystem to move as one from Memento to Logging.jl.

We looked into other ways of writing the logger, #98, lanl-ansi/PowerModels.jl#997 before ultimately deciding on this approach.

We also investigated updating Memento, but it commits type-piracy on this macro: https://github.com/invenia/Memento.jl/blob/58a92c6d688a5372e04c3d05c6da7a0cf3430a94/src/memento_test.jl#L119

We'd likely need to remove it, or rename it to something like @memento_test_throws. This would be a breaking change that we'd need to update every InfrastructureModels package for any way, so we might as well bite the bullet and remove it as a dependency. This should save us from any future issues in the long term.

PowerModelsDistribution

Our approach is different to PMD:

https://github.com/lanl-ansi/PowerModelsDistribution.jl/blob/main/src/core/logging.jl

They muck with the global logger, which would affect all packages using logging. As a single package it's okay. And it doesn't conflict with the approach taken in this PR. But the logic is not correct if multiple packages adopted the logging style of PowerModelsDistribution. Here's an example of where things can go wrong: lanl-ansi/PowerModels.jl#997 (comment) (Changing the logger mutates global state; multiple packages modifying the same global state can get into issues.)

Other PRs

@odow
odow requested a review from ccoffrin April 14, 2026 00:40
@codecov

codecov Bot commented Apr 14, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 57.81250% with 27 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.40%. Comparing base (d9f0a05) to head (34ca985).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/core/data.jl 12.50% 14 Missing ⚠️
src/io/matlab.jl 37.50% 5 Missing ⚠️
src/core/base.jl 72.72% 3 Missing ⚠️
src/core/solution.jl 0.00% 3 Missing ⚠️
src/core/logging.jl 95.45% 1 Missing ⚠️
src/io/common.jl 0.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #99      +/-   ##
==========================================
+ Coverage   90.31%   90.40%   +0.08%     
==========================================
  Files          10       11       +1     
  Lines         940      959      +19     
==========================================
+ Hits          849      867      +18     
- Misses         91       92       +1     
Files with missing lines Coverage Δ
src/InfrastructureModels.jl 100.00% <100.00%> (ø)
src/core/logging.jl 95.45% <95.45%> (ø)
src/io/common.jl 93.75% <0.00%> (ø)
src/core/base.jl 97.17% <72.72%> (ø)
src/core/solution.jl 71.71% <0.00%> (ø)
src/io/matlab.jl 96.35% <37.50%> (ø)
src/core/data.jl 89.75% <12.50%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d9f0a05...34ca985. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread src/core/logging.jl
@@ -0,0 +1,56 @@
const _LOGGER = Ref{Logging.ConsoleLogger}()

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the main file for the logging.

The _LOGGER is a const but it is a Ref because Logging.ConsoleLogger is immutable; we want to be able to change the logging level at runtime.

Comment thread src/core/logging.jl
silence() = logger_config!("error")

function _meta_formatter(level::Logging.LogLevel, _module, args...)
return Logging.default_logcolor(level), "$(_module) | $level]:", ""

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is where we can change how the log messages are formatted. For now, it just prefaces the log message with something like [InfrastructureModels | Warn]: msg. (Note that the opening [ is added automatically by Logging.jl.)

In future we could add more information like file and line number. Or we could standardise this function into InfrastructureModels.meta_formatter so that other InfrastructureModels packages could all use the same formatting. For now, we're just copying this function into each package.

Comment thread src/core/logging.jl

function logger_config!(level::Logging.LogLevel)
_LOGGER[] =
Logging.ConsoleLogger(stdout, level; meta_formatter = _meta_formatter)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function updates the global _LOGGER.

Comment thread src/core/logging.jl
`"warn"`, `"info"`, or `"debug"`.
"""
function logger_config!(level::String)
return getfield(Logging, level |> titlecase |> Symbol) |> logger_config!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit messy. The other option is a big if level == "error" ... end.

If you miss-type, you get this error:

julia> getfield(Logging, "err" |> titlecase |> Symbol)
ERROR: UndefVarError: `Err` not defined in `Logging`
Suggestion: check for spelling errors or missing imports.

Comment thread src/core/logging.jl

function _log_if_level(f, level, logger = _LOGGER[])
if level >= Logging.min_enabled_level(logger)
Logging.with_logger(f, logger)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The if level >= ... check is a cheap check to see if the logger should run. If we shouldn't log this message, then we can skip with_logger entirely (it has some overhead and allocations).

Comment thread src/core/logging.jl
macro _error(msg)
return quote
$_log_if_level(() -> @error($msg), $(Logging.Error))
error($msg)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that @error doesn't throw. But Memento.error did. To preserve backwards compatibility we add an explicit error(msg) here.

function logger_config!(level; kwargs...)
Memento.config!(_LOGGER, level, kwargs...)
function __init__()
logger_config!("info")

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as Memento.register, we need to enable the logger on __init__.

@odow
odow merged commit d54b34e into master Apr 23, 2026
11 of 12 checks passed
matteorossini added a commit to Electa-Git/PowerModelsACDC.jl that referenced this pull request Jun 3, 2026
- Use the same approach as in InfrastructureModels: <lanl-ansi/InfrastructureModels.jl#99>.
- Lower the compatibility requirement for Logging to 1.10 to support Julia LTS.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant