Log4j 1.2 is not logging into RollingFileAppender - spring

I have a problem with Log4J (version 1.2.17) configuration .properties file in my Spring (3.2.5) standalone application.
This is my configuration file, logging to a consoles works fine but RollingFileAppender doesn't append messages into logs/application_log.file. I have tried to change almost everything - file name, ConversionPattern, create the file manually and set filesystem rights (OS X Mavericks) for writing to all but nothing works.
log4j.rootLogger=INFO,CA,FA
#Console Appender
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern=%d{ISO8601} %-5p [%c:%L] - %m%n
#Rolling File Appender
log4j.appender.FA=org.apache.log4j.RollingFileAppender
log4j.appender.FA.File=logs/application_log.log
log4j.appender.FA.MaxFileSize=50MB
log4j.appender.FA.layout.ConversionPattern=%d{ISO8601} %-5p [%c:%L] - %m%n
log4j.appender.FA.Append=true
log4j.appender.FA.MaxBackupIndex=10
log4j.appender.FA.layout=org.apache.log4j.PatternLayout
What am I doing wrong? Do you see something wrong what I don't see?

It looks like you're using wrong class for your appender. You should use org.apache.log4j.DailyRollingFileAppender (you're missing word Daily).
But personally I prefer using log4j.xml instead of log4j.properties. For example:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="true" xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="log-app" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="C:/Temp/my-log.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n"/>
</layout>
</appender>
<root>
<level value="debug"/>
<appender-ref ref="log-app"/>
</root>
</log4j:configuration>
jUnit test:
import org.apache.log4j.Logger;
import org.junit.Test;
public class FakeTest {
private final static Logger log = Logger.getLogger(FakeTest.class);
#Test
public void testTestMe() throws Exception {
log.debug("Debug message");
log.error("Error message");
}
}
Result in my-app.log:
2013-12-20 09:40:40,589 [main] DEBUG my.package.FakeTest - Debug message
2013-12-20 09:40:40,589 [main] ERROR my.package.FakeTest - Error message

Related

How to Log AWSRequestId with Micronaut Lambda Application Native Image

Based on this guide about logging AWSRequestId, I can add %X{AWSRequestId} on my logback.xml to print the request id on my lambda function.
On the example, the method that adds this key on MDC is populateMappingDiagnosticContextValues of class MicronautRequestHandler. But since my lambda function has two endpoints, I created it as an Application type and it says it's using the MicronautLambdaHandler as the handler class.
What I did is I created my custom handler that extends the MicronautLambdaHandler and added the populateMappingDiagnosticContextValues method.
#Override
public AwsProxyResponse handleRequest(AwsProxyRequest input, Context context) {
if (context != null) {
populateMappingDiagnosticContextValues(context);
}
return handler.proxy(input, context);
}
logback.xml
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<withJansi>false</withJansi>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %X{AWSRequestId} %-5p %c{1} - %m%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>
On the lambda setup I pointed the handler on my custom handler and the app is working.
Except that the logs is not showing the AWSRequestId.
Is this functionality only works on MicronautRequestHandler class and not on MicronautLambdaHandler?
I also tried the aws guide here that uses log4j2 for logging the request id. But log4j doesn't work when building the GraalVM native image, that's why I sticked to logback.
If you copied populateMappingDiagnosticContextValues and mdcput into your Handler (I suppose you did it) it should work without any additional changes.

Logback with spring-boot: use ${user.home} does not work

