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.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Luis Trigueiros
  • 636
  • 7
  • 21
  • Well, this is not really tied to `Micronaut`, but to the logging library you are working with, right? – x80486 Jul 23 '19 at 16:41
  • 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. – Luis Trigueiros Jul 23 '19 at 17:59
  • 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. – x80486 Jul 23 '19 at 18:25
  • 1
    Thank you, actually found one solution, conditional configuration in logback, https://stackify.com/logging-logback/ – Luis Trigueiros Jul 23 '19 at 19:25
  • 4
    Have you tried `-Dlogback.configurationFile=logback-dev.xml` as **VM Options**? – Jorge Aug 03 '19 at 09:04

5 Answers5

9

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

Yuri
  • 4,254
  • 1
  • 29
  • 46
erik.aortiz
  • 511
  • 5
  • 10
8

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.

patelb
  • 2,491
  • 19
  • 18
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.

Krabi
  • 113
  • 1
  • 9
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>
Rapture
  • 113
  • 1
  • 4
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);

  }
}
tbo
  • 9,398
  • 8
  • 40
  • 51