Reputation: 1671
I am testing java.util.logging
and it is displaying wrong class when I log a message. This is my code:
I have an interface MyLogger:
package ptest2;
public interface MyLogger {
public void info(String message);
}
I have an implementation class MyLoggerImpl which implements interface MyLogger
using java.util.logging
:
package ptest2;
import java.util.logging.Logger;
public class MyLoggerImpl implements MyLogger {
private Logger logger;
public MyLoggerImpl(String name) {
logger = Logger.getLogger(name);
}
@Override
public void info(String message) {
logger.info(message);
}
}
I have a class MyLoggerFactory which has a static method that accepts a String name
parameter and give MyLogger
:
package ptest2;
public class MyLoggerFactory {
public static MyLogger getMyLogger(String name) {
MyLogger myLogger = new MyLoggerImpl(name);
return myLogger;
}
}
Now I create a class ClientClass2 which uses logging. It has a method which will display a INFO level message:
package ptest2;
public class ClientClass2 {
private static MyLogger LOGGER = MyLoggerFactory.getMyLogger("ClientClass2");
public void method2() {
LOGGER.info("This is INFO level message");
}
}
To test it I create a class TestLoggingClientClass2:
package ptest2;
public class TestLoggingClientClass2 {
public static void main(String[] args) {
ClientClass2 clientClass2 = new ClientClass2();
clientClass2.method2();
}
}
I run it and this is what I got:
10-Apr-2015 12:17:18 PM ptest2.MyLoggerImpl info
INFO: This is INFO level message
But this is what I should have got:
10-Apr-2015 12:17:18 PM ptest2.ClientClass2 info
INFO: This is INFO level message
I dont see any problem with the code. What I am doing wrong? How can I get the required results?
The other questions are for formatting the message. But I am ok with the format of the message. My concern is why the message is displaying the wrong class.
I have look at the source code of the java.util.logging
(Thank you Oracle).
The message is formatted by public synchronized String format(LogRecord record)
method of SimpleFormatter
class. For the class name, this method uses sourceClassName
property of the concerned LogRecord
; and only if that property is null then it uses loggerName
property of the concerned LogRecord
In the Logger
class, when the public void info(String msg)
method is called then it sets the loggerName
property of the concerned LogRecord
.
In the Logger
class, when the public void logp(Level level, String sourceClass, String sourceMethod, String msg)
method is called then it sets the sourceClassName
property of the concerned LogRecord
.
So in MyLoggerImpl class instead of me calling
@Override
public void info(String message) {
logger.info(message);
}
I change to
@Override
public void info(String message) {
logger.logp(Level.INFO, logger.getName(), "info", message);
}
and it work. Strange. What do you guys make of it?
Upvotes: 0
Views: 1049
Reputation: 1622
java.util.logging.Logger
is invoked from MyLoggerImpl
, that's why its name is printed. To check this you can for test use it from ClientClass2
directly and then (and only then) it will print ptest2.ClientClass2
.
BTW I don't know why you're creating your own Logger API, take a look at slf2j or logback, no point in reinventing the wheel.
UPDATE: You've updated the logger to use logger name
where a class name
is expected as parameter for logp
method so it's being printed like that according to current logging pattern. You can either follow this approach or change the pattern. In the former case you could change MyLoggerFactory
to accept Class<?>
parameter:
public static MyLogger getMyLogger(Class<?> clazz) {
return new MyLoggerImpl(clazz.getSimpleName());
}
Upvotes: 1