I'm very new to log back and want to try using it in my app. I tried to configure it as follows:
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/file/log.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>/rotated/log.log.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- keep 30 days' worth of history capped at 3GB total size -->
<maxHistory>30</maxHistory>
<totalSizeCap>16GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
When I write a simple application I have a problem that stacktraces of uncaught exceptions are not get logged:
public static void main(String[] args){
logger.info("Test")
logger.error("TEST!")
throw new IllegalArgumentException("Exception")
}
And what I have in the log file is:
16:57:05.905 [main] INFO com.App - Test
16:57:05.907 [main] ERROR com.App - TEST!
How to configure logging stacktraces of uncaught exceptions?
I don't think that you can log uncaught exceptions outside your main() method at all. But what you CAN do is to use a "catch all" block in your main method:
public static void main(String[] args){
try
{
logger.info("Test");
logger.error("TEST!");
someMethodThatPropablyThrowsAnException();
throw new IllegalArgumentException("Exception");
}
catch (Exception exception)
{
logger.error(exception);
}
}
This should log any exception thrown in your code that was not handled yet.
Related
Problem Statement: Logback is printing in console properly but not in log.txt file. There are many solutions given in other pages but apparently none worked. Could someone help me in this regard?
Java:-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Log {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger("Example App");
logger.info("'sup? I'm your info logger");
logger.debug("hey HEY hey! I'm your debug logger");
}
}
Config:- logback-fileAppender.xml
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${project.basedir}/Log.txt</file>
<append>true</append>
<!-- set immediateFlush to false for much higher logging throughput -->
<immediateFlush>true</immediateFlush>
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="FILE" />
</root>
</configuration>
Expected:- The logs should be printed in log.txt
Actual:- The logs is not printed in log.txt
Note: I am using my customized directory structure in maven not the default provided by maven "src/main/resources".
I am using slf4j and logback for logging in my java web application. I need the info logs from a specific class (MyClass in the example below) to be sent in an email. I configured an email appender in logback. The rest of it can go wherever the root logger is set to. But the email doesn't go out with my current set up. See below...
Set Up:
Here's the relevant information about jar versions and other setup for this:
jars in the classpath:
activation-1.1.jar
jcl-over-slf4j-1.7.25.jar
logback-classic-1.2.3.jar
logback-core-1.2.3.jar
logback-ext-spring-0.1.4.jar
logstash-logback-encoder-4.11.jar
mail-1.4.jar
slf4j-api-1.7.25.jar
logback.xml from classpath:
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d [%thread] %-5level %logger{5}:%L - %msg%n</pattern>
</encoder>
</appender>
<appender name="email" class="ch.qos.logback.classic.net.SMTPAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
<smtpHost>smtp.server</smtpHost>
<to>code4kix#email.com</to>
<from>do-not-reply#email.com</from>
<subject>code4kix - ${HOSTNAME}: %logger{20} - %m</subject>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d [%thread] %-5level %logger{5}:%L - %msg%n</pattern>
</layout>
<!-- <STARTTLS>true</STARTTLS> -->
<!-- <cyclicBufferTracker class="ch.qos.logback.core.spi.CyclicBufferTracker"> -->
<!-- <bufferSize>1</bufferSize> -->
<!-- </cyclicBufferTracker> -->
<!-- <asynchronousSending>false</asynchronousSending> -->
</appender>
<root level="error">
<appender-ref ref="console" />
</root>
<logger name="mypackage.MyClass" level="info" additivity="true">
<appender-ref ref="email"/>
</logger>
The Issue:
The email seems to go out fine if I have logger.error statements in MyClass.java, but if they have just logger.info, the email doesn't go out... despite configuring the threshold to info!
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyClass
{
private static Logger logger = LoggerFactory.getLogger(MyClass.class);
public void myMethod()
{
logger.error("using this sends the email out");
logger.info("using this doesn't");
}
}
I do get this in the console log, but the email never goes out. What could possibly be wrong?
SystemOut O 13:18:00,012 |-INFO in ch.qos.logback.classic.net.SMTPAppender[email] - SMTPAppender [email] is tracking [1] buffers
From my recent reading of the logback it sounds as though only under ERROR will an email be sent out. Chapter 4: Appenders
Thanks to Elijah for pointing me in the right direction. As mentioned in the documentation in SMTP Appender:
by default, the email transmission is triggered by a logging event of
level ERROR
There are multiple ways to solve this. The simplest way for me was to implement my own EventEvaluator like so, and use it in the smtp appender config (shown further below). Alternatively, you can explore using Markers to solve this issue.
public class OnInfoEvaluator extends EventEvaluatorBase<ILoggingEvent> {
#Override
public boolean evaluate(ILoggingEvent loggingEvent) throws NullPointerException, EvaluationException {
if(loggingEvent.getLevel().toInt() >= Level.INFO_INT)
{
return true;
}
else
{
return false;
}
}
}
In the config:
<appender name="email" class="ch.qos.logback.classic.net.SMTPAppender">
<evaluator class="mypackage.OnInfoEvaluator" />
...
</appender>
I am using Logback in my Selenium Webdriver project and I've reached a bit of a roadblock. I've search online but not been able to find the answer.
I am trying to find a way which allows me to get the testcase name (testGoogleWebsite) once inside the setup() method. So instead of just printing "Starting test" it prints out "Starting test - testGoogleWebsite"
I know I can do LOG.debug("testGoogleWebsite"); on the first line of each test, but wanted to know if there's a better way.
My Test:
#Test
public void testGoogleWebsite() {
openGoogleWebsite();
searchForStackOverflow();
clickOnStackOverflowLink();
}
#BeforeTest
public void setup() throws FileNotFoundException {
LOG.debug("Starting test - ");
driver = new ChromeDriver();
}
#AfterTest
public void tearDown(){
LOG.debug("End of test");
}
My logback file:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="DEV_HOME" value="target/Logs" />
<appender name="FILE-AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${DEV_HOME}/debug.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>${DEV_HOME}/archived/debug.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<logger name="com.test" level="debug" additivity="false">
<appender-ref ref="FILE-AUDIT" />
</logger>
<root level="debug">
<appender-ref ref="FILE-AUDIT" />
</root>
</configuration>
I think you are talking about logging your testacse name (as testGoogleWebsite is a testcase name I see). To do this you can put your LOG.debug("Starting test - "); in beforeMethod.
Code snippet
#BeforeMethod
public void beforeMethod(Method method) {
LOG.debug("Starting test - " + method.getName(););
}
This will log your each and every testcase name as you wanted.
my problem is : My application maintains three buildings, and each building has a different process.
So, using logback, I want to create a log which has a specification :
each building will have a specific folder, and inside that specific folder of each building, there will be many log files, with each log file indicates a process.
My logback.xml right now is :
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<appender name="logAppender" class="ch.qos.logback.classic.sift.SiftingAppender">
<discriminator>
<key>processName</key>
<defaultValue>unknown</defaultValue>
</discriminator>
<sift>
<appender name="FILE-${processName}"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/${distributor}/${processName}.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d [%thread] %level %mdc %logger{35} - %msg%n</pattern>
</layout>
<rollingPolicy
class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>logs/${distributor}/${processName}.%i.log</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>10</maxIndex>
<!-- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>5KB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> -->
</rollingPolicy>
<triggeringPolicy
class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>10MB</maxFileSize>
</triggeringPolicy>
</appender>
</sift>
</appender>
<logger name="processLog" level="debug" additivity="false">
<appender-ref ref="logAppender" />
<appender-ref ref="stdout" />
</logger>
<root level="debug">
<appender-ref ref="stdout" />
<appender-ref ref="logAppender" />
</root>
</configuration>
And my java servlet code is :
public class DistributorServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static Logger processLog = LoggerFactory.getLogger("processLog");
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String office = req.getParameter("office");
MDC.put("distributor", office);
String process = req.getParameter("process");
MDC.put("process", process);
processLog.debug("Processing");
}
}
However, a log file is not generated.
Can anyone help me?
Thank you very much
1. Make the below change
private static Logger processLog = LoggerFactory.getLogger("processLog");
to
private static Logger processLog = LoggerFactory.getLogger(DistributorServlet .class);
2. Add additional discriminator for distributor
From the logback.xml it appears that only one discriminator has been added. Did you try adding another one for distributor
3. Do not forget
To add MDC.remove("keyName"); after its usage.
4. In case if you observe issue with multiple MDC keys
I faced an issue with the MDC.put in trying to add multiple keys into it. (I wondered why no putAll has been defined)
Although the underlying implementation is that of a HashMap<Key k, Value v> that should allow adding multiple keys, I was only able to see that the last key you put into MDC would be applied to logback.xml
While for the other keys I observed _IS_UNDEFINED value that gets appended instead.
Of course then again you can refer to the other various links and although this may not be a best idea, here is what I have done in my Java code,
System.setProperty("distributor", req.getParameter("office"));
System.setProperty("process", req.getParameter("process"));
Modify the logback.xml by removing discriminator. Well, alternatively you can remove one of the above properties and have the MDC.put for that property.
However please do refer to the links System.setProperty is safe in java?
Alternatively I suggest https://stackoverflow.com/a/32615172/3838328
i use slf4j+logback
Here is logback.xml with 3 appenders (1 - console, 2 different files)
`
<configuration>
<property name="LOG_HOME" value="D:/logs" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</layout>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- <file>D:/logs/all/all_log.txt</file>-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>${LOG_HOME}/all/all_log.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- keep 30 days' worth of history -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<append>true</append>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<appender name="CONNECT_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--<file>D:/logs/connect/connect_log.txt</file>-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>${LOG_HOME}/connect/connect_log.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- keep 30 days' worth of history -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<append>true</append>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<!--<logger name="connect" level="info" additivity="false">
<appender-ref ref="CONNECT_FILE"/>
</logger>-->
<logger name = "com" level="info">
<appender-ref ref="FILE"/>
</logger>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
`
and simple class:
package com.gitHub.xMIFx.Servlets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by bukatinvv on 25.05.2015.
*/
#WebServlet("/main.do")
public class MainController extends HttpServlet{
private static final String PAGE_OK = "pages/main.jsp";
private static final Logger lOGGER = LoggerFactory.getLogger(MainController.class.getName());
private static final Logger CONNECT_FILE_lOGGER = LoggerFactory.getLogger("connect");
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp){
req.setAttribute("User","Vlad");
try {
lOGGER.info("logger: forwarding");
CONNECT_FILE_lOGGER.info("Connect-logger: forwarding");
// if(true){throw new IOException("blad");}
req.getRequestDispatcher(PAGE_OK).forward(req,resp);
} catch (ServletException e) {
lOGGER.error("Exception", e);
} catch (IOException e) {
lOGGER.error("Exception", e);
}
}
}
lOGGER & CONNECT_FILE_lOGGER write info in the same file, so they are the same loggers.
Why when we calling LoggerFactory.getLogger("connect"); we get logger with name "com", even when logger with name "connect" is not commented.
I try this, but had the same situation.
logs from file all_log.2015-05-28.log:
4968 [http-nio-8081-exec-5] INFO c.g.xMIFx.Servlets.MainController - logger: forwarding
4968 [http-nio-8081-exec-5] INFO connect - Connect-logger: forwarding
Interestingly, logback will create a logger even if you have no logger declared with the name you pass to LoggerFactory. Therefore:
When 'connect' was commented out CONNECT_FILE_lOGGER was a ROOT child logger which also logged to the console.
By uncommenting 'connect' you created a logger which appended to the desired file. As the additivity flag is false, any message logged to it is not propagated to its parents.
Sorry, I don't know what was that. But when I added additivity="false" to the logger with name "com" it works. Then I returned it back and uncommented "connect" - now it all works fine.