I've a custom log4j layout class that extends PatternLayout, my layout class simply masks the password in the log. It works in a simple console app. Here's the log4j.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="A1" class="org.apache.log4j.ConsoleAppender">
<layout class="com.PortalLog4jFilteringPattern"> <param name="ConversionPattern" value="%t %-5p %c{2} - %m%n"/> </layout>
</appender>
<root>
<priority value ="DEBUG" /> <appender-ref ref="A1" />
</root>
</log4j:configuration>
Here's a snipet of the layout class:
public class PortalLog4jFilteringPattern extends PatternLayout {
// omitted
#Override
public String format(LoggingEvent event) {
System.out.println("in format()...... ");
// rest omitted
Here's the calling code:
import org.apache.log4j.Logger;
public class ProductDemo {
private static Logger logger = Logger.getLogger(ProductDemo.class);
public ProductDemo() {
}
public void processOrder(CustomerOrder order) {
logger.info(order.getProductName());
}
// rest ommited
A sample result log with pswd being masked:
main INFO test.ProductDemo - "password":"*****"},
But once I moved the custom layout class to my webapp (log4j.xml is exactly the same.), it doesn't get called (i.e., no System.out output) and the pswd is still being shown. I'm running the webapp locally with maven on Jetty using this cmd: mvn jetty:run
Here's the calling code:
// original code, but I changed it to import org.apache.log4j.Logger for experiment
//import org.slf4j.LoggerFactory;
//import org.slf4j.Logger;
import org.apache.log4j.Logger;
public class BlahBlahClass extends Blah
// things omitted
private final static Logger log = Logger.getLogger( BlahBlahClass .class );
Any idea? thanks
In a Java EE server environment I would say: it's a class loader issue. Jetty is a servlet container, so it's class loading architecture is simpler; still, it's worth checking. If your log4j is not deployed within the WAR, but comes from the Jetty class path, this is almost certainly the cause.
Try changing the class loading strategy to "parent last", as described in the Jetty manual, see if it helps.
You should import package name of your class in log4j. I added to log4j2.xml as below:
<Configuration packages="package path of your class">
Related
I am trying to rotate my gc.log file every time my application starts up.
I am using this file appender in my logback.xml file.
...
<appender name="GCFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.directory}/gc.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.directory}/gc.log.%d{yyyyMMdd}_%d{HHmmss,aux}.gz</fileNamePattern>
<TimeBasedFileNamingAndTriggeringPolicy class="com.ga.omni.utility.StartupTriggeringPolicy" />
<maxHistory>50</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
...
<root level="INFO">
<appender-ref ref="FILE" />
<appender-ref ref="GCFILE" />
</root>
(the "FILE" ref is a reference to our default logging file for the app.)
The appender references a TimeBasedFileNamingAndTriggeringPolicy named StartupTriggeringPolicy:
#NoAutoStart //won't be autostarted by Joran at config time
public class StartupTriggeringPolicy<E> extends DefaultTimeBasedFileNamingAndTriggeringPolicy<E> {
Logger log = LoggerFactory.getLogger(StartupTriggeringPolicy.class);
public StartupTriggeringPolicy() {
log.info("StartupTriggeringPolicy constructor called");
}
#Override
public void start() {
log.info("StartupTriggeringPolicy start() called... initialting gc.log rollover");
super.start();
//only check this once, on startup.
nextCheck = 0L;
isTriggeringEvent(null, null);
try {
tbrp.rollover();
log.info("StartupTriggeringPolicy start() called... gc.log successfully rolled over.");
} catch (RolloverFailure e) {
log.warn("Error rolling over gc.log file in StartupTriggeringPolicy.start()");
//Do nothing
}
}
}
The trouble that I'm facing is that the app starts up, but the StartupTriggeringPolicy never seems to get instantiated. None of the logs from the constructor or start() method are written, and if I put breakpoints in those methods, the breakpoints don't get hit.
Any suggestions would be greatly apperciated!
Environment:
Java, Selenium webdriver, Maven, testNG, Log4J, Eclipse
XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="TestAll" parallel = "tests" thread-count = "2">
<test name="postivelogintest_IE">
<parameter name="browser" value="ie"/>
<classes>
<class name="com.dice.LoginTest">
<methods>
<include name="DataDrivenpositiveLoginTest"/>
</methods>
</class>
</classes>
</test>
<test name="postivelogintest_CH">
<parameter name="browser" value="ch"/>
<classes>
<class name="com.dice.LoginTest">
<methods>
<include name="DataDrivenpositiveLoginTest"/>
</methods>
</class>
</classes>
</test>
</suite>
BaseTest.java
package com.diceBase;
import org.apache.log4j.Logger;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;
public class BaseTest {
protected WebDriver driver;
protected Logger log;
#Parameters ({"browser"})
#BeforeMethod
protected void MethodSetup(String browser){
log.info("method set up"); // line 16
driver = BrowserFactory.getDriver(browser);
}
#AfterMethod
protected void TearDown(){
log.info("method tear down");
try {
Thread.sleep(5000);
driver.quit();
} catch (Exception e) {
}
}
}
I added log4j.properties under src/main/resources.
In the BaseTest.java, I added two lines after importing log4j.
log.info("method set up");
log.info("method tear down");
iMy goal is to be able to use log.info entire project. Before that, I would like to test it by only importing log4j logger in basetest class to see if it works. If it works then I can import log4j in entire project.
I get error if I keep both log messages. But, If I remove both log messages, script passes. How can I print the logs using log4j?
The log variable in your BaseTest.java has not assigned with object of logger class (https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Logger.html) . Since No object is assigned to the variable log, it throws NULL pointer exception. So please create object of logger class to varaiable log
I have a lot of selenium tests that create a logger per class, it might not be the best way but it's code written by somebody else and I dont have time to rewrite it. I would like each Test of have it's own logfile so that it's easier to see what went wrong.
Is there a way to have log4j create a file for each logger that is created?
Yes, you can do this with log4j1 but I believe the only way is through programmatically adding the file appender to the logger.
Here is some sample code:
package test;
import org.apache.log4j.Appender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
public class Main {
private static final Logger logger = Logger.getLogger(Main.class);
private static final Logger logFoo = Logger.getLogger("test.Foo");
private static final Logger logBar = Logger.getLogger("test.Bar");
public static void main(String[] args) {
logger.addAppender(createFileAppender("logs/main.log"));
logFoo.addAppender(createFileAppender("logs/foo.log"));
logBar.addAppender(createFileAppender("logs/bar.log"));
logger.info("This is the main logger");
logFoo.info("this is the foo logger");
logBar.info("This is the bar logger");
}
private static Appender createFileAppender(String logName) {
FileAppender fa = new FileAppender();
fa.setName("FileLogger");
fa.setFile(logName);
fa.setLayout(new PatternLayout("%d %-5p [%c{1}] %m%n"));
fa.setThreshold(Level.DEBUG);
fa.setAppend(true);
fa.activateOptions();
return fa;
}
}
Here is a sample log4j.xml config file:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c{1}] %m %n" />
</layout>
</appender>
<logger name="test" additivity="false">
<level value="DEBUG" />
<appender-ref ref="consoleAppender" />
</logger>
</log4j:configuration>
Note that you probably don't need to specify the console appender, I did it just to make sure things were working. You may not even need to specify any loggers, but I didn't test with that configuration.
The output of the above is 3 log files each containing the one message that was provided to the corresponding logger, and console output of all log messages.
I'm an inexperienced Java developer writing an application that is handling a backup.
My application opens a gui (StepTwoBackup written using NetBeans Template), which gathers some information from the user, then when I press on the "Next" button, the gui passes these information to an object (BackupRestore which is logging all the operation using Log4J), and then opens another window (StepThreeBackup) and passes the object to it.
In this new window(StepThreeBackup), I automatically launch a method on the object passed (BackupRestore.execute()) which performs the backup.
In this last window (StepThreeBackup) I created a JTextArea where I would like to show the output of the Log4J (which currently writes to a log file and outputs to console).
Is there a way to do this? I've read that I should use an appender, but cannot figure out how to do this correctly.
For the time being I've created the following entry in my working Log4J property file:
<appender name="guiAppender" class="BackupAppGui.StatusMessageAppender">
<param name="Threshold" value="INFO" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{dd MMM yyyy HH:mm:ss} %5p %c{1} - %m%n"/>
</layout>
</appender>
Then the following Class in my Package (following another post):
package BackupAppGui;
/**
*
* #author MSTPA
*/
import javax.swing.JTextArea;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Level;
import org.apache.log4j.spi.LoggingEvent;
public class StatusMessageAppender extends AppenderSkeleton {
private final JTextArea jTextA;
public StatusMessageAppender() {
jTextA = StepThreeBackup.getJTextA();
}
protected void append(LoggingEvent event)
{
if(event.getLevel().equals(Level.INFO)){
jTextA.append(event.getMessage().toString());
}
}
public void close()
{
}
public boolean requiresLayout()
{
return false;
}
}
But nothing is written to the jTextArea.
What am I doing wrong? Can someone help me solving this? Thank you for all the help you can give me.
You need to make sure that the instance of JTextArea is not null. Yoy can try adding the appender programmatically (e.g. in the constructor of StepThreeBackup after create the components):
StatusMessageAppender appender = new StatusMessageAppender();
LogManager.getRootLogger().addAppender(appender);
Don't forget delete the entry in the log4j.xml file.
I use Log4j to write some log my program.
I find and read many question and answer in this site, but i can't solve my problem.
Here my code:
1. log4j.xml
<appender name="rollingfileAppender" class="org.apache.log4j.DailyRollingFileAppender">
<param name="append" value="true"/>
<param name="file" value="logs/process.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd-HH"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss:SSS} %-5p [%c{1}] %m%n"/>
</layout>
</appender>
<root>
<level value="DEBUG"/>
<appender-ref ref="rollingfileAppender"/>
<appender-ref ref="stdout"/>
</root>
2. My java code
package TestPacket;
import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
public class TestLog4jXML {
static Logger logger = org.apache.log4j.Logger.getLogger(TestLog4jXML.class.getName());
public TestLog4jXML() {
}
public static void main(String[] args) {
try {
DOMConfigurator.configure("log4j1.xml");
logger.trace("Entering application.");
logger.debug("Debug");
logger.info("info");
logger.warn("warn");
logger.error("error");
logger.fatal("fatal");
lungtng();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void lungtng()
{
logger.fatal("some text here");
logger.info("hello picaso");
}
}
And i run my program, with eclipse, windows os.
But the log file name only: process.log not in daily format: process.log.yyyy-MM-dd-HH
Who can explain this to me?
It appears that if you're running windows this is a known bug:
see here: http://do.whileloop.org/2014/02/14/log4j-rolling-file-appenders-in-windows/
See here: https://issues.apache.org/bugzilla/show_bug.cgi?id=29726
And also here: http://www.coderanch.com/t/424837/java/java/Log-log-file-rolled-day
The solutions seems to be to use the extras here:
http://logging.apache.org/log4j/extras/
Try using this appender with the correct policies defined:
http://logging.apache.org/log4j/extras/apidocs/org/apache/log4j/rolling/RollingFileAppender.html
The org.apache.log4j.DailyRollingFileAppender will create new log file for each day, each hour or each minute but file name of the current log always will be in the format that you've specified in the "file" parameter. In your example it's "process.log". The file names of the logs for the previous hours will be in format "process.log.yyyy-MM-dd-HH".