I can't figure out why logback does not take into account the variable defined in the corresponding application-{env}.yml file.
Here is the content of logback-spring.xml file:
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<springProperty scope="context" name="LOG_FILE" source="logging.file"
defaultValue="localhost"/>
<property name="LOG_FILE" value="${LOG_FILE}"/>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</fileNamePattern>
<!-- keep 30 days' worth of history capped at 3GB total size -->
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<logger name="com.example.demospringweb" level="INFO">
<appender-ref ref="FILE" />
</logger>
<springProfile name="default">
<root level="debug">
<appender-ref ref="CONSOLE"/>
</root>
<logger name="com.demospringweb" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE" />
</logger>>
</springProfile>
<springProfile name="qa, prod">
<logger name="com.demospringweb" level="WARN" additivity="false">
<appender-ref ref="FILE" />
</logger>
</springProfile>
</configuration>
And here is the content of the application.yml file:
greeting: Default greeting
password: default-pass
logging:
path: ${user.home}
file: ${logging.path}/demo_localhost
max-history: 30
level:
com:
example: debug
org:
hibernate: ERROR
springframework:
web: DEBUG
When I start the spring-boot app, it does not create a required log file.
UPDATE
I removed completely spring-logback.xml and kept profile-specific properties in corresponding application.yml files.
Here is the application.yml file and it never writes (creates) a log file:
greeting: Default greeting
password: default-pass
spring:
application:
name: demo-spring
logging:
file: demo-dev
pattern:
file: "%d{dd-MM-yyyy HH:mm:ss.SSS} %logger.%M - %msg%n"
console: "%d{dd-MM-yyyy HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger.%M - %msg%n"
level:
root: debug
org:
hibernate: ERROR
springframework:
web: DEBUG
What am I missing?
Finally, I figured out how to achieve that.
Remove logback-spring.xml or logback.xml file if there is any. In this case, Spring boot will use the default values defined by Logback if they are not overridden in your application.yml (or application.properties) file.
Create application.yml and application-prod.yml. file (you can add as many as you want, depending on how many environments you are going to have.
Here is the content of application.yml file used for development:
spring:
application:
name: demo-spring
greeting: Development greeting
password: dev-pass
logging:
pattern:
console: "%d{dd-MM-yyyy HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger.%M - %msg%n"
level:
root: debug
org:
hibernate: ERROR
springframework:
web: debug
com:
example:
demospringweb: info
In this case, the output will be printed to the console only using the provided pattern. The root log level is set to debug but the package com.example.demospringweb is set to info(you can use either UPPERCASE or lower cased versions of log levels).
Create a profile-specific application-prod.yml file that will be used when the app is started with the prod activated:
spring:
application:
name: demo-spring
greeting: Production greeting
password: prod-pass
logging:
path: ${user.home}/logs
file: ${logging.path}/prod.log
total-size-cap: 100MB
max-history: 10
max-file-size: 5MB
pattern:
console: off
file: "%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M - %msg%n"
rolling-file-name: ${logging.path}/plage_%d{dd-MM-yyyy}_%i.log
level:
root: info
org:
hibernate: ERROR
springframework:
web: warn
com:
example:
demospringweb: info
As you see, when starting the app with spring-boot:run -Dspring-boot.run.profiles=prod Spring Boot will use the values defined in application-prod.yml file:
write the logs to the file prod.log created in the user $HOME/logs directory. We also defined a rolling policy to keep 10 days history of max 5Mb by file max. The total size of all the log files is set to 100 Mb. Once it is achieved, the oldest file will be removed.
We also defined different log levels (root and by package).
To check how the logging varies depending on the active profile, take a look at the GreetingController:
package com.example.demospringweb.controllers;
import com.example.demospringweb.models.Greeting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.atomic.AtomicLong;
#RestController
public class GreetingsController {
private static final Logger LOGGER = LoggerFactory.getLogger(GreetingsController.class);
private final AtomicLong counter = new AtomicLong();
#Value("${greeting}")
private String greeting;
#Value("${password}")
private String password;
#GetMapping("/greeting")
public Greeting greeting() {
LOGGER.debug("This is a debug message");
LOGGER.info("This is an info message");
LOGGER.warn("This is a warn message");
LOGGER.error("This is an error message");
String message = greeting + "/pwd: " + password;
return new Greeting(counter.incrementAndGet(), message);
}
}
VoilĂ .

logback-spring.xml log to file while using org/springframework/boot/logging/logback/base.xml

I have created a test project with Spring Boot to learn about about using the logback-spring.xml file. I want to use Spring's default setting for writing to console so I am using the following line
<include resource="org/springframework/boot/logging/logback/base.xml" />
And I also want to log to a file on a rolling basis and keep a maximum number of log files on the system. Writing to console is working as expected. However no logs are written to the log file. The folder named "logs" gets created and the file "logfile.log" also gets created. But nothing gets logged to it.
Below is the fill logback-spring.xml file
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<property name="LOG_PATH" value="logs" />
<property name="LOG_ARCHIVE" value="${LOG_PATH}/archive" />
<appender name="File-Appender" class="ch.qos.logback.core.FileAppender">
<file>${LOG_PATH}/logfile.log</file>
<encoder>
<pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger{36}.%M - %msg%n</pattern>
<outputPatternAsHeader>false</outputPatternAsHeader>
</encoder>
</appender>
<logger name="test" level="DEBUG" />
</configuration>
and below is the TestApplication.java file which is part of the test package
#SpringBootApplication
public class TestApplication {
private static final Logger logger = LoggerFactory.getLogger(TestApplication.class);
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
logger.trace("Trace Message!");
logger.debug("Debug Message!");
logger.info("Info Message!");
logger.warn("Warn Message!");
logger.error("Error Message!");
}
}
Why is nothing being logged to the file?
I think there are a few issues.
First, remove the line <logger name="test" level="DEBUG" /> . This sets up a logger for classes under the package test but defines no appender, so nothing is logged.
Once that's gone, add
<root level="DEBUG">
<appender-ref ref="File-Appender"/>
</root>
This will configure the root logger (which all loggers inherit) on debug level and to output all the logs to the File-Appender.
Also, I cannot recall if logback creates missing directories, so you might need to ensure the logs directory does exist before starting the application.

