Write specific logs to a log file spring-boot/slf4j - java

I am able to write console logs to rotating log files using this method here:
https://www.codejava.net/frameworks/spring-boot/logback-rolling-files-example
But my requirement is to write only specific logs to the log files instead of whole console log. For example, i need to write only the json messages(i can print them on console using log.info(message) which is supported by slf4j) being received by Kafka listener to the log files and nothing more. How can i achieve this in my spring-boot app? Is this not possible with slf4j logback?

Specify the appender-ref in your logger element.
So something like this in your logger XML configuration file:
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<appender name="bdfile" class="org.apache.log4j.RollingFileAppender">
<param name="append" value="false"/>
<param name="maxFileSize" value="1GB"/>
<param name="maxBackupIndex" value="2"/>
<param name="file" value="/tmp/bd.log"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
Then in the same config file, add a appender reference to the log file that you are interested in
<logger name="com.example.ClassWithJsonMessage" additivity="false">
<level value="debug"/>
<appender-ref ref="bdfile"/>
</logger>

Related

Logging different levels using same object to different files

My simple question is : If I have two statements like logger.info() and logger.error() in Java (using log4j), I want the results of these two lines to be printed in two separate files. That is, logger.info(...) should print to a file say myLog.info and logger.error(...) should print to myLog.error file. I am using rolling file appender for this task. Also I want just one logger object to do the task. Someone might suggest two or more different loggers one for each file, but that's not the case.
I tried searching a solution for the problem. One of the links Creating multiple log files of different content with log4j says about "threshold" and I even tried to add threshold in my xml configuration file. But what it actually is doing that : info log is being printed in myLog.info file but error log gets printed in both the files. Can it be done through xml configuration file alone or a separate properties file is needed? If xml file is sufficient, then what needs to be done?
I am preferring xml file over properties file. If there is a working solution using only xml configuration file, that would be sufficient. Thanks in advance.
You could use filters to deny any messages except those of the level you want. Here is an example of how to do this:
First a class to test our efforts:
package test;
import org.apache.log4j.Logger;
public class Main {
private static final Logger logger = Logger.getLogger(Main.class);
public static void main(String[] args) {
logger.debug("here's some debug");
logger.info("here's some info");
logger.warn("here's some warn");
logger.error("here's some error");
logger.fatal("here's some fatal");
}
}
Next a log4j.xml config file to set up the appenders and loggers:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c{1}] %m %n" />
</layout>
</appender>
<appender name="debugLog" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="logs/debug.log" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="5000KB" />
<param name="maxBackupIndex" value="5" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelMatchFilter">
<param name="LevelToMatch" value="DEBUG" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="org.apache.log4j.varia.DenyAllFilter" />
</appender>
<appender name="infoLog" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="logs/info.log" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="5000KB" />
<param name="maxBackupIndex" value="5" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelMatchFilter">
<param name="LevelToMatch" value="INFO" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="org.apache.log4j.varia.DenyAllFilter" />
</appender>
<logger name="test" additivity="false">
<level value="DEBUG" />
<appender-ref ref="consoleAppender" />
<appender-ref ref="debugLog" />
<appender-ref ref="infoLog" />
</logger>
</log4j:configuration>
This pattern will allow you to generate a separate log for each log level, just repeat the configuration that I have provided for either debug or info logging. Note that the console appender will accept all levels.
I was able to gain some insight from this post so I thought I should give credit.

Spring jdbcTemplate debug messages not getting printed using log4j

I have the below log4j.xml in placed in the src directory of a web application. Even after follwing many post examples, i cannot get the below configuration print jdbcTemplate internals to log file.
Config:
<appender name="INTERNALSLOG" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="C:/springDB.log"/>
<param name="Append" value="true"/>
<param name="MaxFileSize" value="10mb"/>
<param name="MaxBackupIndex" value="5"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%t] %C{2} - %m%n"/>
</layout>
</appender>
<logger name="org.springframework.jdbc.core">
<level value="DEBUG" />
<appender-ref ref="INTERNALSLOG"/>
</logger>
Whats wrong with the configuration. Just want to get the sql's from jdbcTemplate printed.

