GAUTAM
asked on
Using Log4j across classes
Hi Experts...
I use looging from log4j in my java programs.
I get the logger using the below command:
static Logger logger = Logger.getLogger(TestLoggi ng.class.g etName());
How do i have a common logger for say more than one java class.
Please help...
I use looging from log4j in my java programs.
I get the logger using the below command:
static Logger logger = Logger.getLogger(TestLoggi
How do i have a common logger for say more than one java class.
Please help...
What do you exactly mean, When I use log4J I always define a new logger, de "default" log4j will get the class and writes the log were ever you configured it
Unless I want to have somecode logged to a special file, then I define other/second logger
static Logger logger = Logger.getLogger([i]classname[/i].class);
Unless I want to have somecode logged to a special file, then I define other/second logger
static Logger logger = Logger.getLogger("loggerToOtherFile");
Further they point out that it is often convenient and good organization to name by class
but it is not necessary, do you can invoke the same logger in different classes
and the logeger named by one clas can be clled and used in another calss
but it is not necessary, do you can invoke the same logger in different classes
and the logeger named by one clas can be clled and used in another calss
I think tyhis is a good explanation of all options
from
http://stackoverflow.com/questions/3038079/using-same-log4j-logger-in-standalone-java-application
(in particuylar option B applies directly to yourt question):
A) in Log4J, you have logger hierarchies, not a single logger. This typically boils down to one logger per class, where loggers are identified by classname. The logger is initialized like this:
private static final Logger logger = Logger.getLogger(MyClass.c
This is a good practice in that it allows you to fine-tune logging behaviour for modules (packages) or even individual classes within your app. So you may disable logging for some packages, log at INFO level in others, and log on DEBUG level for some critical classes e.g. when you want to catch a bug.
B) However, if you want a single logger everywhere, simply use the root logger in every class:
private static final Logger logger = Logger.getLogger();
C) for calls to not too complex methods, the performance difference is likely negligible, as the JIT compiler will agressively inline calls anyway. For complicated methods it is more of an open question.
Note that the method you show does unnecessary work by loading logger configuration - this is done automatically by Log4J if you name your config file log4j.properties and put it on the classpath. However, even if you need to use a nonstandard config file name, you could still load the Log4J configuration in a single place upon startup, and omit the lazy loading of the logger. Then what is left is
private static final Logger logger = Logger.getLogger(ExtractDa
private static Logger getLogger() {
return logger;
}
and this will surely be inlined by the compiler. You may want to retain getLogger nevertheless, to avoid modifying a lot of caller code.
Note that it is unnecessary for getLogger to be public, as all classes are supposed to have their own logger reference anyway.
ASKER
@for_yan:Thanks for the reply.
Considering the case B)
private static final Logger logger = Logger.getLogger();
returns an error stating: The method getLogger(String) in the type Logger is not applicable for the arguments ().
How do i solve this.
Please help...
Considering the case B)
private static final Logger logger = Logger.getLogger();
returns an error stating: The method getLogger(String) in the type Logger is not applicable for the arguments ().
How do i solve this.
Please help...
I assume they meant this method:
public static Logger getRootLogger()
public static Logger getRootLogger()
>>How do i have a common logger for say more than one java class.
Why would you want that actually? It's not usually a good way of organizing logging
Why would you want that actually? It's not usually a good way of organizing logging
ASKER
@for_yan:Thanks for replying.
I added the below method and it works fine.But i have to add this method in all the classes of the application.Or do i have an alternative.
@CEHJ:Thanks for the reply.
So how else can i improve this?Or what other option do i have?
Please help...
I added the below method and it works fine.But i have to add this method in all the classes of the application.Or do i have an alternative.
@CEHJ:Thanks for the reply.
So how else can i improve this?Or what other option do i have?
Please help...
ASKER
Code added in all classes
public static Logger getLogger() {
if (logger != null) return logger;
try {
PropertyConfigurator.configure("log4j.properties");
logger = Logger.getLogger(ClassName.class);
} catch (Exception exception) {
exception.printStackTrace();
}
return logger;
}
No, I think once you say in the your MainClass
static Logger mylogger = Logger.getRootLoger();
then everywher youjust use
MainClass.mylogger
as any static variable
static Logger mylogger = Logger.getRootLoger();
then everywher youjust use
MainClass.mylogger
as any static variable
>>
So how else can i improve this?Or what other option do i have?
Please help...
>>
Normally speaking, you want logging to be as granular as possible, so that the behaviour of individual classes can be observed in isolation from others. What you're asking for is the opposite. Nearly always you want the following
So how else can i improve this?Or what other option do i have?
Please help...
>>
Normally speaking, you want logging to be as granular as possible, so that the behaviour of individual classes can be observed in isolation from others. What you're asking for is the opposite. Nearly always you want the following
Logger logger = Logger.getLogger(TestLogging.class);
ASKER
@for_yan::Thanks for replying.
But is i do that i will not know the class in which any exception occurs since the logger was defined in the parent class.
I have my appender status as log4j.appender.A1.layout.C onversionP attern=%-4 r [%t] %-5p %c %x - %m%n and the class displayed is the main class in which it was defined as static and public and not the class in which exception occured.
Please help...
But is i do that i will not know the class in which any exception occurs since the logger was defined in the parent class.
I have my appender status as log4j.appender.A1.layout.C
Please help...
You still haven't said WHY you want a common logger...
but I guess you still can have printStackTrace with full information where exception occurred
@gaugeta
I do not recommend you use log4J in this manner. You can make use of the "Named Hierarchy" nature of log4J to archieve what you are trying to do.
Suppose you have 2 java classes.
1) A.B.C.D1
2) A.B.C.D2
In (1)
static Logger logger = Logger.getLogger("A.B.C.D1 ");
In (2)
static Logger logger = Logger.getLogger("A.B.C.D2 ");
In your log4J settings.
Set a logger for "A.B.C"
Log4J in (1) and (2) will use logger "A.B.C" because of "Name Hierarchy".
Alternatively.
You can also define 2 logger in log4J settings.
One for "A.B.C.D1" and another for "A.B.C.D2".
The logger for (1) and (2) uses the same appender.
--------------------------
The benefit of this is that you will have more control over what you are going to log without changing code.
Example: You can choose not to log (2) by just changing the log4J settings without having the need to change code.
I do not recommend you use log4J in this manner. You can make use of the "Named Hierarchy" nature of log4J to archieve what you are trying to do.
Suppose you have 2 java classes.
1) A.B.C.D1
2) A.B.C.D2
In (1)
static Logger logger = Logger.getLogger("A.B.C.D1
In (2)
static Logger logger = Logger.getLogger("A.B.C.D2
In your log4J settings.
Set a logger for "A.B.C"
Log4J in (1) and (2) will use logger "A.B.C" because of "Name Hierarchy".
Alternatively.
You can also define 2 logger in log4J settings.
One for "A.B.C.D1" and another for "A.B.C.D2".
The logger for (1) and (2) uses the same appender.
--------------------------
The benefit of this is that you will have more control over what you are going to log without changing code.
Example: You can choose not to log (2) by just changing the log4J settings without having the need to change code.
tht's how you can put stacktrace of exception to logger:
http://stackoverflow.com/questions/4347797/how-to-send-a-stacktrace-to-log4j
ASKER
@for_yan:Thanks for the reply.
I have the following two java files and the log4j properties files as well.
When the exception occurs i get the message as shown below as well.
I want to retain the same format but add a user defined message at each function as well in which exception occurs.
How do i achieve this.
Please help...
I have the following two java files and the log4j properties files as well.
When the exception occurs i get the message as shown below as well.
I want to retain the same format but add a user defined message at each function as well in which exception occurs.
How do i achieve this.
Please help...
import java.util.Properties;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class TestLogging {
//static Logger logger = Logger.getLogger(TestLogging.class.getName());
public static Logger logger =TestLogging.getLogger();
public static void main(String[] args) {
PropertyConfigurator.configure("log4j.properties");
try
{
TestLogging2.main1();
//String s=args[4];
// BasicConfigurator replaced with PropertyConfigurator.
logger.debug("Entering application.");
logger.info("Exiting application.");
}
catch(Exception e)
{
String stackStr = null;
StackTraceElement[] stk = e.getStackTrace();
for (int i = 0; i < stk.length ; i++)
{
stackStr += "Level [" + Integer.toString(i) + "] - File Name: '" + stk[i].getFileName() + "' Method Name: '" + stk[i].getMethodName() +"' Line Number: '" + stk[i].getLineNumber()+"' Message: '" + e.toString() + "'\n";
}
logger.debug("Exception occured "+stackStr);
logger.debug("Exception ended");
}
}
public static Logger getLogger()
{
if (logger != null) return logger;
try
{
PropertyConfigurator.configure("log4j.properties");
logger = Logger.getLogger(TestLogging.class);
}
catch (Exception exception)
{
exception.printStackTrace();
}
return logger;
}
}
import java.util.Properties;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class TestLogging2 {
public static void main1() throws Exception {
PropertyConfigurator.configure("log4j.properties");
main2();
// BasicConfigurator replaced with PropertyConfigurator.
TestLogging.logger.debug("Entering application.");
TestLogging.logger.info("Exiting application.");
}
public static void main2() throws Exception
{
String args[]={"hello"};
String s=args[4];
// BasicConfigurator replaced with PropertyConfigurator.
TestLogging.logger.debug("Entering application.");
TestLogging.logger.info("Exiting application.");
}
}
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%m%n
Exception occured nullLevel [0] - File Name: 'TestLogging2.java' Method Name: 'main2' Line Number: '30' Message: 'java.lang.ArrayIndexOutOfBoundsException: 4'
Level [1] - File Name: 'TestLogging2.java' Method Name: 'main1' Line Number: '16' Message: 'java.lang.ArrayIndexOutOfBoundsException: 4'
Level [2] - File Name: 'TestLogging.java' Method Name: 'main' Line Number: '18' Message: 'java.lang.ArrayIndexOutOfBoundsException: 4'
Exception ended
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
You also need to read up on formatting - you don't need to do anything but use the correct format string:
http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html
http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html
:)
this is from:
http://logging.apache.org/log4j/1.2/manual.html
Calling the getLogger method with the same name will always return a reference to the exact same logger object.
For example, in
Logger x = Logger.getLogger("wombat")
Logger y = Logger.getLogger("wombat")
x and y refer to exactly the same logger object.
Thus, it is possible to configure a logger and then to retrieve the same instance somewhere else in the code without passing around references. In fundamental contradiction to biological parenthood, where parents always preceed their children, log4j loggers can be created and configured in any order. In particular, a "parent" logger will find and link to its descendants even if it is instantiated after them.