configuring log4j.xml from different location other than classpath in spring boot application

I am using sl4j logger print logs in file, I have following log4j.xml file configured, as I am deploying my spring application on JBOSS it doesn't create directory structure like tomcat so I am not able to configure debug level of log, I want to my application to pick the log4j.xml from different location like d:\configuration so that I can configure debug level for my application how can I do it ? I am not having web.xml. I have tried using PropertyPlaceholderConfigurer class but it gives error as file not found though file is present
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>
<appender name="file" class="org.apache.log4j.RollingFileAppender">
<param name="append" value="false" />
<param name="file" value="/home/client/webApp.log"/>
<param name="maxFileSize" value="5MB" />
<param name="maxBackupIndex" value="5" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>
<root>
<priority value="DEBUG" />
<appender-ref ref="file" />
</root>
First in application.properties set a property viz. server.context_parameters.log4jConfigLocation=path/to/log4j.xml.
Then implement a listener class Log4jConfigListener as below
import java.io.File;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.log4j.LogManager;
import org.apache.log4j.xml.DOMConfigurator;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
public class Log4jConfigListener implements ServletContextListener {
#Override
public void contextDestroyed(ServletContextEvent servletcontextevent) {
LogManager.shutdown();
}
#Override
public void contextInitialized(ServletContextEvent servletcontextevent) {
ServletContext context = servletcontextevent.getServletContext();
String path = null;
path = context.getInitParameter("log4jConfigLocation");
PathMatchingResourcePatternResolver pathResolver = new PathMatchingResourcePatternResolver();
Resource[] resources = null;
try {
resources = pathResolver.getResources(path);
for (Resource resource : resources) {
File file = resource.getFile();
path = file.getAbsolutePath();
break; // read only the first configuration
}
} catch (IOException e) {
context.log("Unable to load log4j configuration file", e);
}
LogManager.resetConfiguration();
DOMConfigurator.configure(path);
}
}
Next register the listener in configuration class as #Bean
#Bean
public Log4jConfigListener log4jConfigListener() {
return new Log4jConfigListener();
}
Update pom.xml to exclude default logback configuration and include the log4j as below
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
</dependency>
Let know in comments for any more information.
P.S.: For non Spring Boot (or with traditional web.xml) refer my answer here

Querydsl logging queries with bindings

logQuery is called in prepareStatementAndSetParameters mehtod - SQLInsertClause class
protected void logQuery(Logger logger, String queryString, Collection<Object> parameters) {
String normalizedQuery = queryString.replace('\n', ' ');
MDC.put(QueryBase.MDC_QUERY, normalizedQuery);
MDC.put(QueryBase.MDC_PARAMETERS, String.valueOf(parameters));
if (logger.isDebugEnabled()) {
logger.debug(normalizedQuery);
}
}
how can I set debug level to logger ?
That logger there is from SLF4J API. Depending on the logger you have behind the API you use facilities of that underlying logging implementation.
For instance we use Logback Classic (dependency ch.qos.logback:logback-classic) and I can explicitly override what configuration file to use with -Dlogback.configurationFile=devel-logback.xml in JVM parameters. Default mechanism is documented here. My file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date %level [%.60thread] %logger{1} %msg%n</pattern>
</encoder>
</appender>
<logger name="com.mysema.query.jpa.impl.JPAQuery" level="DEBUG"/>
<!-- more loggers -->
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>
Also adding -Dlogback.debug=true to JVM arguments adds some debug output when logback is being initialized.

Resources