Skip to content

Commit

Permalink
Merge branch '3.0.x' into 3.1.x
Browse files Browse the repository at this point in the history
Closes gh-37484
  • Loading branch information
wilkinsona committed Sep 20, 2023
2 parents b2dc52f + 2a3d5c4 commit e10ca23
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import org.slf4j.bridge.SLF4JBridgeHandler;
import org.slf4j.helpers.SubstituteLoggerFactory;

import org.springframework.aot.AotDetector;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution;
Expand Down Expand Up @@ -384,7 +385,7 @@ private ch.qos.logback.classic.Logger getLogger(String name) {
}

private LoggerContext getLoggerContext() {
ILoggerFactory factory = LoggerFactory.getILoggerFactory();
ILoggerFactory factory = getLoggerFactory();
Assert.isInstanceOf(LoggerContext.class, factory,
() -> String.format(
"LoggerFactory is not a Logback LoggerContext but Logback is on "
Expand All @@ -396,6 +397,21 @@ private LoggerContext getLoggerContext() {
return (LoggerContext) factory;
}

private ILoggerFactory getLoggerFactory() {
ILoggerFactory factory = LoggerFactory.getILoggerFactory();
while (factory instanceof SubstituteLoggerFactory) {
try {
Thread.sleep(50);
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
throw new IllegalStateException("Interrupted while waiting for non-subtitute logger factory", ex);
}
factory = LoggerFactory.getILoggerFactory();
}
return factory;
}

private Object getLocation(ILoggerFactory factory) {
try {
ProtectionDomain protectionDomain = factory.getClass().getProtectionDomain();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.boot.logging.logback;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import ch.qos.logback.classic.LoggerContext;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.slf4j.LoggerFactory;

import org.springframework.boot.logging.LoggingSystem;
import org.springframework.boot.testsupport.classpath.ForkedClassPath;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Tests for parallel initialization of {@link LogbackLoggingSystem} that are separate
* from {@link LogbackLoggingSystemTests}. This isolation allows them to have complete
* control over how and when the logging system is initialized.
*
* @author Andy Wilkinson
*/
class LogbackLoggingSystemParallelInitializationTests {

private final LoggingSystem loggingSystem = LoggingSystem
.get(LogbackLoggingSystemParallelInitializationTests.class.getClassLoader());

@AfterEach
void cleanUp() {
this.loggingSystem.cleanUp();
((LoggerContext) LoggerFactory.getILoggerFactory()).stop();
}

@Test
@ForkedClassPath
void noExceptionsAreThrownWhenBeforeInitializeIsCalledInParallel() {
List<Thread> threads = new ArrayList<>();
List<Throwable> exceptions = new CopyOnWriteArrayList<>();
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(() -> this.loggingSystem.beforeInitialize());
thread.setUncaughtExceptionHandler((t, ex) -> exceptions.add(ex));
threads.add(thread);
}
threads.forEach(Thread::start);
threads.forEach(this::join);
assertThat(exceptions).isEmpty();
}

private void join(Thread thread) {
try {
thread.join();
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
throw new RuntimeException(ex);
}
}

}
1 change: 1 addition & 0 deletions src/checkstyle/checkstyle-suppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<suppress files="LogbackInitializer\.java" checks="IllegalImport" />
<suppress files="LogbackLoggingSystem\.java" checks="IllegalImport" />
<suppress files="LogbackLoggingSystemTests\.java" checks="IllegalImport" />
<suppress files="LogbackLoggingSystemParallelInitializationTests\.java" checks="IllegalImport" />
<suppress files="LogbackConfigurationAotContributionTests\.java" checks="IllegalImport" />
<suppress files="MetricsAutoConfigurationMeterRegistryPostProcessorIntegrationTests\.java" checks="IllegalImport" message="LoggerFactory"/>
<suppress files="SpringApplicationTests\.java" checks="FinalClass" />
Expand Down

0 comments on commit e10ca23

Please sign in to comment.