Skip to content

T-1365 Keep the appender running while the JVM shuts down - #34

Merged
PetrHeinz merged 2 commits into
mainfrom
claude/shutdown-hook-flush-only
Sep 29, 2026
Merged

PetrHeinz merged 2 commits into
mainfrom
claude/shutdown-hook-flush-only

Conversation

@PetrHeinz

Copy link
Copy Markdown
Member

The JVM shutdown hook added in #31 calls stop() as soon as the JVM starts shutting down. The JVM runs all shutdown hooks at the same time, so anything the application logs after that moment is rejected by logback ("Attempted to append to non started appender [Logtail]", only visible with a status listener). Frameworks log a lot at exactly that point and stop logback themselves only at the very end: Spring Boot's logging shutdown handler and the Quarkus logback extension's last shutdown task both call LoggerContext.stop(), and so does logback's own <shutdownHook>.

Measured end to end with 0.3.8 against a real source, SIGTERM one second into a four-second request:

  • Spring Boot 3.5.16 and 4.1.1 delivered 14 and 13 lines, where 0.3.7 delivered 19 and 18. Missing were the ContextClosedEvent listener's line, "Commencing graceful shutdown", the in-flight request's last line, "Graceful shutdown complete" and the @PreDestroy line, so every rolling deploy loses its shutdown logs.
  • Quarkus 3.33 with quarkus-logging-logback lost the ShutdownEvent observer's line.
  • A plain app with logback's <shutdownHook> plus a <delay> lost the line its own shutdown hook logged, which 0.3.7 still delivered.

The hook now only sends what is queued, after waiting for a flush in progress, and leaves the appender running. Whatever is logged afterwards is sent when the framework or logback's hook stops logback, and a JVM that exits without anyone stopping logback still gets its queued logs sent as before. The same scenarios with this change: Spring Boot 19 of 19 lines, the logback <delay> case 4 of 4, and return from main, System.exit, SIGTERM and a 25,000-line backlog all still delivered in full.

The first commit only adds testLogsWrittenWhileAFrameworkShutsDownAreSentWhenItStopsLogback and is expected to fail on CI: a child JVM whose own shutdown hook logs a line and then stops logback, like Spring Boot does. The existing exit test moved onto the same helper.

🤖 Generated with Claude Code

PetrHeinz and others added 2 commits September 29, 2026 10:58
Spring Boot and Quarkus keep logging while they shut down and stop logback
at the very end. Since 0.3.8 the appender's own JVM shutdown hook stops the
appender as soon as the JVM starts shutting down, so those lines are
rejected. FrameworkApp reproduces that in a child JVM.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shutdown hook now only sends what is queued, after waiting for a flush in
progress, instead of stopping the appender. Lines logged afterwards by the
application's own shutdown are queued as usual and sent when the framework
(or logback's <shutdownHook>) stops logback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@PetrHeinz
PetrHeinz marked this pull request as ready for review September 29, 2026 10:21
@PetrHeinz
PetrHeinz merged commit 78a7294 into main Sep 29, 2026
5 checks passed
@PetrHeinz
PetrHeinz deleted the claude/shutdown-hook-flush-only branch September 29, 2026 12:13
PetrHeinz added a commit that referenced this pull request Sep 29, 2026
Merging main brought in flushQueue() as #34 added it, next to the version
this branch replaces it with, and the class did not compile.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.

1 participant