I have a problem with an old project: The log file doesn't append in the console view of Eclipse. Instead of declaring the properties of log4j uses in log4j.xml or log4j.properties, the logger is defined in java:
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
public class GCLogger {
private static GCLogger _self;
private Logger logger;
private static final String NAME_FILE = "fichierLog.log";
public static GCLogger getInstance() {
if (_self == null || _self.logger == null) {
GCLogger logger = new GCLogger();
logger.initLogger();
_self = logger;
}
return _self;
}
public void error(String msg, Exception e) {
if (logger != null) {
logger.error(msg, e);
}
}
public void debug(String msg) {
if (logger != null) {
logger.debug(msg);
}
}
private void initLogger() {
logger = Logger.getRootLogger();
FileAppender fa = new FileAppender();
PatternLayout monLayout = new PatternLayout("%d{DATE} - %5p %c{1} - %m%n");
logger.removeAllAppenders();
try {
File repLogs = new File(GCConstants.GC_REPERTOIRE_LOGS);
if (!repLogs.exists()) {
repLogs.mkdir();
}
fa = new FileAppender(monLayout, GCConstants.GC_REPERTOIRE_LOGS + File.separator + NAME_FILE, true);
fa.activateOptions();
fa.setImmediateFlush(true);
logger.addAppender(fa);
logger.setLevel(Level.ALL);
} catch(Exception e) {
logger = null;
}
}
}
Is there a simple way to show fichierLog.log in the console view (using eclipse configuration)?
If not, what is the minimal change to make it works?
Minimum change - add a console appender:
ConsoleAppender console = new ConsoleAppender(monLayout); // re-use the layout
logger.addAppender(console);
<opinion>
However, if you're making other changes to the codebase, I would strongly recommend changing this to use external configuration - it'll make your life much easier in the long (and probably short) term.</opinion>
Related
I have the following legacy class which used PropertyConfigurator under Log4J 1.x
There's no equivalent under Log4J 2.x but I am trying to preserve the functionality at method level.
The existing answers on Stack Overflow are for locating the configuration file, but the legacy code I have in loadConfiguration is setting properties inside the configuration file about where the actual log file will be output.
I wish to know what the equivalent would be under Log4J2. It's not clear to me how the
loadConfiguration method will change due to not having a PropertyConfigurator under log4j 2.x.
Thanks in advance.
Existing code:
public class BasicLogConfigurator {
public static final String LOG_LEVEL_KEY = "log.level.override";
private static final Level DEFAULT_LOG_LEVEL = Level.ERROR;
private static final String LOG4J_PROPS_LOCATION = "/log4j.properties";
private static final String LOG_FILE_PATTERN = "CustomLog_%s.log";
private static final Date TIMESTAMP = new Date();
private static final String METADATA_FOLDER = ".metadata";
public static void loadDefaultConfiguration() {
// 1. Grab the Log file location
File logLocation = getLogFileLocationInMetadataDirectory();
// 2. Grab default Log level
Level logLevel = DEFAULT_LOG_LEVEL;
loadConfiguration(logLocation, logLevel);
}
public static void loadConfiguration(File logLocation, Level logLevel) {
Properties properties = getConfigurationProperties();
// 1. Setup the Log file location
properties.setProperty("log4j.appender.FILE.file", logLocation.getAbsolutePath());
// 2. Setup the default Log level
properties.setProperty("log4j.rootLogger", String.format("%s, CONSOLE, FILE", sanitizeLogLevel(logLevel)));
LogManager.resetConfiguration();
PropertyConfigurator.configure(properties);
}
public static File getLogFileLocationInMetadataDirectory() {
String workspaceDirectory = getWorkspaceDirectory();
File metadataDirectory = new File(workspaceDirectory, METADATA_FOLDER);
File logLocation = getLogFileLocation(metadataDirectory);
return logLocation;
}
public static File getLogFileLocation(File directory) {
return new File(directory, String.format(LOG_FILE_PATTERN, formatTimeStamp(TIMESTAMP)));
}
private BasicLogConfigurator() {
// prevent instantiation
}
private static Level sanitizeLogLevel(Level selectedLevel) {
String overridingLevel = System.getProperty(LOG_LEVEL_KEY);
if (overridingLevel != null) {
return Level.toLevel(overridingLevel, Level.DEBUG);
}
if (selectedLevel != null) {
return selectedLevel;
}
return DEFAULT_LOG_LEVEL;
}
public static String getWorkspaceDirectory() {
return ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString();
}
private static String formatTimeStamp(Date date) {
return new SimpleDateFormat("yyyyMMdd").format(date).toString();
}
public static Properties getConfigurationProperties() {
try {
Properties properties = new Properties();
properties.load(BasicLogConfigurator.class.getResourceAsStream(LOG4J_PROPS_LOCATION));
return properties;
} catch (IOException e) {
throw new RuntimeException(
String.format("Error while loading {%s}", LOG4J_PROPS_LOCATION), e);
}
}
}
So how is this done for Log4J2 given the inputs of the loadConfiguration method? And does getConfigurationProperties need to change to work with Log4J2?
We moved our application from a own small logging component to Log4j2.
The application runs about 60.000 jobs per day at our biggest installation.
We write our own Appender which writes using Hibernate to our DB (see InnovaIntegrationsportalHibernateAppender).
After a runtime of ~36h the JVM crashed with Out of Memory Exception/Error(OOME), analysing the hprof i saw that there is a amount of 763,5MB of the class org.apache.logging.log4j.core.appender.AbstractManager
see screenshot of the Analyse attached (2019-04-12 13_20_45-eclips...)
https://issues.apache.org/jira/browse/LOG4J2-2589
Going deeper i tried to reconstruct the behavior in a test class and profiled its result (see screenshot-1).
Looks like a memory leak to me.
InnovaIntegrationsportalHibernateAppender
package de.itout.innova.log4j.innova_log4j_appender;
import de.itout.innova.ssp.entities.ssp.entities.*;
import de.itout.jpa.util.*;
import java.io.*;
import java.util.*;
import javax.persistence.*;
import org.apache.logging.log4j.core.*;
import org.apache.logging.log4j.core.appender.*;
import org.apache.logging.log4j.core.config.plugins.*;
import org.apache.logging.log4j.core.layout.*;
/**
*
* #author swendelmann
*/
#Plugin(name = "InnovaIntegrationsportalHibernateAppender", category = "Core", elementType = "appender")
public class InnovaIntegrationsportalHibernateAppender extends AbstractAppender
{
private String schnittstelle;
private String version;
private String laufId;
private EntityManager em;
public InnovaIntegrationsportalHibernateAppender(String name, Filter filter, Layout<? extends Serializable> layout)
{
super(name, filter, layout);
}
public InnovaIntegrationsportalHibernateAppender(String name, Filter filter, Layout<? extends Serializable> layout, boolean ignoreExceptions)
{
super(name, filter, layout, ignoreExceptions);
}
private InnovaIntegrationsportalHibernateAppender(String name, Filter filter, Layout<? extends Serializable> layout, boolean ignoreExceptions, String schnittstelle, String version, String laufId)
{
super(name, filter, layout, ignoreExceptions);
this.schnittstelle = schnittstelle;
this.version = version;
this.laufId = laufId;
}
// Your custom appender needs to declare a factory method
// annotated with `#PluginFactory`. Log4j will parse the configuration
// and call this factory method to construct an appender instance with
// the configured attributes.
#PluginFactory
public static InnovaIntegrationsportalHibernateAppender createAppender(
#PluginAttribute("name") String name,
#PluginElement("Layout") Layout<? extends Serializable> layout,
#PluginElement("Filter") final Filter filter,
#PluginAttribute("schnittstelle") String schnittstelle,
#PluginAttribute("version") String version,
#PluginAttribute("laufId") String laufId
)
{
if (name == null)
{
LOGGER.error("No name provided for InnovaIntegrationsportalHibernateAppender");
return null;
}
if (layout == null)
{
layout = PatternLayout.createDefaultLayout();
}
if (laufId == null || laufId.isEmpty())
{
LOGGER.error("No laufid provided for InnovaIntegrationsportalHibernateAppender");
}
return new InnovaIntegrationsportalHibernateAppender(name, filter, layout, true, schnittstelle, version, laufId);
}
#Override
public void append(LogEvent event)
{
try
{
em = JPAUtil.getEntityManager("SSP");
em.getTransaction().begin();
LauflogPK lauflogPK = new LauflogPK(schnittstelle, version, laufId, getNextLaufLogPos());
Lauflog lauflog = new Lauflog(lauflogPK);
lauflog.setLevel(event.getLevel().name());
Date eventDateTime = new Date(event.getTimeMillis());
lauflog.setLastchangeAenderungsdatum(eventDateTime);
lauflog.setLastchangeAenderungszeit(eventDateTime);
lauflog.setLastchangeBenutzer("WENDELMANN");
lauflog.setLastchangeLogflag('A');
lauflog.setText(event.getMessage().getFormattedMessage());
em.persist(lauflog);
em.getTransaction().commit();
}
catch (Throwable t)
{
em.getTransaction().rollback();
LOGGER.error("Cant commit to Database InnovaIntegrationsportalHibernateAppender ", t);
//TODO Log to file
}
finally
{
try
{
if (em != null)
{
em.close();
}
}
catch (Throwable t)
{
LOGGER.error("Cant close em: ", t);
}
}
}
/**
* SELECT ISNULL(MAX(POS)+1,0) FROM LAUFLOG
* #return
*/
private int getNextLaufLogPos()
{
Integer i = (Integer) em.createQuery("SELECT MAX(l.lauflogPK.pos)+1 FROM Lauflog l WHERE l.lauflogPK.schnittstelle = :schnittstelle AND l.lauflogPK.version = :version AND l.lauflogPK.lauf = :lauf ")
.setParameter("schnittstelle", this.schnittstelle)
.setParameter("version", this.version)
.setParameter("lauf", this.laufId)
.getSingleResult();
if (i == null)
{
return 0;
}
else
{
return i;
}
}
}
package de.itout.innova.log4j;
import de.itout.innova.log4j.innova_log4j_appender.*;
import de.itout.jpa.util.*;
import java.io.*;
import java.nio.charset.*;
import org.apache.logging.log4j.*;
import org.apache.logging.log4j.core.*;
import org.apache.logging.log4j.core.appender.*;
import org.apache.logging.log4j.core.config.*;
import org.apache.logging.log4j.core.layout.*;
import org.junit.*;
/**
*
* #author swendelmann
*/
public class ProfilingTest
{
QEntityManager em;
private org.apache.logging.log4j.Logger logg = LogManager.getLogger();
// Potential memory leak
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
public ProfilingTest()
{
}
#Before
public void setUp()
{
em = JPAUtil.getEntityManager("SSP");
}
#After
public void tearDown()
{
em.close();
}
#Test
public void testProfiling()
{
logg.trace("Start the Main Method");
int runs = 1000;
int logs = 10;
String allSicherungsVerzeichnis = "target/sicherungsverzeichnis/";
logg.debug("Start Test mit " + runs + " durchläufen");
for (int i = 0; i < runs; i++)
{
String laufid = "LD0" + i;
File laufLogFile = new File(allSicherungsVerzeichnis + laufid + "_full.log");
Configuration config = ctx.getConfiguration();
// Full File Logger
Layout layout = PatternLayout.newBuilder()
.withConfiguration(config)
.withPattern(PatternLayout.SIMPLE_CONVERSION_PATTERN)
.withCharset(Charset.forName("UTF-8"))
.build();
Appender fullAppender = FileAppender.newBuilder()
.setConfiguration(config)
.setName(laufid + "FULL")
.withFileName(laufLogFile.getAbsolutePath())
.withAppend(true)
.withImmediateFlush(true)
.setIgnoreExceptions(false)
.setLayout(layout)
.build();
fullAppender.start();
config.addAppender(fullAppender);
// Hibernate Logger
Appender appender = InnovaIntegrationsportalHibernateAppender.createAppender(laufid, null, null, "LISA_4711", "LI0001", laufid);
appender.start();
AppenderRef ref = AppenderRef.createAppenderRef(laufid, Level.ALL, null); // HIER LOGLEVEL DB EINSTELLEN
AppenderRef refFull = AppenderRef.createAppenderRef(laufid + "FULL", Level.ALL, null); // HIER LOGLEVEL Datei einstellen
AppenderRef[] refs = new AppenderRef[]
{
ref, refFull
};
LoggerConfig loggerConfig = LoggerConfig
.createLogger(false, Level.ALL, laufid, "true", refs, null, config, null);
loggerConfig.addAppender(appender, Level.ALL, null); // HIER LOGLEVEL ebenfalls einstellen
loggerConfig.addAppender(fullAppender, Level.ALL, null); // HIER LOGLEVEL Datei einstellen
config.addLogger(laufid, loggerConfig);
ctx.updateLoggers();
org.apache.logging.log4j.Logger log = LogManager.getLogger(laufid);
for (int j = 0; j < logs; j++)
{
log.info("Ich bin nur eine Info und soll nur in das FullFile logging!");
log.warn("Ich bin ein böser warning und soll in das FullFile und in das Innova Integrationsportal Hibernate Logging");
}
appender.stop();
fullAppender.stop();
config.removeLogger(laufid);
config.removeLogger(laufid + "FULL");
ctx.updateLoggers();
}
logg.trace("Fertig");
}
}
Update 02.05.2019
I moved to the JDBC logger and changed the DB.
The first test was about fine, but when i programatically add a fileappender + logger with ref to the fileappender & jdbc appender from xml config, i got empty files and no db entries.
I made up a test project on github see: https://github.com/stefanwendelmann/JavaLogging
I am looking at :
https://github.com/stefanwendelmann/JavaLogging/blob/master/src/test/java/LoggerTest.java
I think this is what is happening:
private static final LoggerContext ctx ...
Configuration config = ctx.getConfiguration();
config.addAppender(fullAppender);
and you never remove it, so it keeps adding in the static field. You can debug and see what is inside Log4j2. I haven't debugged yet.
Memory leaks are coming through static fields and through classloaders usually.
Best option is to move away from logging with jdbc. It is designed to work in another way and not to dynamically add/remove appenders, because you have to do all the zookeeping of objects. It may be easier for you to just make a facade pattern and hide the complexity there and only expose couple of methods for write in DB.
Probably, Hibernate keeps objects in its cache. Try evict them immediately after commit.
Trying to use java.util.logging and failing.
In an attempt to make use of https://stackoverflow.com/a/8249319/3322533 :
handlers = mypackage.logging.RequestFileHandler, mypackage.logging.MainFileHandler
config =
mainLogger.handlers = mypackage.logging.MainFileHandler
requestLogger.handlers = mypackage.logging.RequestFileHandler
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.filter =
java.util.logging.ConsoleHandler.formatter = mypackage.logging.VerySimpleFormatter
java.util.logging.ConsoleHandler.encoding =
mypackage.RequestFileHandler.level = SEVERE
mypackage.RequestFileHandler.filter =
mypackage.RequestFileHandler.formatter = mypackage.logging.VerySimpleFormatter
mypackage.RequestFileHandler.encoding =
mypackage.RequestFileHandler.limit =
mypackage.RequestFileHandler.count =
mypackage.RequestFileHandler.append = false
mypackage.RequestFileHandler.pattern = REQUESTS.%u.%g.log
mypackage.MainFileHandler.level = INFO
mypackage.MainFileHandler.filter =
mypackage.MainFileHandler.formatter = mypackage.logging.VerySimpleFormatter
mypackage.MainFileHandler.encoding =
mypackage.MainFileHandler.limit =
mypackage.MainFileHandler.count =
mypackage.MainFileHandler.append = false
mypackage.MainFileHandler.pattern = MAIN.%u.%g.log
where
public class MainFileHandler extends FileHandler {
public MainFileHandler() throws IOException, SecurityException {
super();
}
}
and
public class RequestFileHandler extends FileHandler {
public RequestFileHandler() throws IOException, SecurityException {
super();
}
}
Intention: provide two loggers accessible through
Logger.getLogger("mainLogger");
or
Logger.getLogger("requestLogger");
respectively, one that will write (exclusively) to MAIN[...].log and the other to REQUESTS[...].log
(No limits on the amount of messages that can be logged to either file and if necessary, use logging level to filter out unwanted msgs to either.)
However, neither file is created when I (for example)
public static final Logger log = Logger.getLogger("mainLogger");
and then
public void configureLogger(){
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream config = classLoader.getResourceAsStream("logging.properties");
LogManager.getLogManager().readConfiguration(config);
}catch(Exception ex){
throw new RuntimeException("logging properties failed");
}
}
before I
log.info("Hello World!")
I know the properties are loaded because when I include java.util.logging.ConsoleHandler in the handlers = ... list and use the global logger, instead, the formatter is applied for the console output.
So ... I guess my attempt at setting up the file loggers is faulty. How do I get this working?
EDIT
So I removed the [...].pattern = [...] lines and instead hardcoded the file names:
public class MainFileHandler extends FileHandler implements FileHandlerProperties {
public MainFileHandler() throws IOException, SecurityException {
super("MAIN_" + new SimpleDateFormat(TIME_PATTERN).format(new Date()) + ".log");
}
}
and
public class RequestFileHandler extends FileHandler implements FileHandlerProperties {
public RequestFileHandler() throws IOException, SecurityException {
super("REQUESTS_" + new SimpleDateFormat(TIME_PATTERN).format(new Date()) + ".log");
}
}
where
public interface FileHandlerProperties {
static final String TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
}
Both files now get created BUT they both contain exactly the same (despite their different level settings and loggers) AND what they contain is in xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
<date>2016-10-10T18:49:23</date>
<millis>1476118163654</millis>
<sequence>0</sequence>
<logger>mainLogger</logger>
<level>INFO</level>
<class>mypackage.main.Main</class>
<method><init></method>
<thread>1</thread>
<message>Hello World</message>
</record>
</log>
Please help ...
The problem is that the first call to Logger.getLogger during class loading reads the log configuration and your configureLogger method fails due to JDK-8033661: readConfiguration does not cleanly reinitialize the logging system.
To workaround this you have to ensure that configureLogger runs before the first call to Logger.getLogger.
public class BootMain {
static {
configureLogger();
mainLogger = Logger.getLogger("mainLogger");
requestLogger = Logger.getLogger("requestLogger");
}
private static final Logger mainLogger;
private static final Logger requestLogger;
public static void main(String[] args) throws IOException {
mainLogger.log(Level.SEVERE, "Test from main.");
requestLogger.log(Level.SEVERE, "Test from request.");
System.out.println(new File(".").getCanonicalPath());
}
private static void configureLogger() {
try {
InputStream config = config();
LogManager.getLogManager().readConfiguration(config);
} catch (Exception ex) {
throw new RuntimeException("logging properties failed");
}
}
private static String prefix() {
return "mypackage.logging";
}
private static InputStream config() throws IOException {
String p = prefix();
Properties props = new Properties();
props.put("mainLogger.handlers", p + ".MainFileHandler");
props.put("requestLogger.handlers", p + ".RequestFileHandler");
props.put(p + ".RequestFileHandler.level", "SEVERE");
props.put(p + ".MainFileHandler.level", "INFO");
props.put(p + ".RequestFileHandler.pattern", "REQUESTS.%u.%g.log");
props.put(p + ".MainFileHandler.pattern", "MAIN.%u.%g.log");
ByteArrayOutputStream out = new ByteArrayOutputStream();
props.store(out, "");
return new ByteArrayInputStream(out.toByteArray());
}
}
Also make sure you are not using a really old version of JDK or you can run into JDK-5089480: java.util.logging.FileHandler uses hardcoded classname when reading properties.
Otherwise you can use the LogManager config option to manually setup your configuration.
I have one query is that if I write a simple Java class and I want to see the logs that are executed at the behind, such that are executed at the backend by the JVM. I have log4j JAR with me. Could you please give me advice to how to achieve this?
I would to see the same logs that are generated in case of a WebApp, so I can reuse it for a Java App.
try looking at log4j api/demo here http://www.vaannila.com/log4j/log4j-tutorial/log4j-tutorial.html
you can generate log for any class and any application afaik using log4j , which needs not necessarily be a web app
Here is a very simple example that you should be able to adapt to what you are trying to achieve.
Step 1:Import log4j jar file in your project
Step 2:-Create a Log java file
public Log(Class className) {
logger = Logger.getLogger(className.getClass());
logger.getClass();
final String LOG_PROPERTIES_FILE_NAME = "log4j.properties";
props = loadLogFile(LOG_PROPERTIES_FILE_NAME, className);
//props =getPropsFile(LOG_PROPERTIES_FILE_NAME, className);
PropertyConfigurator.configure(props);
}
public static Properties loadLogFile(String propertyFile, Class className) {
//String filePath="";
try {
Properties ps = null;
ResourceBundle bundle = ResourceBundle
.getBundle("resource.DbProperties");
String logPath = bundle.getString("logs.path");
File filePath = new File(logPath);
if (!filePath.exists()) {
filePath.mkdirs();
}
props.clone();
props = getPropsFile(propertyFile, className);
props.setProperty("info_file_path", filePath.toString());
// PropertyConfigurator.configure(props);
} catch (Exception e) {
e.printStackTrace();
}
return props;
}
public void info(String message) {
logger.info(message);
}
public void warn(String message) {
logger.warn(message);
}
public void error(String message) {
logger.error(message);
}
public void fatal(String message) {
logger.fatal(message);
}
public void printStackTrace(Throwable ex) {
StringWriter sw = new StringWriter();
ex.printStackTrace(new PrintWriter(sw));
logger.error("\n" + sw.toString());
}
log4j.properties
log4j.rootCategory=LOGFILE
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=${info_file_path}\\info_Pension_application.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.Threshold=INFO
log4j.appender.LOGFILE.Threshold=DEBUG
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
If your "simple Java class" happens to be in a Java EE container (like a .jsp or servlet in Tomcat, JBoss or WebSphere), then all you need to do is:
1) import org.apache.log4j.Logger;
2) declare a static instance in your class:
EXAMPLE: `static Logger logger = Logger.getLogger ("MyApp");`
3) Use your logger
EXAMPLE: `logger.info ("something interesting happened");`
4) If you include log4j.java and your own log4j.properties in your CLASSPATH, then you don't need to do anything else.
Here's a bit more info on using log4j with Tomcat or app servers:
http://tomcat.apache.org/tomcat-5.5-doc/logging.html
http://logging.apache.org/log4j/1.2/manual.html
http://www.tutorialspoint.com/log4j/log4j_quick_guide.htm
Here's a very simple example program that "does logging", from the above tutorialspoint.com link:
import org.apache.log4j.Logger;
import java.io.*;
import java.sql.SQLException;
import java.util.*;
public class log4jExample{
/* Get actual class name to be printed on */
static Logger log = Logger.getLogger(
log4jExample.class.getName());
public static void main(String[] args)
throws IOException,SQLException{
log.debug("Hello this is an debug message");
log.info("Hello this is an info message");
}
}
I am using Log4j with Jboss EJB webservice. I am logging the application flow in the File.
This is the code I am using for logging
FileAppender fileappender;
File file = new File("jws_" + getCurrentDate("dd_MMM_yyyy") + ".log");
Logger log = null;
System.out.println(file.getAbsolutePath() );
try
{
log = Logger.getLogger(ConnMan.class);
fileappender = new FileAppender(new PatternLayout(),"f2cjws_" + getCurrentDate("dd_MMM_yyyy") + ".log");
log.addAppender(fileappender);
if (!theLogLevel.equalsIgnoreCase("error"))
{
if ("yes".equalsIgnoreCase(getProperties().getProperty("log")))
{
log.debug(getCurrentDate("dd MMM yyyy HH:mm:ss 1")+" "+theError);
}
}
else
{
log.debug(getCurrentDate("dd MMM yyyy HH:mm:ss 1")+" "+theError);
}
}
catch (IOException e)
{
System.out.println("Logger failed due to "+e.getMessage());
}
catch(Exception e)
{
System.out.println("Logger failed due to "+e.getMessage());
}
When I run the application, I am getting duplicate data in my file, i.e.., same data is written twice or thrice. The above code worked fine in webapplication deployed in tomcat.
So I feel I am missing something in related to JBoss.
This webservice now currently uses the log4j properties built in with the server. Can I know how to make it to use application's own properties file?
Please help me,
Thanks in advance,
You need to create your own log writer,
public final class LogWriter
{
private static Logger appLogger = null;
private static String className = LogWriter.class.getName() + ".";
static
{
try
{
appLogger = Logger.getLogger("Demologer");
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void logDebug(String message)
{
appLogger.log(className, Level.DEBUG, LogWriter.getMessage(message), null);
}
public static void logInfo(String message)
{
appLogger.log(className, Level.INFO, LogWriter.getMessage(message), null);
}
public static void logError(String message)
{
appLogger.log(className, Level.ERROR, LogWriter.getMessage(message), null);
}
private static String getMessage(String message)
{
String retValue;
Calendar cale = Calendar.getInstance();
Date now = cale.getTime();
//retValue=now.getDate()+"/"+(now.getMonth()+1)+"/"+(now.getYear()+1900)+" "+now.getHours()+":"+now.getMinutes()+":"+now.getSeconds();
retValue = now + "\n";
now = null;
cale = null;
return retValue + message;
}
}
You can use this one as you need.
If you have some thing like following in your log4j.properties you will see duplications in output:
log4j.rootLogger=error, myappender
log4j.logger.com.sample=warn, myappender
log4j.logger.com.sample.deeper.package=all, myappender
correct it to:
log4j.rootLogger=error, myappender
log4j.logger.com.sample=warn
log4j.logger.com.sample.deeper.package=all
Edit:
Following will write fatal and error level logs from every classes, fatal, error and warning level logs from com.sample.* classes and every logs from com.sample.deeper.package.* classes to /var/log/myappender/myappender.log file.
Save as log4j.properties in you root package:
# This appender is not used in this example.
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c - %m%n
# But this one is used.
log4j.appender.myappender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.myappender.DatePattern='.'yyyy-MM-dd
log4j.appender.myappender.File=/var/log/myappender/myappender.log
log4j.appender.myappender.layout=org.apache.log4j.PatternLayout
log4j.appender.myappender.layout.ConversionPattern=%d{ABSOLUTE} %5p %c - %m%n
log4j.appender.myappender.Encoding=UTF-8
log4j.rootLogger=error, myappender
log4j.logger.com.sample=warn
log4j.logger.com.sample.deeper.package=all
In your every classes you need a logger:
private static Logger logger = Logger.getLogger(ThisClassName.class);
And you don't need the snippet code you have in you question any more.