I have a spring boot application where I need to change log level to info for my application and error for the library it uses. Both of them have the same parent package structure:
com.org.product.library
com.org.product.module
I added the following to the application.yml
logging:
level:
com.org.product.library: ERROR
com.org.product.module: INFO
But now the module is also logging only errors.
This is how Logger is invoked:
public static void info(String msgCode, String msg) {
if (isInfoEnabled()) {
getLoggerEngine().info(msgCodeMarker(msgCode), msg);
}
}
static Logger getLoggerEngine() {
//slf4j LoggerFactory
return LoggerFactory.getLogger(Log.class);
}
Also there is this spring-logback.xml configuration in the library:
<logger name="com.org" level="info" additivity="false">
<appender-ref ref="json" />
</logger>
<!-- By default will log warnings and above-->
<!-- set to other level for development if needed -->
<root level="warn">
<appender-ref ref="json" />
</root>
Related
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.
I have multi-tenant application followed by microservices created in spring boot version 1.4.3, i have generated tenant wise logs in different folders inside logs folder of tomcat.
A Problem which i am facing is after some time/hours/days/weeks my logs will stop but application work in backgroud. I am trying to find root cause of the same but failed.
In java code some classes using Slf4j and some classes using log4j to print logs.
As mentined i am using SiftingAppender and changing logFolder variable from Filter/Intercepter based on the tenant.
previously i was doing MDC.clear() to remove logFolder from MDC, then i have moved to MDC.remove("logFolder") but that also not worked
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}}" />
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<!-- This is MDC value -->
<!-- We will assign a value to 'logFileName' via Java code -->
<appender name="FILE-THREAD" class="ch.qos.logback.classic.sift.SiftingAppender">
<!-- This is MDC value -->
<!-- We will assign a value to 'logFileName' via Java code -->
<discriminator>
<key>logFolder</key>
<defaultValue>main</defaultValue>
</discriminator>
<sift>
<appender name="FILE-${logFileFolder}" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}/${logFolder}/enquiryengine.log</file>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<!-- <file>${LOG_FILE}</file> -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE}/${logFolder}/enquiryengine.log.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
<maxHistory>15</maxHistory>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
</sift>
</appender>
<springProfile name="development">
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE-THREAD" />
</root>
</springProfile>
<springProfile name="production">
<root level="INFO">
<appender-ref ref="FILE-THREAD" />
</root>
</springProfile>
<springProfile name="staging">
<root level="INFO">
<appender-ref ref="FILE-THREAD" />
</root>
</springProfile>
<springProfile name="testing3">
<root level="INFO">
<appender-ref ref="FILE-THREAD" />
</root>
</springProfile>
<springProfile name="testing">
<root level="INFO">
<appender-ref ref="FILE-THREAD" />
</root>
</springProfile>
<springProfile name="testing2">
<root level="INFO">
<appender-ref ref="FILE-THREAD" />
</root>
</springProfile>
<jmxConfigurator />
</configuration>
public class MyClass extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
MDC.put(UtilConstant.LOG_FOLDER_NAME, "dynamicTenantFolderName");
return true;
}
#Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
MDC.remove(UtilConstant.LOG_FOLDER_NAME);
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
MDC.remove(UtilConstant.LOG_FOLDER_NAME);
}
}
public class TenantRequestFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
MDC.remove(UtilConstant.LOG_FOLDER_NAME);
MDC.put(UtilConstant.LOG_FOLDER_NAME, "dynamicLogFolderName");
// Goes to default servlet
chain.doFilter(requestWrapper, response);
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
#Override
public void destroy() {
MDC.remove(UtilConstant.LOG_FOLDER_NAME);
}
}
As logs are not working so i will not get any stack trace, Expected Result is logs generation should not stop.
The default Timeout for Siftappender is 30 Minutes,
If no logs are written in 30mins then the siftappender gets timeout and no further logs on that MDC will be processed.
To overcome this,
1. You can increase the time limit as per the application's requirement
2. Have a scheduler to print log after particular interval, so that it never gets timeout
Refer Document: http://logback.qos.ch/manual/appenders.html
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!
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
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.