Micronaut configure logger appenders based of the enviroment - logback

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.

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.
the set env var MICRONAUT_ENVIRONMENTS=dev according to your deployment logic.
enjoy using logback-dev.xml, logback-prod.xml, logback-stagging.xml, etc

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.

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.

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>

Related

How to configure logback-based logging to handle log masking with Apache Storm?

I am trying to configure logback based log masking for Apache Storm topologies.
When I try to replace logback.xml file inside Apache Storm log4j2- directory and update worker.xml and cluster.xml file, Apache Storm nimbus and supervisors are unable to understand logback based keywords.
Error:
2022-10-02 16:31:51,671 Log4j2-TF-1-ConfiguratonFileWatcher-2 ERROR Unable to locate appender "A1" for logger config "root"
2022-10-02 16:32:51,681 Log4j2-TF-7-ConfiguratonFileWatcher-4 ERROR Error processing element appender ([configuration: null]): CLASS_NOT
Sample cluster.xml file:
<configuration monitorInterval="60" shutdownHook="disable">
<properties>
<property name="pattern">%msg%n</property>
</properties>
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.FileAppender"/>
<FileAppender name="A1">
<file>logfilename.log</file>
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</FileAppender>
<loggers>
<root level="info"> <!-- We log everything -->
<appender-ref ref="A1"/>
</root>
</loggers>
</configuration>
To my best knowledge, Apache Storm uses naturally log4j2, as also your logfile indicates. However, when I used log4j in Storm, I did not need to import any further classes. You also do not seem to use these logback-classes in the rest of your xml-file. So have you tried to simply remove those?

How to override logback config in Sonatype Nexus 3?

I'm running Sonatype Nexus 3.15.0-01 and am a little stumped about how to override the default logback configs.
I created a file called 'logback-overrides.xml' in the 'nexus-data/etc/logback' folder containing the following:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/nexus-data/log/myApp.log</file>
<encoder>
<pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
This is essentially just a simple bit of config that should cause logs to be written to '/nexus-data/log/myApp.log'. I restarted the server after adding this file, to confirm it would pick up the new configs.
However, when I check for that file, it's not present. What am I missing here?
I posted this same question on the Sonatype forums here. To sum up the answer I got there, it isn't possible to override the default logback config this way.
Possible workarounds are:
Create your own logback.xml file and build your own Docker image that extends Sonatype’s official image.
Create a volume mount for /opt/sonatype/nexus/etc/logback and customize the logback.xml on your host machine.

Logback configuration without explicit appender defining

The following Logback configuration, one of the loggers explicitly defines it's appender, another one not:
<configuration scan="true" scanPeriod="60 seconds">
<appender name="AMAZING_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>XXX</pattern>
</encoder>
</appender>
<logger name="org.springframework">
<level value="ERROR" />
</logger>
<logger name="com.company" additivity="false">
<level value="INFO" />
<appender-ref ref="AMAZING_APPENDER"/>
</logger>
</configuration>
What appender would the logger without the explicit appender specification would use, if any at all?
By "logger without the explicit specification" I think you are referring to this: <logger name="org.springframework">.
If so, then there is no appender available for that logger and any log events emitted by classes in the org.springframework (regardless of the log level) will be ignored.
If you tweak your logback.xml slightly to add this: <configuration debug="true"> you'll see a WARN event of this nature ...
No appenders present in context [default] for logger [...]
... emitted when a class in the org.springframework emits a log event at ERROR level.
If you want events from the org.springframework namespace (or more generally, from any namespace other than com.company) to be logged then you should add a <root> configuration. For example:
<root level="INFO">
<appender-ref ref="AMAZING_APPENDER"/>
</root>
If you add a root and point it at AMAZING_APPENDER then you should probably set additive="false" on logger name="com.company" otherwise anything logged from the com.company namespace will be logged twice. So, perhaps your desired configuration will be:
<root level="INFO">
<appender-ref ref="STANDARD_APPENDER"/>
</root>

How to send hibernate connection info to logback

I want to get hibernate conncection info (like driver_class, url, username, password) in logback file. (Not manually)
This belows is my logback file.
<appender name="dbAppender" class="ch.qos.logback.classic.db.DBAppender">
<append>false</append> //unfortunately it does not work.
<connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
<driverClass>oracle.jdbc.driver.OracleDriver</driverClass>
<url>jdbc:oracle:thin:#localhost:1521:aaa</url>
<user>bbb</user>
<password>ccc</password>
</connectionSource>
</appender>
It works. But I want to get information about connection info(like driver class, url, user, password) from hibernate.cfg.xml automatically in logback.xml.
Your cooperation would be appreciated.
Please Help.
Thanks.
Getting the values out of your hibernate.cfg.xml would probably require writing some code. However, if you externalise all your hibernate properties in a properties file you can import them into your logback configuration.
Hibernate supports using a properties file called hibernate.properties in the root of the classpath, or you could pass an instance of java.util.Properties to Configuration.setProperties() when configuring your session factory.
If you can get your hibernate properties into a properties file you can use it from logback like so:
properties file on the classpath
<configuration>
<property resource="hibernate.properties" />
<appender name="dbAppender" class="ch.qos.logback.classic.db.DBAppender">
<append>false</append> //unfortunately it does not work.
<connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
<driverClass>${hibernate.connection.driver_class}</driverClass>
<url>${hibernate.connection.url}</url>
<user>${hibernate.connection.username}</user>
<password>${hibernate.connection.password}</password>
</connectionSource>
</appender>
</configuration>
If your properties aren't on the classpath you can use <property file="path/to/some.properties" /> instead.

logback how to set destination folder for log files

Is there a way to set a single destination folder, such that I can specify where all log files should be created rather than having to set it on an appender by appender basis?
You can define a property in the logback configuration file an use it as below
<configuration>
<property name="USER_HOME" value="/home/sebastien" />
<appender name="SPRING_LOGS" class="ch.qos.logback.core.FileAppender">
<file>${USER_HOME}/spring.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_HOME}/myApp.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
Note that logback can read the variables from System properties or a separate properties file too. Follow the manual for more details.
I've wasted a lot of time configuring Logback to work with Spring Boot and I'd like to share my configuration, hoping to save other people from wasting their time.
My example is similar to Andy Dufresne's above, with one key difference - no <property> tag. This was really important in my case because if you include the <property name="logs_dir" value="." /> you won't be able to override it using system properties, which I wanted to do like this:
java -jar -Dlogs_dir=~/newLogsDir yourApp.jar
Also note the default value is set inside the path variable - ${logs_dir:-.}. Hope this helps:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%-20(%d{yyyy-MM-dd HH:mm:ss} %highlight([%-5level])) %msg%n</pattern>
</encoder>
</appender>
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logs_dir:-.}/system.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover monthly -->
<fileNamePattern>system-%d{yyyy-MM}.log.zip</fileNamePattern>
<maxHistory>12</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%-26(%d [%-5level]) %logger{35} - %msg%n</pattern>
</encoder>
</appender>
</configuration>
I have a spring boot app, and I run the fat .jar as a systemd service.
I struggled a couple of hours on how to set the LOG_PATH relative to the user's home dir.
Here is what worked for me:
in application.properties I have:
logging.path=${HOME}/attach_logs
in logback-spring.xml I have:
<springProperty scope="context" name="LOG_PATH" source="logging.path"/>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/console.log</file>
References:
Getting the user home path in application.properties in Spring Boot
Accessing the application properties in logback.xml
Spring boot logging path
logback how to set destination folder for log files