Trouble with log4j configuration

I have been trying to change the logging from console to both console as well as file. Looking at the large documentation on log4j I was able to add the appender as shown in the code below. However I don't seem to be getting logs in the specified file.
Any ideas what might be wrong? Here is my log4j.xml (already located at src/)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Threshold" value="DEBUG"/>
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
</layout>
</appender>
<appender name="FILE" class="org.apache.log4j.RollingFileAppender">
<param name="append" value="false" />
<param name="file" value="/data/MFlogs/log.log"/>
<param name="immediateFlush" value="true"/>
<param name="threshold" value="debug"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
</layout>
</appender>
<root>
<priority value="DEBUG" />
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</log4j:configuration>
change file path tag. try it with double slash.
value="//data//MFlogs//log.log"
Try adding full path to path location or add ${catalina.home}/logs/myApp.log to it.
Read this question, it tells how to use relative path. It is easy if you use properties file instead of xml file.

Conditional log4j.xml pattern

Because %C and %M are resource intensive, for the pattern
%d{yyyy-MM-dd HH:mm:ss} [%C][%M][%t]
I would like that %C and %M to be effective only if log level is set to debug (or more detailed levels).
Does log4j have any provisions for such conditional output formats?
Similar to what Matt suggested before, you can also attach filters to log Appenders and attach multiple Appenders to a single logger. For example:
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%C][%M][%t] - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMax" value="DEBUG" />
</filter>
</appender>
<appender name="console2" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="INFO" />
</filter>
</appender>
<root>
<priority value="debug" />
<appender-ref ref="console" />
<appender-ref ref="console2" />
</root>
</log4j:configuration>
This should output the patterns you require. The max level filter on the first appender should prevent high log levels and the min level on the second appender prevents debug level statements from appearing twice.
Hope this helps.
You could use another logger that sets additivity="false" for the debug level combined with a ThresholdFilter that only accepts DEBUG or below. It would be a bit of work, though. If that doesn't work, file an issue.

Why is log4j logging to the console?

This is a standalone java application.
I am using the configuration file below and having two problems.
1) I'm getting logs to stdout and I don't know why.
2) I'm getting ALL log messages in my error log even though I have tried to direct only error and higher to the error log.
I am using the BasicConfigurator without specifying an explicit path to the log4j.xml file. The xml file is in the same jar as my classes. It is creating and writing to the appropriate logs in addition to these problems so the configuration is being applied.
3) In addition, I have had no luck having the log4j.xml file outside of the jar so I can change it at runtime. How do I do that?
<!--appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Threshold" value="DEBUG"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p [%F:%L] - %m%n"/>
</layout>
</appender-->
<!-- working dir is $CATALINA_TMPDIR. send logs to log dir. -->
<appender name="ROLL" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="/var/log/company/application.log"/>
<param name="MaxFileSize" value="5MB"/>
<param name="MaxBackupIndex" value="9"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c %x - %m%n"/>
</layout>
</appender>
<appender name="ERRORLOG" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="/var/log/rocketvox/company/error.log"/>
<param name="MaxFileSize" value="5MB"/>
<param name="MaxBackupIndex" value="9"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c %x - %m%n"/>
</layout>
</appender>
<category name="com.company">
<priority value="ALL"/>
<appender-ref ref="ROLL"/>
</category>
<category name="com.mattx">
<priority value="ALL"/>
<appender-ref ref="ROLL"/>
</category>
<root>
<priority value="error"/>
<appender-ref ref="ERRORLOG"/>
</root>
Add -Dlog4j.debug to the application's JVM args to see exactly what log4j is doing and which configuration file it uses.
Your problem is using BasicConfigurer - for configuring using a file named log4j.xml, you don't need to use any explicit log4j Configurer in your application code, as the default log4j initialization logic will kick in to pick log4j.xml (or log4j.properties, if no xml is found) from the classpath.
See Default Initialization Procedure from the log4j manual.

Categories

Resources