Skip to content

Respect the logger-name hierarchy boundary in Configurator.setAllLevels and putIfAbsent results in AbstractConfiguration - #4419

Open
sharanggupta wants to merge 6 commits into
apache:2.xfrom
sharanggupta:gh-configurator-setalllevels-boundary
Open

sharanggupta wants to merge 6 commits into
apache:2.xfrom
sharanggupta:gh-configurator-setalllevels-boundary

Conversation

@sharanggupta

@sharanggupta sharanggupta commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #4418.
Fixes #3155.

Two independent log4j-core fixes, in one PR as asked on #3155. The first two commits are the #4418 fix (unchanged since the review round), the third commit is the #3155 fix (previously #4423, closed).

Configurator.setAllLevels (#4418)

Configurator.setAllLevels(parentLogger, level) selected the child LoggerConfigs with a plain startsWith, so setAllLevels("com.foo", TRACE) also re-leveled com.foobar and com.foobar.child. This adds the same hierarchy-boundary check that #4414 introduced for LoggerNameLevelRewritePolicy (the parent itself, or names continuing with .; the root logger "" and a trailing-dot parent still cover everything below them), LoggerTest cases that pin each boundary check (a sibling logger keeps its level; root and trailing-dot parents still reach their descendants), and a changelog entry.

main (3.x) carries the identical lines in Configurator.setAllLevels; happy to forward-port once this is merged.

AbstractConfiguration logger mutators (#3155)

AbstractConfiguration.addLoggerAppender, addLoggerFilter and setLoggerAdditive (the implementation behind core.Logger#addAppender, #addFilter and #setAdditive) ignored the result of their putIfAbsent calls:

  • addLoggerAppender: when a different appender instance was already registered under the same name, the new instance was not registered but was still attached to the LoggerConfig, so the logger wrote to an appender the configuration never started or stopped while getAppender(name) returned another one. The registered instance is now attached instead (first wins, as addAppender already behaves), with a status-logger warning.
  • All three: the result of loggerConfigs.putIfAbsent(loggerName, nlc) is respected; when a config already exists the change is applied to it instead of re-wiring the parents and updating the loggers again. Under the method lock and the exact-name lookup that precedes it this branch is defensive, so it has no test of its own.
  • addLoggerFilter and setLoggerAdditive now ignore null arguments like addLoggerAppender does, instead of throwing NullPointerException (side note 1 in the issue).

Tests, one per method in AbstractConfigurationTest: the duplicate-name appender case; the filter case (null arguments ignored, exactly one LoggerConfig created with the right parent, both filters applied); the additive case (null logger ignored, one config created, additivity reflected by the logger). All three fail before the change and pass after. Changelog entry for 2.x included.

Checklist

  • Based on 2.x
  • ./mvnw verify on log4j-core / log4j-core-test with LoggerTest and AbstractConfigurationTest succeeds (spotless clean)
  • Changelog entries in src/changelog/.2.x.x, one per issue
  • Tests are provided

Configurator.setAllLevels(parentLogger, level) selected the child
LoggerConfigs with a plain startsWith, so setAllLevels("com.foo", TRACE)
also re-leveled the unrelated sibling loggers com.foobar and
com.foobar.child. Apply the same hierarchy-boundary check that
LoggerNameLevelRewritePolicy got in apache#4414: the parent itself, or names
that continue with a dot; the root logger and a trailing-dot parent
still cover everything below them.

Adds a LoggerTest case with a sibling logger that keeps its level, and
a changelog entry.

Signed-off-by: Sharang Gupta <sharang@sharanggupta.dev>
Comment thread src/changelog/.2.x.x/4418_Configurator-setAllLevels-boundary.xml Outdated
@ramanathan1504

Copy link
Copy Markdown
Contributor

The boundary check matches #4414, and the sibling case fails without the fix.
Removing charAt(...) == '.', isEmpty() or endsWith(".") from Configurator.isChildLogger keeps every test green. Can the test give LoggerTest.child its own level and cover the root and trailing-dot parents, as in the inline suggestions?

Give the child logger its own level in setAllLevelsDoesNotChangeSiblingLoggers,
add a test for the root and trailing-dot parents, and shorten the changelog entry.
Removing any one of the three checks now fails a test.
…on logger mutators

addLoggerAppender attached an appender instance that was not registered
when another appender with the same name already was, so the logger wrote
to an instance the configuration never started or stopped. Attach the
registered instance instead, respect the result of the loggerConfigs
putIfAbsent in all three methods, and ignore null arguments in
addLoggerFilter and setLoggerAdditive like addLoggerAppender does.

Closes apache#3155
@sharanggupta sharanggupta changed the title Respect logger-name hierarchy boundary in Configurator.setAllLevels Respect the logger-name hierarchy boundary in Configurator.setAllLevels and putIfAbsent results in AbstractConfiguration Oct 25, 2026
@sharanggupta

Copy link
Copy Markdown
Contributor Author

As asked on #3155, this PR now also carries the AbstractConfiguration fix for that issue as a separate second commit (941a6a7, previously #4423, now closed). Description updated to cover both issues; the two commits stay independent.

setParents();
logger.getContext().updateLoggers();
} else {
existing.addAppender(effective, null, null);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This branch and the existing.addFilter(filter) and existing.setAdditive(additive) branches below have no test. Removing any of them keeps every test green. A LoggerConfig added with addLogger under a key that differs from its name reaches them, for example:

final LoggerConfig other = new LoggerConfig("other", Level.INFO, true);
config.addLogger("mismatch", other);
config.addLoggerFilter(context.getLogger("mismatch"), filter);
assertThat(other.hasFilter()).isTrue();

type="fixed">
<issue id="3155" link="https://github.com/apache/logging-log4j2/issues/3155"/>
<description format="asciidoc">
Fix `addLoggerAppender()` attaching an unregistered appender when its name is already registered, and `addLoggerFilter()`/`setLoggerAdditive()` failing on `null` arguments.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can the entry be one short line with what the user sees?

Suggested change
Fix `addLoggerAppender()` attaching an unregistered appender when its name is already registered, and `addLoggerFilter()`/`setLoggerAdditive()` failing on `null` arguments.
Fix `Logger.addAppender()` attaching an unregistered appender.

@ramanathan1504

Copy link
Copy Markdown
Contributor

The setAllLevels tests now fail for each removed condition, and each new AbstractConfigurationTest case fails without its fix.
The three existing branches in AbstractConfiguration stay green when removed, and a LoggerConfig added with addLogger under a different key reaches them. Can each get a test, and can the #3155 changelog be one short line?

A LoggerConfig added under a key that differs from its name reaches the
putIfAbsent branches of addLoggerAppender, addLoggerFilter and
setLoggerAdditive, which no test covered.
Each putIfAbsent branch of addLoggerAppender, addLoggerFilter and
setLoggerAdditive now fails exactly one test when removed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

2 participants