'Merge logging config of Spring boot and Logback

I have a following situation: A spring boot app using logback and several logging properties configured already in application.yml

I would like to add other config options that are only available via logback.xml file but as soon as i add this file to the classpath (does not matter if it is named logback.xml or logback-spring.xml) it overrides everything from application.yml and all logging levels/patterns and other options defined there stop having effects - it seems that after adding logback.xml all options from appication.yml are ignored and i would need to readd them in the xml file instead of yml.

My question is: is it possible to merge these two configs? I mean i only need to add one option to logback.xml and i do not want to force every other developer to learn logback.xml syntax while they are already familiar with application.yml way of configuring logging.

UPDATE1

One of things i am trying to do is to enable logback JMX access, therefore i create a logback-spring.xml file with following contents:

<configuration debug="true">
   <jmxConfigurator />
</configuration>

Right after i introduce this file i lose all logging from the webapp even if i have logging.level.root: info in the application.yml file.

I would also like to keep using root logging level and pattern as it is defined in the application.yml. I also want to configure several turboFilters which are specific to logback and, from my knowledge, can only be degined via logback configuration file.

UPDATE 2

Both @devatherock and @Ashish Patil asnwers helped me with the issue, i have been aware of the possibility to include spring configuration elements in logback.xml via springProperty but i have not seen it as a viable solution since i would have to rewrite multiple elements this way making the logback.xml harder to read.

But as @devatherock mentioned - by default the config files ARE merged it is that logback requires the existence of appender and root logger in its configuration. Even when present in the logback.xml file the root logger level will still be overwritten by application.yml setting (which is desired) but the pattern property will not and we have to use springProperty for that.

So while both answers were helpful but actually @devatherock's insignts were more helpful for me i am included to accept his answer.



Solution 1:[1]

I created a sample project, spring-boot-logback which specifies logging config in both logback.xml and application.yml

The root log level gets set to WARN in the logback.xml which looks like below:

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <withJansi>true</withJansi>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="WARN">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

There is a controller method that handles /hello, with a DEBUG and a INFO log line. The log level for the controller class is set to DEBUG in the application.yml file which looks like below:

logging:
  level:
    io.github.devatherock.demo.controller: DEBUG

I started the application and hit the /hello controller endpoint. Below are the log lines that I saw:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.7)

08:41:45.051 [http-nio-8080-exec-1] DEBUG i.g.d.d.controller.HelloController - Debug log in sayHello method
08:41:45.052 [http-nio-8080-exec-1] INFO  i.g.d.d.controller.HelloController - Info log in sayHello method

None of the application startup logs are present because the root log level is set to WARN in the logback.xml. Both the debug and info log lines from the controller are present because the controller log level has been set to DEBUG in the application.yml. Thus we can confirm that logging config from both logback.xml and application.yml are applied without any issues

Update 1:

Looks like if a logback.xml is specified, at a minimum, it needs to have the appender, encoder and the attachment of appender to root log level, for the logging config overrides using spring boot's logging.* properties to work. Once I specified such a logback.xml file with also the jmxConfigurator, I was able to adjust the root and controller log levels in the application.yml. The new logback.xml and application.yml files below:

logback.xml with jmxConfigurator:

<configuration>
    <jmxConfigurator />
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

application.yml with root log level:

logging:
  level:
    root: WARN
    io.github.devatherock.demo.controller: DEBUG

Solution 2:[2]

Use of springProperty might be suitable for your requirement.

Let's say ,you have application.yml like below:

logging:
  level:
    root: DEBUG
...  // other configs

Now you want to enforce configs of application.yml even after having logback.xml, then you can add springProperty in your logback.xml:

<configuration>
    <jmxConfigurator />
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <springProperty scope="context" name="loggerProperty" source="logging.level.root"/>
    
    <root level="${loggerProperty}">
        <appender-ref ref="STDOUT" />
    </root>
    ... //other configurations.
</configuration>

Now, here when you start your spring-boot, you can see application.yml's config value is getting read instead of overriding.

So by this way , you can have as many properties configured in logback & in application.yml.

Basically, you are referring Environment properties (which are defined in your application.properties / application.yml) from your logback.

Here logging.level.root is environment property which is defined application.yml & you referred it in logback.xml by giving it a name as loggerProperty. You are then using this loggerProperty within your logback so that it will get used instead of logback's default one.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2