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

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à.

Related

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.

How to enable Logback-access in Spring Boot?

I'm trying to enable logback-access in a spring boot app to log all http requests that hit the application.
I've tried implementing this using: https://github.com/akihyro/logback-access-spring-boot-starter
Adding the XML file shown in the example doesn't do anything, is there anything more that needs to be added to enable?
Any other suggestions to achieve the same result would be welcomed :)
you still need to wire a bean to your application...like this code snippet wires the filter to your application:
#SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
// ... your other methods here
#Bean
public CommonsRequestLoggingFilter logFilter() {
CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();
filter.setIncludeQueryString(true);
return filter;
}
}
I am pretty sure you are talking about the logback logger for SpringBoot. If I am not wrong, this is how you can do this
a. Add the dependency in your POM
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
b. Now there are may ways you can ask spring to configure logback. For example
In the application.properties file
In the logback.xml file
The advantage of using logback.xml file is that, you might have different xml file for different build profile. But in the application.properties, you don’t have this freedom.
Sample entries in the application.properties file from one of my project
logging.level.org.springframework.web = INFO
logging.level.com.company.app = DEBUG
#logging.level.org.hibernate=ERROR
logging.file=logs/spring-boot-logging.log
## Hibernate Logging
logging.level.org.hibernate.SQL = DEBUG
If you are using XML, configuration probably will look like this
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</layout>
</appender>
<logger name="org.springframework" level="error" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
<logger name="org.springframework" level="info" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
<logger name="org.springframework" level="warn" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
<logger name="com.memorynotfound" level="debug" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
<configuration scan="true"/>
</configuration>
I recommend you to do some Googling for better understating.
Good luck!

Play! 2.5 log access to stdout in development

Is there easy way to get development access logs on my console with Play 2.5?
Something I could read as "GET /foo/123 routed to FooController's show action with id=123"?
I've found how to get netty access log ( btw, option play.server.netty.log.wire=true in application.conf doesn't work for me for some reason, but -Dplay.server.netty.log.wire=true does ), but it's too low-level.
You can create a logger.xml file in the conf directory. It should follow logback's file format.
for instance a default configuration could look like :
<configuration scan="true" scanPeriod="5 seconds">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%level %logger{15} - %message%n%xException{5}</pattern>
</encoder>
</appender>
<logger name="play" level="INFO" />
<logger name="application" level="INFO" />
<root level="ERROR">
<appender-ref ref="STDOUT" />
</root>
</configuration>
You can then enable loglevels : FATAL, ERROR, WARNING, INFO, DEBUG, TRACE selectively for any package or as a default on the root leve.
This is described in the playframework configuration configuring logging
Note that this behaviour was changed in 2.4.x from the previous versions where you could configure loggers through application.conf
Once you have logging working you can use the sample logging filter provided in the documentation to log all requests to your server.
import javax.inject.Inject
import akka.stream.Materializer
import play.api.Logger
import play.api.mvc._
import scala.concurrent.{ExecutionContext, Future}
class LoggingFilter #Inject() (implicit val mat: Materializer, ec: ExecutionContext) extends Filter {
def apply(nextFilter: RequestHeader => Future[Result])
(requestHeader: RequestHeader): Future[Result] = {
val startTime = System.currentTimeMillis
nextFilter(requestHeader).map { result =>
val endTime = System.currentTimeMillis
val requestTime = endTime - startTime
Logger.info(s"${requestHeader.method} ${requestHeader.uri} took ${requestTime}ms and returned ${result.header.status}")
result.withHeaders("Request-Time" -> requestTime.toString)
}
}
}
you will have to activate it by setting the play.http.filters:
play.http.filters=com.example.LoggingFilter

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.

Log4j 1.2 is not logging into RollingFileAppender

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

Resources