Ignore out-of-range batch, queue, retry, timeout and flush settings with a warning - #45
Merged
Merged
Conversation
…ignored with a warning A batchInterval below 1 ms must not keep the appender from starting: from a logback configuration it must start without an error status, keep the default 3000 ms and send on it; set in code before start() or on a running appender it must keep the interval set before and send on that schedule. A negative maxFlushTime must not make stop() throw: the queue is sent and the default 30000 ms is kept. Each ignored value leaves a warning in logback's status. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…warning setBatchInterval() stored 0 or less for start() to schedule the sender with, which throws IllegalArgumentException: logback 1.2 left the appender unstarted, logback 1.3+ failed the whole configuration. On a running appender it cancelled the sender before throwing. A negative maxFlushTime made Thread.join() throw in stop() and in the shutdown hook, which then let the JVM exit without sending the queue. Both setters now keep the current value and add a warning to logback's status instead; 0 still means no limit for maxFlushTime. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ngs are ignored with a warning A batchSize or maxQueueSize below 1, a negative maxRetries and a negative connectTimeout or readTimeout must be ignored: from a logback configuration the appender keeps the default, records a warning and no error in logback's status and still sends; set in code it keeps the value set before, which also pins that 0 retries and a timeout of 0 (none) stay valid. A kept batch size still splits the queue into batches, a kept queue size still limits the queue. Each test checks the kept value before anything is logged, so on the current code they fail at once, without starting a flush. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…arning A batchSize of 0 made every flush send an empty batch and loop without end (below 0 it failed on every attempt), so nothing queued was ever sent. A maxQueueSize below 1 queued nothing, a negative maxRetries dropped every batch before its first attempt, and a negative connectTimeout or readTimeout made HttpURLConnection throw on every request, so every batch was dropped after its retries. The setters now keep the current value and add a warning to logback's status instead, like batchInterval and maxFlushTime; 0 still means no retries for maxRetries and no timeout for the timeouts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PetrHeinz
marked this pull request as ready for review
September 29, 2026 16:55
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Since #44,
setBatchInterval()only stores the value andstart()schedules the sender with it, so abatchIntervalof 0 or less makesstart()throw theIllegalArgumentExceptionofscheduleWithFixedDelay(). Measured with<batchInterval>0</batchInterval>(and -1) in a logback.xml that also has a console and a file appender:RuntimeException in Action for tag [appender] java.lang.IllegalArgumentExceptionand leaves the Logtail appender unstarted: nothing is sent, the console and the file keep logging.Failed to initialize or to run Configurator), so the console and the file log nothing either. A Spring Boot 3.5.16 app with the setting in logback-spring.xml does not start at all ("Logging system failed to initialize").Failed to set property [batchInterval] to value "0"and the appender kept running without its periodic sends, so only full batches and the flush at JVM exit went out.A negative
maxFlushTime(new in #35, not released yet) goes toThread.join(), which throwstimeout value is negative. The shutdown hook dies at once and the JVM exits without sending the queue (0 of 100 queued lines arrived, on JDK 8 and 21), andstop()throws, which also aborts logback's reset inLoggerContext.stop(). logback's ownAsyncAppender, whichmaxFlushTimeis modelled on, throws fromstop()on a negative value too, but has no shutdown hook that would lose the queue.The other numeric settings were never checked either, and some of their values keep the appender from sending anything while logback's status shows no error. This is as old as the settings, 0.3.8 behaves the same unless noted:
batchSize0 makes every flush send an empty batch and start over, since it never takes a line off the queue: against a local endpoint, about 18,000 empty requests a second over one kept connection and none of the queued lines, until the JVM exits, which the shutdown hook holds for the fullmaxFlushTimewhile it waits for that flush. 0.3.8 looped the same way over a new connection per request, and its JVM did not exit at all. A negativebatchSizefails every attempt onbatch.subList(0, -1)instead and, once the retries are used up, logsError trying to call Better Stack : fromIndex(0) > toIndex(-1)in a tight loop (about 600,000 times a second in a probe).maxQueueSize0 or less queues nothing, so nothing is sent. 0 logsMaximum number of messages in queue reached (0)once, a negative value nothing at all.maxRetriesdrops every batch before its first attempt (Dropped batch of 3 logs.).connectTimeoutorreadTimeoutmakesHttpURLConnectionthrowtimeouts can't be negativeon every request, so every batch fails, is retried 5 times and dropped.Each of these setters now keeps the value it had instead:
setBatchInterval()ignores a value below 1 with a warning in logback's status (batchInterval must be positive, keeping 3000 ms instead of 0), keeps the current interval and leaves a running sender alone. Valid values behave as before.setMaxFlushTime()ignores a negative value the same way (maxFlushTime must be 0 (no limit) or more, keeping 30000 ms instead of -1). 0 still means no limit.setBatchSize()andsetMaxQueueSize()ignore a value below 1,setMaxRetries(),setConnectTimeout()andsetReadTimeout()a negative one, the same way (batchSize must be positive, keeping 1000 instead of 0,maxRetries must be 0 (no retries) or more, keeping 5 instead of -1,connectTimeout must be 0 (no timeout) or more, keeping 5000 ms instead of -1). 0 still means no retries and no timeout. A negativeretrySleepMillisecondsis left alone:TimeUnit.sleep()returns at once, so it only means no pause between retries.Measured with the jars of main (64cef67) and of this branch (3548ce4 for the first two tables, a7a53c2 for the third) on JDK 21, against a local endpoint that counts the lines of each request. For
batchInterval, the logback.xml has a console, the Logtail and a file appender, and the app logs 3 lines and waits 4.5 s:batchIntervalFor
maxFlushTime-1, withbatchInterval60000, the app queues 100 lines and returns frommainwithout stopping logback:timeout value is negative, 0 of 100 lines arriveFor the other settings, the same logback.xml has one of them changed and the app again logs 3 lines and waits 4.5 s. logback 1.2.13 and 1.5.38 behave the same, the console and the file log the 3 lines in every run, and no run records an error status:
batchSize0maxQueueSize0Maximum number of messages in queue reached (0)maxRetries-1Dropped batch of 3 logs.connectTimeout-1,readTimeout-1 (a run each)timeouts can't be negative, thenDropped batch of 3 logs.batchSize1,maxQueueSize10,maxRetries0,connectTimeout0,readTimeout0The commits come in two red/green pairs. The first commit only adds the tests for
batchIntervalandmaxFlushTimeand fails on CI with four of them (run):LogtailAppenderLifecycleTestconfigures two appenders from XML with 0 and -1 (two error statuses from theIllegalArgumentExceptioninstead of started appenders and warnings), sets 0 in code beforestart()and -5 on a running appender (both throwIllegalArgumentException), andLogtailAppenderMaxFlushTimeTeststops an appender withmaxFlushTime-1 (stop()throwstimeout value is negative). The second commit makes them pass. The third commit adds the tests for the other settings and fails on CI with five of them on every JDK (run):LogtailAppenderOutOfRangeSettingsTestconfigures an appender per setting from XML (no warnings, the values taken as they are) and sets a batch size, a queue size and a number of retries in code (the invalid value replaces the one set before), andLogtailAppenderTimeoutTestdoes the same for both timeouts. Each of them checks the setting before anything is logged, so the red run never starts the endless flush. The fourth commit makes them pass.🤖 Generated with Claude Code