Volkan Yazici created LOG4J2-3188:
-------------------------------------
Summary: Concurrent individual LoggerContext initializations cause
severe LogEvent drop or incorrect delivery
Key: LOG4J2-3188
URL: https://issues.apache.org/jira/browse/LOG4J2-3188
Project: Log4j 2
Issue Type: Bug
Components: Core
Reporter: Volkan Yazici
When multiple {{LoggerContext}}s get initialized concurrently, they affect each
other causing severe {{LogEvent}} drop and incorrect delivery. Consider the
following test:
{code:java}
@Execution(ExecutionMode.SAME_THREAD)
class ParallelRunTest {
@ParameterizedTest
@ValueSource(chars = {'A', 'B', 'C', 'D'})
void test(final char letter) {
// Create the configuration builder.
final ConfigurationBuilder<?> configBuilder =
ConfigurationBuilderFactory
.newConfigurationBuilder()
.setStatusLevel(Level.ERROR)
.setConfigurationName("Letter-" + letter);
// Create the configuration.
final String appenderName = "File";
final String appenderFilepath = Paths
.get(
System.getProperty("java.io.tmpdir"),
"ParallelRunTest-" + letter + ".log")
.toAbsolutePath()
.toString();
final Configuration config = configBuilder
.add(configBuilder
.newAppender(appenderName, "File")
.addAttribute("fileName", appenderFilepath)
.addAttribute("append", false)
.addAttribute("immediateFlush", false)
.addAttribute("ignoreExceptions", false)
.add(configBuilder
.newLayout("PatternLayout")
.addAttribute("pattern", "%m\n")))
.add(configBuilder
.newRootLogger(Level.ALL)
.add(configBuilder.newAppenderRef(appenderName)))
.build(false);
// Initialize the configuration.
try (final LoggerContext loggerContext =
Configurator.initialize(config)) {
final Logger logger =
loggerContext.getLogger(ParallelRunTest.class);
// Write logs.
final String message = Strings.repeat(String.valueOf(letter), 999);
for (int i = 0; i < 1_000; i++) {
logger.info(message);
}
}
// Verify the file content.
final long appenderFileLength = new File(appenderFilepath).length();
assertThat(appenderFileLength).isEqualTo(1_000_000L);
}
}
{code}
Above test, given a {{letter}}, creates a {{ParallelRunTest-<letter>.log}}
file, and writes 999 times that letter to each line (ending with a line-feed
character) for 1,000 lines. The eventual file is expected to be of size
{{lineLength * lineCount = 1,000 * 1,000 = 1e6}}. These assumptions indeed hold
after a run:
{code}
wc -l /tmp/ParallelRunTest-*
1000 /tmp/ParallelRunTest-A.log
1000 /tmp/ParallelRunTest-B.log
1000 /tmp/ParallelRunTest-C.log
1000 /tmp/ParallelRunTest-D.log
4000 total
for log_file in /tmp/ParallelRunTest-*; do
echo "file: $log_file"
echo "line lengths:"
awk "{print length}" $log_file | sort | uniq
echo "distinct lines:"
sort $log_file | uniq
echo
done
file: /tmp/ParallelRunTest-A.log
line lengths:
999
distinct lines:
AAA...A
file: /tmp/ParallelRunTest-B.log
line lengths:
999
distinct lines:
BBB...B
file: /tmp/ParallelRunTest-C.log
line lengths:
999
distinct lines:
CCC...C
file: /tmp/ParallelRunTest-D.log
line lengths:
999
distinct lines:
DDD...D
{code}
Though when {{ExecutionMode.SAME_THREAD}} is replaced with
{{ExecutionMode.CONCURRENT}} tests fail due to unexpected
{{appenderFileLength}}:
{code}
wc -l /tmp/ParallelRunTest-*
96 /tmp/ParallelRunTest-A.log
1 /tmp/ParallelRunTest-B.log
96 /tmp/ParallelRunTest-C.log
3577 /tmp/ParallelRunTest-D.log
3770 total
for log_file in /tmp/ParallelRunTest-*; do
echo "file: $log_file"
echo "line lengths:"
awk "{print length}" $log_file | sort | uniq
echo "distinct lines:"
sort $log_file | uniq
echo
done
file: /tmp/ParallelRunTest-A.log
line lengths:
999
distinct lines:
AAA...A
BBB...B
CCC...C
file: /tmp/ParallelRunTest-B.log
line lengths:
999
distinct lines:
BBB...B
file: /tmp/ParallelRunTest-C.log
line lengths:
999
distinct lines:
BBB...B
CCC...C
file: /tmp/ParallelRunTest-D.log
line lengths:
999
distinct lines:
AAA...A
BBB...B
CCC...C
DDD...D
{code}
Note that {{AAA...A}}, {{BBB...B}}, etc. snippets shared above are truncated
for display purposes, otherwise each line has 999 _unscrambled_ characters.
Given 1) the total number of logged lines is less than 4000, 2) letters are
scattered between files, and 3) lines are not scrambled, I have the feeling
that produced {{LogEvent}}s either got lost or sent to wrong appenders.
--
This message was sent by Atlassian Jira
(v8.20.1#820001)