*[Note that the shared `ParallelRunTest` is a self-sufficient code, that
is, one can simply copy-paste it into a Log4j test and run it.]*

When `ExecutionMode.SAME_THREAD` is used, everything works as expected:

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

When `ExecutionMode.CONCURRENT` is used, tests fail due to unexpected
`appenderFileLength`:

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

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.

On Fri, Nov 12, 2021 at 7:49 AM Remko Popma <[email protected]> wrote:

> What do the generated files look like?
> Is the output that is generated in concurrent mode longer or shorter than
> the expected length?
> Also, does it contain one entry (one log message) per line, or is it
> scrambled? Are entries ordered by time?
>
> On Fri, Nov 12, 2021 at 12:34 AM Ralph Goers <[email protected]>
> wrote:
>
> > How does it fail?
> >
> > Ralph
> >
> > > On Nov 11, 2021, at 1:42 AM, Volkan Yazıcı <[email protected]> wrote:
> > >
> > > They sort of do exist, see JsonTemplateLayoutConcurrentEncodeTest
> > > <
> >
> https://github.com/apache/logging-log4j2/blob/release-2.x/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutConcurrentEncodeTest.java#L58
> > >
> > > .
> > > But I can add a dedicated test too.
> > > Nevertheless, I still wonder what the problem is.
> > >
> > > On Wed, Nov 10, 2021 at 9:15 PM Gary Gregory <[email protected]>
> > wrote:
> > >
> > >> Should this test be added to the repo with a TODO comment?
> > >>
> > >> Gary
> > >>
> > >> On Mon, Nov 8, 2021, 07:09 Volkan Yazıcı <[email protected]>
> > wrote:
> > >>
> > >>> Hello! Does anybody have an idea why the following test fails for
> > >>> CONCURRENT execution mode, whereas it works for SAME_THREAD?
> > >>>
> > >>> import org.apache.logging.log4j.Level;
> > >>> import org.apache.logging.log4j.Logger;
> > >>> import org.apache.logging.log4j.core.LoggerContext;
> > >>> import org.apache.logging.log4j.core.config.Configuration;
> > >>> import org.apache.logging.log4j.core.config.Configurator;
> > >>> import
> > >>>
> org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
> > >>> import
> > >>>
> > >>
> >
> org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
> > >>> import org.apache.logging.log4j.util.Strings;
> > >>> import org.junit.jupiter.api.parallel.Execution;
> > >>> import org.junit.jupiter.api.parallel.ExecutionMode;
> > >>> import org.junit.jupiter.params.ParameterizedTest;
> > >>> import org.junit.jupiter.params.provider.ValueSource;
> > >>>
> > >>> import java.io.File;
> > >>> import java.nio.file.Paths;
> > >>>
> > >>> import static org.assertj.core.api.Assertions.assertThat;
> > >>>
> > >>> @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);
> > >>>
> > >>>    }
> > >>>
> > >>> }
> > >>>
> > >>
> >
> >
> >
>

Reply via email to