Micronaut configure logger appenders based of the enviroment
Asked Answered
A

5

8

I would like to configure logging appender based on the environment, for example while running in production I would like to configure an appender that would send log to elasticsearch but while on test or development mode this appender would not be enabled.

Aida answered 21/7, 2019 at 18:27 Comment(5)
Well, this is not really tied to Micronaut, but to the logging library you are working with, right?Tolle
Well if logback supports away to conditionally enable log appender based on some environmental variable this would also work, I will check it thank you. I was aiming to solved it using Micronaut initially because Micronaut is able to pick up if it is running on AWS Cloud or not.Aida
You can also have several files configuration files according to the environment(s), and later on tell Micronaut to read it from a specific/predefined location.Tolle
Thank you, actually found one solution, conditional configuration in logback, stackify.com/logging-logbackAida
Have you tried -Dlogback.configurationFile=logback-dev.xml as VM Options?Covetous
D
10

You can override the default logback config file by using logback.configurationFile system variable.

java -Dlogback.configurationFile=logback-prod.xml -jar your.jar

But, if what you need is the ability to use an env variable you can do this without to use a third-party library:

  1. Override the logback system variable inside the main micronaut class before call main, like following

     @Singleton
     public class MyMicronautApplication  {
    
         public static void main(String[] args) {
             var env = System.getenv("MICRONAUT_ENVIRONMENTS");
    
             if (env != null && !env.isEmpty()) {
                 System.setProperty(ContextInitializer.CONFIG_FILE_PROPERTY, "logback-" + env + ".xml");
             }
    
             Micronaut.run(MyMicronautApplication.class);
    
         }
     }
    
  2. create you custom env based logback config file like: logback-dev.xml and put in resources dir.

  3. then set env var MICRONAUT_ENVIRONMENTS=dev according to your deployment logic.

  4. enjoy using logback-dev.xml, logback-prod.xml, logback-stagging.xml, etc

Distinguished answered 24/3, 2021 at 17:28 Comment(0)
T
9

The work around i found was by doing conditional expressions in logback. You will need the following dependency

<!-- https://mvnrepository.com/artifact/org.codehaus.janino/janino -->
<dependency>
    <groupId>org.codehaus.janino</groupId>
    <artifactId>janino</artifactId>
    <version>3.1.2</version>
</dependency>

Then in your logback.xml file, you can do a conditional statement such as following for selecting the appender you want to you use based on a micronaut profile. In my case, I wanted to activate the STDOUT appender if i was running the application locally but i did not want to activate the STDOUT profile if the app was running in any other environment such as dev or prod profiles, instead i wanted the RSYSLOG appender to be used.

    <root level="info">
        <if condition='property("MICRONAUT_ENVIRONMENTS").contains("local")'>
            <then>
                <appender-ref ref="STDOUT"/>
            </then>
            <else>
                <appender-ref ref="RSYSLOG"/>
            </else>
        </if>
    </root>

You can use conditional statements to configure other properties in your logback file.

Thetos answered 18/5, 2020 at 19:40 Comment(1)
I believe this the cleanest solution so far, as logback supports if conditions.Vandalize
S
1

As far I understand, Micronaut doesn't have similar thing like Spring boot ( ) implemented. I think logback-production.xml (where production is profile ) doesn't work too - only logback.xml and logback-test.xml is suported.

Surfacetosurface answered 30/7, 2019 at 13:4 Comment(0)
V
1

I wasn't crazy about the idea of having multiple logback config files or pulling in another dependency (janino) to support this use-case.

You can also do this using environment variables.

In my logback.xml I defined 2 appenders, one for "DEV" and one for "PROD".

Then I dynamically select which appender to use via the LOG_TARGET variable. If the variable is not set then it defaults to "DEV".

<configuration>

    <appender name="DEV" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date{ISO8601} %-5level [%X{trace_id},%X{span_id}] [%thread] %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="PROD" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="net.logstash.logback.encoder.LogstashEncoder" />
    </appender>

    <appender name="OTEL" class="io.opentelemetry.instrumentation.logback.v1_0.OpenTelemetryAppender">
        <appender-ref ref="${LOG_TARGET:-DEV}"/>
    </appender>

    <root level="info">
        <appender-ref ref="OTEL"/>
    </root>
</configuration>
Volleyball answered 7/2, 2023 at 13:18 Comment(0)
A
0

Yet another approach, if it can be useful for someone. Maybe not the best one but I've been building my micronaut application as native-image and for some reason, the environmental variable inside logback.xml or janino setup did not have any effect during runtime.

Hence, I ended up declaring both references at the root logger and then programmatically removing the appenders I do not want and leaving the one I want based on my configuration or environment variables.

Logback.xml would look like this

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appender name="PLAIN" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} - %msg%n</pattern>
    </encoder>
  </appender>
  <appender name="LOGSTASH" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LogstashEncoder" />
  </appender>
  <root level="error">
    <appender-ref ref="PLAIN"/>
    <appender-ref ref="LOGSTASH"/>
  </root>
</configuration>

and then at micronaut start (simplified for the example)

@Singleton
public class MyMicronautApplication  {

  public static void main(String[] args) {

    List<String> appenders = new ArrayList<>();
    appenders.add("PLAIN");
    appenders.add("LOGSTASH");

    String appender = System.getenv("LOG_APPENDER");

    LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
    Logger root = loggerContext.getLogger("ROOT");

    appenders.filter(value -> !value.equals(appender))
        .forEach(filtered -> root.detachAppender(filtered));

    Micronaut.run(MyMicronautApplication.class);

  }
}
Anglonorman answered 13/7, 2023 at 7:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.