New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Backport part of #2062 to 2.x
branch.
#2454
base: 2.x
Are you sure you want to change the base?
Conversation
The property source comparator should not merge distinct property sources with the same priority.
I also included a fix for If your prefer to split this fix into a separate PR, I can do it. |
Objects.requireNonNull(right); | ||
final int result = Integer.compare(left.getPriority(), right.getPriority()); | ||
// Two property sources can have the same priority | ||
return result != 0 || left.equals(right) ? result : left.hashCode() - right.hashCode(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with Phillip Webb's proposal in LOG4J2-3618:
use
equals/hashCode
to determine if items can be added, and only use the Comparator for sorting
I am not able to see how this achieves that. I would be in favor of the following instead:
- Leave this comparator as is (only compare using ranks)
- Initialize the
PropertiesUtil.Environment#sources
usingnew ConcurrentSkipListSet()
, i.e., no explicit comparator - Find iterations over
PropertiesUtil.Environment#sources
, and employ the comparator there (i.e.,.stream().sorted(Comparator.INSTANCE).forEach(...)
) iff an order is needed.
@@ -540,18 +552,18 @@ private synchronized void reload() { | |||
final List<CharSequence> tokens = PropertySource.Util.tokenize(key); | |||
final boolean hasTokens = !tokens.isEmpty(); | |||
sources.forEach(source -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we only guard against the particular failure cases reported rather than the entire block? That is, I was expecting:
keys.stream().filter(Objects.nonNull).forEach(key -> {
try {
// Old logic goes here verbatim
} catch (final Exception error) {
// Report the failure
}
});
for (final PropertySource source : sources) {
try {
// Old logic goes here verbatim
} catch (final Exception error) {
// Report the failure
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reporting failures will actually generate bug reports. It is very likely that Log4j will try to load the Spring PropertySource before the Spring environment exists. As I recall that will cause an exception during startup of every Spring Boot application, which obviously is unacceptable.
This backports the part of PR #2062 that concerns spring-projects/spring-boot#33450 to the
2.x
branch.It contains two sets of changes:
PropertiesUtil#removePropertySource
to allow Spring Boot to remove its custom property source, when the SpringEnvironment
becomes unavailable at shutdown.Note that the second change will not be effective until Spring Boot starts using it, which can happen only after a
2.24.0
release of Log4j API.Remark: the part of PR #2062 that concerns #1799 was not backported, since I believe it to be a Spring Boot problem:
o.a.l.l.spi.LoggerContext
,LogManager.getContext
multiple times, but cache theLoggerContext
it received at startup.Fixes #2453