Repository navigation
Conversation
Previously, AOT processing serialized the Logback configuration model to META-INF/spring/logback-model, and this was deserialized and processed at runtime. The deserialization relied on reflection, which made the approach fragile in a native image. This commit uses logback-tyler, when it is on the AOT processing classpath, to translate the Logback XML configuration into Java source for a GeneratedLogbackConfigurator class. The class extends the new SpringBootTylerConfiguratorBase. When AOT-generated artifacts are in use, LogbackLoggingSystem instantiates that class to configure Logback. <springProperty> and <springProfile> elements are translated by Spring Boot-specific Tyler model handlers into code that is evaluated against the Environment at runtime, so profiles and properties still take effect at runtime. Any warning or error reported during translation fails AOT processing. When Tyler is not available, or the configuration was not loaded from a URL, the existing serialized-model approach is used. This commit also upgrades to Logback 1.6.6 and adds dependency management for logback-tyler 1.0.5. Signed-off-by: ceki <ceki@qos.ch>
There was a problem hiding this comment.
🟡 Changes recommended
Valid Logback configurations can produce uncompilable generated code or silently change behavior during translation.
5 open issues
Honor declared XML encoding during configuration translation · New Preserve property-first processing during translation · New Translate the packagingData configuration attribute · New Apply variable substitution to generated logger names · New Prevent duplicate generated appender identifiers across profiles · New
What changed in this PR
Adds optional Tyler-based Java generation to Spring Boot’s Logback AOT support, allowing runtime configuration without deserializing a Logback model.
Changes:
- Generates configurator source with runtime support for Spring properties and profiles.
- Prefers generated configurators at startup while retaining the serialized-model fallback.
- Updates dependencies and adds translation, contribution, and runtime tests.
| File | Description |
|---|---|
| platform/spring-boot-dependencies/build.gradle | Upgrades Logback and manages Tyler. |
| core/spring-boot/src/test/java/org/springframework/boot/logging/logback/SpringBootModelToJavaTests.java | Tests translation equivalence and failure handling. |
| core/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemGeneratedConfiguratorTests.java | Tests generated-configurator startup and fallback. |
| core/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackConfigurationAotContributionTests.java | Keeps existing tests on the serialized-model path. |
| core/spring-boot/src/test/java/org/springframework/boot/logging/logback/GeneratedConfiguratorAotContributionTests.java | Tests generated source, hints, and contribution consistency. |
| core/spring-boot/src/main/java/org/springframework/boot/logging/logback/SpringProfileModelHandler.java | Shares profile-matching logic with generated configuration. |
| core/spring-boot/src/main/java/org/springframework/boot/logging/logback/SpringBootTylerConfiguratorBase.java | Provides runtime Spring property and profile helpers. |
| core/spring-boot/src/main/java/org/springframework/boot/logging/logback/SpringBootModelToJava.java | Translates XML and Spring-specific elements into Java. |
| core/spring-boot/src/main/java/org/springframework/boot/logging/logback/SpringBootJoranConfigurator.java | Contributes generated source when Tyler is available. |
| core/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java | Loads generated configurators during AOT startup. |
| core/spring-boot/build.gradle | Adds the optional Tyler dependency. |
| config/checkstyle/checkstyle-suppressions.xml | Permits logging imports in the new runtime tests. |
Review effort: Balanced
|
Most of the review items automatically generated have easy fixes in logback-tyler that will be adressed by version logback-tyler 1.0.6. However, the remark about "Tyler translates in document order rather than preserving Joran's property-first processing" seems more serious/pervasive. I am looking into it. In the meantime, please do not merge this PR. |
Upgrade to logback-tyler 1.0.6, which fixes the translation issues raised in the review of spring-projectsgh-52466: - Properties are now available to the appenders and loggers that precede them, as with Joran's two processing phases. Conditions, including <springProfile>, are evaluated once, where they appear in the configuration. - The packagingData attribute of <configuration> is translated. - Logger, appender and appender-ref names are substituted at runtime. - Appenders with the same name can be defined in mutually exclusive branches, for example in <springProfile name=dev> and The <springProfile> translation handler now extends Tyler's GuardModelHandler, so that the elements it contains are guarded in both phases. The configuration is now passed to the XML parser as a byte stream so that its encoding declaration is honored. Previously, it was decoded as UTF-8, which corrupted configurations that use another encoding, such as ISO-8859-1, and broke the parsing of UTF-16 configurations. An <appender-ref> to an appender that is never declared now fails AOT processing, as Tyler reports it while translating. With Joran, it only produces a warning at runtime. See spring-projectsgh-52466 Signed-off-by: ceki <ceki@qos.ch>
|
All five issues raised during review were reproduced and are now fixed in logback-tyler version 1.0.6, which commit 2 of this PR now uses. |

