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.
-
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
-
1Thank you, actually found one solution, conditional configuration in logback, https://stackify.com/logging-logback/ – Luis Trigueiros Jul 23 '19 at 19:25
-
4Have you tried `-Dlogback.configurationFile=logback-dev.xml` as **VM Options**? – Jorge Aug 03 '19 at 09:04
5 Answers
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:
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); } }
create you custom env based logback config file like:
logback-dev.xml
and put in resources dir.then set env var
MICRONAUT_ENVIRONMENTS=dev
according to your deployment logic.enjoy using
logback-dev.xml
,logback-prod.xml
,logback-stagging.xml
, etc

- 4,254
- 1
- 29
- 46

- 511
- 5
- 10
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.

- 2,491
- 19
- 18
-
1I believe this the cleanest solution so far, as logback supports if conditions. – Traycho Ivanov Jul 28 '20 at 19:42
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.

- 113
- 1
- 9
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>

- 113
- 1
- 4
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);
}
}

- 9,398
- 8
- 40
- 51