Hi,
Could you please help me on migrating from log4j to logback. I am using a
layout and appender.
What I was trying to do is create a different log file for each thread.
I really appreciate any help from anyone.
Thank you so much in advance.
Below is my codes:
Log4j version of the layout:
package com.selenium.reporting;
import java.io.*;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;
import org.apache.commons.lang3.StringEscapeUtils;
public class ReportNGTestLayout extends PatternLayout {
public ConcurrentHashMap<String, String> threadTestName = new
ConcurrentHashMap<String, String>();
public int consoleLevel = Level.DEBUG_INT;
public String reportParentFolder = "test-output";
public String executionDate;
@Override
public String format(LoggingEvent event) {
String logline = "";
String logFileName;
String logPrefix;
String consolePrefix;
// Get test name by thread id
String testName =
threadTestName.get(Long.toString(Thread.currentThread().getId()));
String curThreadName = Thread.currentThread().getName();
if (testName == null) {
// log to a file by thread name, if no test
name
consolePrefix = logPrefix = " " +
curThreadName + " : ";
logFileName = Paths.get(reportParentFolder,
"main.log").toString();
} else {
// log to <test name>.log file
logFileName = Paths.get(reportParentFolder,
"DetailReport", "Attachments", testName + ".log").toString();
logPrefix = " : ";
if (!curThreadName.contains("pool") &&
!curThreadName.equalsIgnoreCase("TestNG"))
logPrefix = logPrefix + "[" +
curThreadName + "] ";
consolePrefix = testName + logPrefix;
}
// Console output
if (event.getLevel().toInt() >= consoleLevel) {
if (event.getLevel().toInt() > consoleLevel)
consolePrefix +=
event.getLevel() + " : ";
String consoleMessage = new
SimpleDateFormat("HH:mm:ss.SSS ").format(new Date(event.timeStamp))
+ consolePrefix +
event.getMessage();
if (event.getLevel().toInt() >=
Level.INFO_INT)
consoleMessage = "\n" +
consoleMessage;
System.out.println(consoleMessage);
}
if (!reportParentFolder.isEmpty()){
// Create log file if needed
File logFile = new File(logFileName);
if (!logFile.exists()){
try {
File parentFolder =
new File(logFile.getParent());
parentFolder.mkdirs();
logFile.createNewFile();
} catch (IOException e) {
// TODO
Auto-generated catch block
e.printStackTrace();
}
}
// Append to log file
try(PrintWriter out = new PrintWriter(new
BufferedWriter(new FileWriter(logFile, true)))) {
out.println(new
SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
.format(new Date(event.timeStamp)) +
" [" +
event.getLevel() + "]" +
logPrefix +
event.getMessage());
} catch (IOException e) {
e.printStackTrace();
}
}
// Append to old report if INFO message
if (event.getLevel().toInt() == Level.INFO_INT) {
String newMsg =
StringEscapeUtils.escapeHtml3(event.getMessage()
.toString());
Throwable t = null;
ThrowableInformation ti =
event.getThrowableInformation();
if (ti != null) {
t = ti.getThrowable();
}
LoggingEvent encodedEvent = new
LoggingEvent(
event.fqnOfCategoryClass, Logger.getLogger(event
.getLoggerName()), event.timeStamp,
event.getLevel(),
newMsg, t);
String baseFmt =
super.format(encodedEvent).replace("@{{", "<")
.replace("@}}",
">");
logline = "<div class=step" +
"event.level.toString()" + ">"
+ baseFmt +
"</div><br/>";
}
return logline;
}
}
Logback version of the layout:
It is the same as the Log4j version but the only difference is I am extending
ch.qos.logback.classic.PatternLayout and I use ILoggingEvent in the format
instead of LoggingEvent.
//@Override
public String format(ILoggingEvent event) {
Log4j version of the appender:
package com.selenium.reporting;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
import org.testng.Reporter;
public class TestNGAppender extends AppenderSkeleton {
public TestNGAppender(String name) {
super();
setName(name);
}
@Override
protected void append(LoggingEvent event) {
String logMessage = layout.format(event);
if (!logMessage.isEmpty()) {
Reporter.log(logMessage);
String[] thorwableCrap =
event.getThrowableStrRep();
if (thorwableCrap != null) {
Reporter.log(thorwableCrap.toString());
}
}
}
@Override
public void close() {
}
@Override
public boolean requiresLayout() {
return true;
}
}
Logback version of the appender:
package com.selenium.reporting;
import org.testng.Reporter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
public class TestNGAppender extends AppenderBase<ILoggingEvent> {
public TestNGAppender(String name) {
super();
setName(name);
}
//@Override
protected void append(ILoggingEvent event) {
String logMessage = this.layout.format(event); ===> in
here layout cannot be resolved. How can I access the format method in the
ReportNGTestLayout class?
if (!logMessage.isEmpty()) {
Reporter.log(logMessage);
}
}
@Override
public void stop() {
}
/* @Override
public boolean requiresLayout() {
return true;
}*/
}
This is how I setup the appender and layout in the logger:
Logger rootLogger = (Logger)LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
TestNGAppender testNGAppender = new TestNGAppender("TestNG");
ReportNGTestLayout logLayout = new ReportNGTestLayout();
logLayout.executionDate = new
SimpleDateFormat("MM-dd-yyyy-HH-mm").format(new Date());
logLayout.reportParentFolder =
Paths.get(System.getProperty("reportRootPath"),
logLayout.executionDate).toString();
logLayout.consoleLevel = Level.toLevel(logLevel.toUpperCase(),
Level.DEBUG).toInt();
testNGAppender.setLayout(logLayout); ==> I am also having an error on
this line. The method setLayout(ReportNGTestLayout) is undefined for the type
TestNGAppender
testNGAppender.start();
rootLogger.addAppender(testNGAppender);
logger.debug("Log4j appender configuration is successful !!");
----------------------------
This message (including any attachments) contains confidential information
intended for a specific individual and purpose, and is protected by law. If you
are not the intended recipient of this e-mail (even if the e-mail address above
is yours), (i) you may not use, copy or retransmit it, (ii) please delete this
message and (iii) please notify the sender immediately. Any disclosure,
copying, or distribution of this message or the taking of any action based on
it, is strictly prohibited.
----------------------------
----------------------------
This message (including any attachments) contains confidential information
intended for a specific individual and purpose, and is protected by law. If you
are not the intended recipient of this e-mail (even if the e-mail address above
is yours), (i) you may not use, copy or retransmit it, (ii) please delete this
message and (iii) please notify the sender immediately. Any disclosure,
copying, or distribution of this message or the taking of any action based on
it, is strictly prohibited.
----------------------------
_______________________________________________
logback-user mailing list
[email protected]
http://mailman.qos.ch/mailman/listinfo/logback-user