Generate Logback configurator during AOT processing
Overview
At the moment, Logback XML configuration in a native image relies on the model serialized during AOT processing (
META-INF/spring/logback-model). That model is deserialized and processed at runtime, which depends on reflection and on Logback's model handlers running inside the native image.This PR uses logback-tyler. When
tyler-baseis on the AOT processing classpath, the application's Logback XML configuration is translated into Java source during AOT processing. The result is aGeneratedLogbackConfiguratorclass that is compiled into the application and used at runtime instead of the serialized model.How it works
AOT processing:
SpringBootJoranConfiguratorpasses the configuration file (getTopURL()) toSpringBootModelToJava, a subclass of Tyler'sModelToJava. The configurator source is contributed asorg.springframework.boot.logging.logback.aot.GeneratedLogbackConfigurator, together with a reflection hint for its public constructor. Includes such as Boot'sbase.xmlare resolved at translation time, so nothing is parsed from XML at runtime.Spring-specific elements: two Boot-specific Tyler model handlers translate
<springProperty>and<springProfile>:<springProperty>becomesPropertyModelHandlerHelper.setProperty(this, name, springProperty(source, defaultValue), scope).<springProfile name="...">becomesif (acceptsProfiles("...")) { ... }around the nested elements.springProperty(...)andacceptsProfiles(...)are provided by the newSpringBootTylerConfiguratorBaseand are evaluated against theEnvironmentat runtime. Activating a profile when the native image is launched (--spring.profiles.active=staging) therefore behaves as it does on the JVM. The profile matching logic is extracted toSpringProfileModelHandler.acceptsProfiles(...), so the XML and generated paths share it.Runtime: when AOT-generated artifacts are in use,
LogbackLoggingSysteminstantiates the generated configurator if it is present and uses it to configure theLoggerContext. Otherwise it falls back to the serialized model, as before.Failure handling: any warning or error reported while parsing, checking or translating the configuration fails AOT processing with an
IllegalStateExceptionthat lists the problems. A configuration that could not be translated faithfully is not silently shipped. For example, a<springProfile>nested inside a<logger>element, which only produces a warning at runtime, now fails the build.Fallback: if Tyler is not on the AOT processing classpath, or the configuration was not loaded from a URL, the existing serialized-model contribution is used unchanged.
Dependencies
ch.qos.logback.tyler:tyler-base1.0.5.tyler-baseis anoptionaldependency ofspring-boot. It is needed only during AOT processing, not at runtime.The Logback upgrade could be split into a separate commit if preferred.
User opt-in
Users currently opt in by adding Tyler to the AOT processing classpath:
dependencies { processAotClasspath("ch.qos.logback.tyler:tyler-base") }Maven has no AOT-only classpath, so
tyler-basehas to be added as a regular dependency. A follow-up could have the Gradle and Maven plugins add it automatically.Testing
SpringBootModelToJavaTests: compiles the translated configurator and checks that it produces the sameLoggerContextstate asSpringBootJoranConfiguratoracross several profile and property combinations. The fixture covers nested and negated profiles,${...}in profile names, conversion rules and thebase.xmlinclude. Translation failures are also covered.GeneratedConfiguratorAotContributionTests: checks the contributed source and hint, that the contributed source compiles, matching and differing contributions, the fallback without Tyler, and failure on configurations that cannot be translated.LogbackLoggingSystemGeneratedConfiguratorTests: checks the runtime path withspring.aot.enabled=true, with and without a generated configurator.:core:spring-boot:checkpasses.logback-spring.xmlandbase.xmlinclude, against Logback 1.6.6 and logback-tyler 1.0.5. With the default andstagingprofiles it logs as expected, the file appender works, and nologback-modelresource is generated.Related issues
<if condition="...">expressions are no longer honored, so there are no runtime-compiled conditions left to support. The issue's comments also suggested combining Tyler-generated code with Boot's Logback support, which is what this PR does.Configuratorthat supports<springProperty>,<springProfile>and Boot's default includes, which are the obstacles described in the issue. This PR does not add a public hook for user-written configurators.LogbackLoggingSystemstill referencesSpringBootJoranConfiguratorfor the non-AOT path, so the XML classes are likely still reachable during native image analysis. Making them unreachable would need further changes, for example skipping the Joran path when a generated configurator is present.