How to use request param as log identifier in logback - spring

In my controller I get an id as request param. Is there a way to use this id to identify all the log entries of this particular request?
#ResponseBody
#RequestMapping(value="/anyRequest", method = RequestMethod.GET)
public String doAnything(#RequestParam(value="Id", required = true) long id) {
logger.info(id);
return "";
}
Means anywhere of this entry should be the id value:
2017-02-28 08:30:41.035 INFO 23050 --- [http-bio-1084-exec-20] AnyServiceImpl ...
Im using logback and have this configuration:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<springProfile name="dev">
<property name="FILE_PATH" value="C:\\DATA\\temp" />
</springProfile>
<appender name="FILE-AUDIT"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${FILE_PATH}/service.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n
</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>service.%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>25MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>90</maxHistory>
</rollingPolicy>
</appender>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<charset>UTF-8</charset>
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n</Pattern>
</encoder>
</appender>
<logger name="Service" level="info"
additivity="false">
<appender-ref ref="FILE-AUDIT" />
<appender-ref ref="consoleAppender" />
</logger>
<root level="info">
<appender-ref ref="FILE-AUDIT" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
And I use the logger in this way:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
Is there any Spring out of the box magic?

Use MDC to achieve this.
Controller Method:
#ResponseBody
#RequestMapping(value="/anyRequest", method = RequestMethod.GET)
public String doAnything(#RequestParam(value="Id", required = true) long id) {
try {
MDC.put("id", id);
logger.info(id);
return "";
} finally {
org.slf4j.MDC.clear();
}
}
Logback.xml:
<Pattern>[%X{id}] %d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n</Pattern>

Related

spring logback how to dinamically retrieve class and application name

I have the following logback-spring.xml configuration file:
<configuration scan="true">
<property name="LOG_PATH" value="/logs/application/"/>
<timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>
<appender name="ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<encoder>
<pattern>[%d{yyyy-MM-dd_HH:mm:ss.SSS}] %-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily and when the file reaches 15 MegaBytes -->
<fileNamePattern>${catalina_home}/${LOG_PATH}/general-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>15MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>30</maxHistory>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
</appender>
<root level="INFO">
<appender-ref ref="ALL" />
</root>
</configuration>
Now, I have my springboot application "Application" and within the class "MyClass" I call:
LoggerFactory.getLogger(MyClass.class);
I want to configure the log file name by changing the static name "general" in "Application-MyClass" (whatever is the application name). Any tips?

Logback TimeBasedRollingPolicy not saving the log with the desired name of the log file

I want to configure TimeBasedRollingPolicy in my spring boot project. I want the log file to be saved in a pattern 'mylog.%d{yyyy-MM-dd}.log'.
My logback-spring.xml file looks like the following:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="Console"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5p{${LOG_LEVEL_PATTERN}} %15.15t - %-80.80c{1.} %X{username} %X{ipaddress} : %msg%n</pattern>
</encoder>
</appender>
<appender name="RollingFile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${catalina.base}/logs/mylog.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5p{${LOG_LEVEL_PATTERN}} %15.15t - %-80.80c{1.} %X{username} %X{ipaddress} : %msg%n</pattern>
</encoder>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${catalina.base}/logs/mylog.%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
</appender>
<root level="INFO">
<appender-ref ref="Console" />
<appender-ref ref="RollingFile" />
</root>
</configuration>
But it's not working, the log file is created but it is not titled mylog but the default 'localhost_access_log.2022-05-16'. Can someone please help me with this?
Declare timestamp separately and refer it inside your fileNamePattern
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<timestamp key="timestamp" datePattern="yyyy-MM-dd"/>
// place all your appenders
<appender name="RollingFile"
.
.
.
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${catalina.base}/logs/mylog.${timestamp}.log</fileNamePattern>
</rollingPolicy>
</appender>
</configuration>

AWS CloudWatch logging with Spring Boot

