Versions
- logback version: 1.5.33
- JDK version: 17
Describe the problem
FileCollisionAnalyser currently detects duplicate file / fileNamePattern values during the DEPENDENCY_ANALYSIS phase of model processing.
This works for collisions that are already visible at configuration parse time, but it does not seem to cover cases where appenders are created dynamically after initial configuration.
As a result, two appenders may end up writing to the same file even though the existing collision check did not reject them.
Minimal reproduction
With the configuration below, SiftingAppender creates one nested FileAppender per discriminator value.
If two different discriminator values are used, two different appenders are created (FILE-A and FILE-B), but both write to the same target file.
This case does not appear to be rejected by FileCollisionAnalyser.
logback.xml
<configuration debug="true">
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
<property name="LOG_DIR" value="logs" />
<property name="TARGET_FILE" value="${LOG_DIR}/shared.log" />
<appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
<discriminator>
<Key>userId</Key>
<DefaultValue>default</DefaultValue>
</discriminator>
<sift>
<appender name="FILE-${userId}" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${TARGET_FILE}</file>
<append>true</append>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
</sift>
</appender>
<root level="INFO">
<appender-ref ref="SIFT" />
</root>
</configuration>
Example Java snippet
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
public class Demo {
private static final Logger logger = LoggerFactory.getLogger(Demo.class);
public static void main(String[] args) {
MDC.put("userId", "A");
logger.info("message from A");
MDC.clear();
MDC.put("userId", "B");
logger.info("message from B");
MDC.clear();
}
}
Reproduction steps
- Start the application with the configuration above.
- Log one event with MDC
userId=A.
- Log another event with MDC
userId=B.
Actual behavior
Two different nested appenders are created and both write to the same file (logs/shared.log).
Expected behavior
The second appender should ideally be rejected at startup time because its effective file target is already in use by another appender.
Observations from the code
FileCollisionAnalyser is a model analyser in the DEPENDENCY_ANALYSIS phase.
- It stores seen values in
ModelInterpretationContext.
- It skips initialization only for collisions detected during that model-processing pass.
AppenderFactoryUsingSiftModel appears to build dynamic appenders with its own processor setup, and it does not seem to register FileCollisionAnalyser.
So the current protection seems limited to configuration-time model analysis, not runtime appender startup.
Suggested direction
A more robust approach may be to perform collision detection at FileAppender.start() / RollingFileAppender.start() time, using a context-level registry of active file targets.
That registry could:
- register the effective file target on successful start
- reject startup if the same target is already owned by another appender
- unregister on stop
Versions
Describe the problem
FileCollisionAnalysercurrently detects duplicatefile/fileNamePatternvalues during theDEPENDENCY_ANALYSISphase of model processing.This works for collisions that are already visible at configuration parse time, but it does not seem to cover cases where appenders are created dynamically after initial configuration.
As a result, two appenders may end up writing to the same file even though the existing collision check did not reject them.
Minimal reproduction
With the configuration below,
SiftingAppendercreates one nestedFileAppenderper discriminator value.If two different discriminator values are used, two different appenders are created (
FILE-AandFILE-B), but both write to the same target file.This case does not appear to be rejected by
FileCollisionAnalyser.logback.xml
Example Java snippet
Reproduction steps
userId=A.userId=B.Actual behavior
Two different nested appenders are created and both write to the same file (
logs/shared.log).Expected behavior
The second appender should ideally be rejected at startup time because its effective file target is already in use by another appender.
Observations from the code
FileCollisionAnalyseris a model analyser in theDEPENDENCY_ANALYSISphase.ModelInterpretationContext.AppenderFactoryUsingSiftModelappears to build dynamic appenders with its own processor setup, and it does not seem to registerFileCollisionAnalyser.So the current protection seems limited to configuration-time model analysis, not runtime appender startup.
Suggested direction
A more robust approach may be to perform collision detection at
FileAppender.start()/RollingFileAppender.start()time, using a context-level registry of active file targets.That registry could: