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

Log4j2 not working with Spring Boot 3.4.2 together with BlockHound #43963

Open
micopiira opened this issue Jan 25, 2025 · 9 comments
Open

Log4j2 not working with Spring Boot 3.4.2 together with BlockHound #43963

micopiira opened this issue Jan 25, 2025 · 9 comments
Labels
type: regression A regression from a previous release
Milestone

Comments

@micopiira
Copy link

When upgrading to Spring Boot 3.4.2 our logging stopped completely working.

After narrowing down I figured the problem happens with Spring Boot 3.4.2 when using Log4j2 together with BlockHound.

Here is a minimum reproducer repo: https://github.com/micopiira/spring-boot-log4j2-issue

Spring Boot 3.4.1 with exact same Log4j2 version and BlockHound version works.

Spring Boot 3.4.1:

Image

Spring Boot 3.4.2:

Image
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jan 25, 2025
@wilkinsona
Copy link
Member

wilkinsona commented Jan 26, 2025

Thanks for the report and for the minimal sample. I assume that something has changed in Spring Boot 3.4.2 that is causing BlockHound to break Log4j2 in some way. Unfortunately, given that this works fine without BlockHound and the way in which BlockHound works, I don't think there's anything we can do about this in Spring Boot. Please raise a BlockHound issue so that they can investigate further.

@wilkinsona wilkinsona closed this as not planned Won't fix, can't repro, duplicate, stale Jan 26, 2025
@wilkinsona wilkinsona added status: invalid An issue that we don't feel is valid for: external-project For an external project and not something we can fix and removed status: waiting-for-triage An issue we've not yet triaged labels Jan 26, 2025
@wilkinsona wilkinsona reopened this Jan 29, 2025
@wilkinsona wilkinsona added status: waiting-for-feedback We need additional information before we can continue and removed status: invalid An issue that we don't feel is valid for: external-project For an external project and not something we can fix labels Jan 29, 2025
@wilkinsona
Copy link
Member

Re-opening. Thanks to @violetagg's analysis, this has been tracked down to an assumption in StatusConsoleListener#closeNonSystemStream that is faulty when BlockHound is involved. It's only started causing a problem due to #43578.

@nosan
Copy link
Contributor

nosan commented Jan 29, 2025

Thanks for the sample, @micopiira.

StandardOutputIntegration.applyTo(...) replaces the standard OUT and ERR streams with PrintStreamDelegate. During initialization, Log4J2LoggingSystem attempts to reset the StatusLogger.FallbackListener stream (which was previously replaced by BlockHound). This results in PrintStreamDelegate being closed, which in turn delegates the close call to the standard OUT and ERR streams.

One of the options is to revert b6b9237 and fix SampleLog4j2StructuredLoggingApplicationTests.
main...nosan:spring-boot:43963

Meanwhile, you can use this solution reactor/BlockHound#469 (comment)

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jan 29, 2025
@wilkinsona wilkinsona added status: waiting-for-triage An issue we've not yet triaged and removed status: feedback-provided Feedback has been provided labels Jan 29, 2025
@violetagg
Copy link
Member

Thanks for the sample, @micopiira.

StandardOutputIntegration.applyTo(...) replaces the standard OUT and ERR streams with PrintStreamDelegate. During initialization, Log4J2LoggingSystem attempts to reset the StatusLogger.FallbackListener stream (which was previously replaced by BlockHound). This results in PrintStreamDelegate being closed, which in turn delegates the close call to the standard OUT and ERR streams.

@nosan Please check the screenshot below -> it is not the delegator that closes but the real system stream

Image

One of the options is to revert b6b9237 and fix SampleLog4j2StructuredLoggingApplicationTests. main...nosan:spring-boot:43963

Meanwhile, you can use this solution reactor/BlockHound#469 (comment)

@nosan
Copy link
Contributor

nosan commented Jan 29, 2025

@violetagg

Oh, you're right, my mistake.

// stream = original System.out
// System.out = BlockHound.PrintStreamDelegate

    private static void closeNonSystemStream(final OutputStream stream) {
        // Close only non-system streams
        if (stream != System.out && stream != System.err) {
            try {
                stream.close();
            } catch (IOException error) {
                // We are at the lowest level of the system.
                // Hence, there is nothing better we can do but dumping the failure.
                error.printStackTrace(System.err);
            }
        }
    }

so Log42J closes the original stream.

@philwebb philwebb added type: regression A regression from a previous release and removed status: waiting-for-triage An issue we've not yet triaged labels Jan 29, 2025
@philwebb philwebb added this to the 3.4.x milestone Jan 29, 2025
@eichingertim
Copy link

I noticed a similar problem in IntelliJ:

When I upgraded to 3.4.2 and executed a SpringBootTest with OutputCaptureExtension (Log Framework Log4J) the test is marked as "Not started" after some time and produces no log output. However when the tests are run via maven it works fine.

When I downgraded again to 3.4.1 the behavior is back to normal. Can anybody else validate this?

@nosan
Copy link
Contributor

nosan commented Feb 3, 2025

@eichingertim

I've tried the following test with IntelliJ IDEA and 3.4.2:

@SpringBootTest
@ExtendWith(OutputCaptureExtension.class)
class SpringBootLog4j2DemoApplicationTests {

	@Test
	void contextLoads(CapturedOutput output) {
		Assertions.assertThat(output).isNotEmpty();
	}

}

And indeed it does not work for me as well.

Image

This fix main...nosan:spring-boot:gh-43963 resolves both issues.

@eichingertim
Copy link

Thanks for validating ;) Are you able to get this into 3.4.3?

@nosan
Copy link
Contributor

nosan commented Feb 4, 2025

I don't make the decision, but it seems likely that the plan is to fix it in 3.4.3. The solution I proposed is just one option—another option is to revert resetFallbackListenerStream changes. There's a good chance that someone on the team might have a better approach or another idea for handling this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: regression A regression from a previous release
Projects
None yet
Development

No branches or pull requests

7 participants