What should be the approach to store logs of multiple spring boot application(s) in cloud watch?
Sample spring-boot - logback-spring.xml configuration file is below.
<?xml version="1.0" encoding="UTF-8"?>
<property name="LOGS" value="/logs/abc/" />
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern> %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable </Pattern>
</layout>
</appender>
<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOGS}/abc-log.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d %p %C{1.} [%t] %m%n</Pattern> </encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily and when the file reaches 10 MegaBytes -->
<fileNamePattern>${LOGS}/archived/abc-log-%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>5MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>2</maxHistory>
<totalSizeCap>10MB</totalSizeCap>
</rollingPolicy>
</appender>
<!-- LOG everything at INFO level -->
<root level="info">
<appender-ref ref="RollingFile" />
<appender-ref ref="Console" />
</root>
<logger name="com.abc" level="trace" additivity="false">
<appender-ref ref="RollingFile" />
<appender-ref ref="Console" />
</logger>
I was able to achieve the same using Cloudwatch log agent.
Step 1 - Create awslogs.conf file to point to the log location.
[/logs/abcd/8080-abcd.log]
datetime_format = %Y-%m-%d %H:%M:%S
file = /logs/abcd/8080-abcd.log
buffer_duration = 5000
log_stream_name = {hostname}
initial_position = start_of_file
log_group_name = ABCD Group Name
[/logs/defg/8081-defg.log]
datetime_format = %Y-%m-%d %H:%M:%S
file = /logs/abcd/8081-defg.log
buffer_duration = 5000
log_stream_name = {hostname}
initial_position = start_of_file
log_group_name = DEFG Group Name
Step 2 - Install cloud watch log agent as part of UserData/Bootstrap script for ec2.
yum install wget -y
wget https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py
python ./awslogs-agent-setup.py --region $aws_region --non-interactive --configfile=/configlocation/awslogs.conf
Step 3 - Need a role for ec2 machine to create logs in CloudWatch.

How to set log4j log level in spring MVC web project

Please find below for the log4j.xml and controller class. I have added lines in log4j.xml to change the log level from error to debug. But there is no effect seen after adding these lines.
I need this setup to debug "HTTP 400: The request sent by the client was syntactically incorrect."
Could anyone help me on this? Thanks.
log4j.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="Appender1" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-7p %d [%t] %c %x - %m%n"/>
</layout>
</appender>
<appender name="Appender2" class="org.apache.log4j.FileAppender">
<param name="File" value="./Logs/SpringMVC2.log" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-7p %d [%t] %c %x - %m%n"/>
</layout>
</appender>
<!-- no effect of these lines -->
<!-- <logger name="org.springframework.web" additivity="false"> -->
<logger name="org.springframework" additivity="false">
<priority value ="DEBUG" />
<level value="DEBUG"/>
<appender-ref ref="CONSOLE"/>
</logger>
<root>
<priority value ="DEBUG" />
<level value="DEBUG"/>
<appender-ref ref="CONSOLE"/>
</root>
<!-- /no effect of these lines -->
</log4j:configuration>
Controller class
#EnableWebMvc
#Controller
#RequestMapping(value="/home")
public class HomeController {
private Logger logger= Logger.getLogger(HomeController.class);
#RequestMapping(method=RequestMethod.GET)
public String home() {
logger.info("sample info log");
logger.debug("sample debug log");
logger.trace("sample trace log");
logger.error("sample error log");
return "home";
}
}
You define appender with name <appender name="Appender1" class="org.apache.log4j.ConsoleAppender"> but you don't use it.
Instead of use <appender-ref ref="CONSOLE"/> use the one you define :
<logger name="org.springframework" additivity="false">
<priority value ="DEBUG" />
<level value="DEBUG"/>
<appender-ref ref="Appender1"/>
</logger>

Spring-boot log rotations issue with logback

I am working on a spring-boot project and I am using logback and slf4j for logging. Application is deployed on external tomcat and I am using logback 1.1.6 .
I have created an appender with marker , it working fine but rotation policy is not working.
here is the entry from logback.xml
<appender name="FAILED-QUERY"
class="com.xyz.config.HourlyFileAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator">
<marker>FAILEDQUERY</marker>
</evaluator>
<onMismatch>DENY</onMismatch>
<onMatch>NEUTRAL</onMatch>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>
%d{yyyy-MM-dd HH:mm:ss} - %msg%n
</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>${DEV_HOME}/xyz_otp_logs_failed_query.%d{yyyy-MM-dd-HH-mm}.log
</fileNamePattern>
<!-- <timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
</timeBasedFileNamingAndTriggeringPolicy> -->
</rollingPolicy>
</appender>
<logger name="com.xyz" level="info"
additivity="false">
<appender-ref ref="FAILED-QUERY" />
<!-- <appender-ref ref="STDOUT" /> -->
</logger>
The code for rotating policy is below
public class HourlyFileAppender<E> extends RollingFileAppender<E> {
private static long start = System.currentTimeMillis(); // minutes
private int rollOverTimeInSecond = 60*60;
#Override
public void rollover()
{
long currentTime = System.currentTimeMillis();
int maxIntervalSinceLastLoggingInMillis = rollOverTimeInSecond * 1000;
if ((currentTime - start) >= maxIntervalSinceLastLoggingInMillis)
{
super.rollover();
start = System.currentTimeMillis();
}
}
}
though the same settings for other appender is working fine.

Resources