Skip to content
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

Ensure order of logged messages, fix a few flaky tests #25365

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

OndroMih
Copy link
Contributor

@OndroMih OndroMih commented Feb 5, 2025

Fixes #25349
Fixes an issue that caused the GlassFishLogHandlerTest.roll test to fail sometimes - the messages produced when rolling log files could be logged in reversed order.

Fixes flaky GlassFishLogManagerLifeCycleTest.reconfigureWithoutResolvingLevelsWithincompleteconfiguration test, which produced log messages in undeterministic order but expected them in order. The fix is similar, but this time in the test, not in production code.

@@ -133,6 +136,7 @@ public void startReconfiguration() throws Exception {
() -> assertEquals(GlassFishLoggingStatus.CONFIGURING, MANAGER.getLoggingStatus()),
() -> assertNull(COLLECTOR.pop(), "COLLECTOR should be empty after reconfiguration started"));
doLog(Level.INFO, "Log after reconfiguration started", 0);
Thread.sleep(10L);
Copy link
Contributor

Choose a reason for hiding this comment

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

In all these tests should not be any sleeps, they make these tests ineffective. Also the line before has 0 sleep time, while the thread started before the sleep (but still could be executed before or after it).
I have to think what kind of error I intended to catch by this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added this sleep to ensure that the logging actually happens before the assertion on the next line. Otherwise the assertion doesn't have any value - it could be asserted before the log happens and then the test passes.

Should I remove the sleep here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Could doLog return something that the code here could check if it's safe to proceed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have no idea. Now it looks to me that @dmatej intended to do the check immediately. It’s supposed to test locking, so maybe all should run as soon as possible. Although it would be good to clarify what the tests intends to verify.

Copy link
Contributor

Choose a reason for hiding this comment

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

Obviously I did something wrong, I just need to remember, document it somehow and fix it.

But I think I know how to resolve it better ... the point is that you cannot write into a file while it is renamed. The idea I implemented in #24980 was that if I have just a single log message, I can log it asynchronously. The problem is that there can be more threads which want to log something and we are a bit out of the control with threads here.

Creating static executor with any thread waiting whole day or month is ugly, but maybe it can be "transactional". When rolling starts create the thread, send logs to its buffer and destroy it when the operation finished (after it consumes the queue). Then you even don't need the executor.

However, the original idea was that log handler will accept log records, it just will not process them while the file manager does roll. So even the idea with threads was bad workaround. Or I missed yet something.... mhm ... (eh, there is yet another situation - startup, which is another stateful machine ... that is related to #25183 , because logging system can be used even also by the garbage collector which ten can break everything, as it is initialized too early).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean the executor I created here in rhe LogFileManager? It creates a thread only when it’s needed and disposes it after 100ms if it’s inactive. The only thing that is kept all the time is the executor itself, with no threads most of the time.

A better approach would be as you suggest - it would be enough to create a single threaded executor in the scope of roll method and use it for all async logging and then shut it down at the end of the roll method.

@pzygielo

This comment was marked as resolved.

@OndroMih OndroMih force-pushed the ondromih-flaky-tests branch from a162bb8 to d0a0c4c Compare February 5, 2025 16:32
@OndroMih

This comment was marked as resolved.

@dmatej dmatej changed the title Fix:#25349 Ensure order of logged messages, fix a few flaky tests Ensure order of logged messages, fix a few flaky tests Feb 5, 2025
@@ -164,10 +168,11 @@ public void roll() throws Exception {
);
handler.publish(new GlassFishLogRecord(Level.SEVERE, "File two, line two", false));
Thread.sleep(MILLIS_FOR_PUMP);
final List<String> fileLines3 = Files.readAllLines(logFile.toPath());
Copy link
Contributor

Choose a reason for hiding this comment

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

If the file doesn't exist, this will cause IOException, so the assertion will not make sense.

() -> assertTrue(handler.getConfiguration().getLogFile().exists(), "file exists"),
() -> assertThat("file content", Files.readAllLines(handler.getConfiguration().getLogFile().toPath()),
() -> assertTrue(logFile.exists(), "file exists"),
() -> assertThat("file content, filename=" + logFile + ", content=" + fileLines2 , fileLines2,
Copy link
Contributor

Choose a reason for hiding this comment

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

Putting whole content to "reason" argument is bit too much ... the assertion would provide quite good explanation, ie:

java.lang.AssertionError: file content
Expected: iterable containing [a string containing "INFO", "Rolling the file ", ".log", "output was originally enabled: true" in order, a string containing "INFO", "Araaachiving file ", ".log", " to ", ".log_" in order, a string containing "SEVERE", "main", "File two, line two" in order]
     but: item 1: was "21:56:32.278209    INFO er-Async-Info-Logger                                                             . Archiving file /tmp/org.glassfish.main.jul.handler.GlassFishLogHandlerTest11276075090100096775.log to /tmp/org.glassfish.main.jul.handler.GlassFishLogHandlerTest11276075090100096775.log_2025-02-05T21-56-32"

but maybe adding the file to the message is a good idea, perhaps directly to assertAll.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Flaky GlassFishLogManagerLifeCycleTest.reconfigureWithoutResolvingLevelsWithincompleteconfiguration
3 participants