I'm new to util.logging so this might seem a trivial question to some but anyway here goes..I'm using Java's Util.logger to log messages. I'm trying to declare a logger in a single class and accessing it from other classes for logging messages.
Logger class
package util;
import java.util.logging.*;
public class Logger {
public Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
}
I'm trying to access this logger in other class as follows..
package mycode;
import util.Logger;
public class MYcode{
private void test(){
LOGGER.fine("Sample message");
}
}
Compilation Error message..
error: cannot find symbol
[javac]LOGGER.fine("Sample message");
When I'm declaring logger in Mycode class then I'm not getting any error but when declaring it another class I'm getting an error. Any idea where I'm going wrong??
Just keep using in all classes needing the logger the same line:
public Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
This way you are creating many references to one instance of logger identified by the global name.
The problem is your 'LOGGER' is NOT static, so you are NOT able to access.
Logger class:
package util;
import java.util.logging.*;
public class Logger {
public static final Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
}
Accessing logger in other class:
package mycode;
import util.Logger;
public class MYcode{
public void test(){
LOGGER.fine("Sample message");
}
}
Related
I'm migrating a service to log4j2. A package/library in this service has custom appender implementation for one logger.
Now, due to some complexity, I'd like to use Logger interface of Logger present in Log4j bridge instead of the Log4j2 Logger. And, add appenders to this logger in the runtime. But, this doesn't work.
What works
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
public class someClass {
private static final Logger log = LogManager.getLogger("logName");
private void addAppendersToLog() {
AddAppenders.add(log);
}
}
}
import org.apache.logging.log4j.Logger;
public class AddAppenders {
public static void add(Logger log) {
//logic to add Appenders;
}
}
What doesn't work
import org.apache.log4j.Logger;
public class someClass {
// This Logger gets picked from Log4j bridge
private static final Logger log = Logger.getLogger("logName");
private void addAppendersToLog() {
AddAppenders.add(log);
}
}
}
import org.apache.log4j.Logger;
public class AddAppenders {
public static void addAppenders(Logger log) {
//logic to add Appenders;
}
}
I want to migrate from log4j to log4j2. I have a custom logger class MyLoggerImplwhich extends Logger from log4j and implements user defined interface.
MyLoggerImpl.java (using log4j)
import org.apache.log4j.Logger;
public class MyLoggerImpl extends Logger implements MyLoggerInterface
{
private Logger logger = null;
MyLoggerImpl(){};
MyLoggerImpl(Class clas){
logger = Logger.getLogger(clas);
}
}
I tried modifying custom class as below. Also, configuration files like log4j2.xml etc are in place.
Solution 1
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class MyLoggerImpl extends LogManager implements MyLoggerInterface
{
private Logger logger = null;
MyLoggerImpl(){};
MyLoggerImpl(Class clas){
logger = LogManager.getLogger(clas);
}
}
Solution 2
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class MyLoggerImpl implements MyLoggerInterface
{
private Logger logger = null;
MyLoggerImpl(){};
MyLoggerImpl(Class clas){
logger = LogManager.getLogger(clas);
}
}
However I am getting below exception
Reason:java.lang.ClasCastException: com.custom.logger.MyLoggerImpl incompatible with org.apache.logging.log4j.Logger
I am not getting what is causing this. Please help.
UPDATE 1
public interface MyLoggerInterface{
public void info(Object infoObject1);
public void info(Object infoObject1, Object infoObject2);
public void info(int scheduleId, Object infoObject1);
public void info(int scheduleId, Object infoObject1, Object infoObject2);
// similar variations for error and debug methods
}
I am using final Logger LOGGER = LoggerFactory.getLogger(clazz); to get the LOGGER object of org.slf4j. I am facing difficulty in overriding any default implemented method of this class.
I am trying to override non-static method of the conrete class. Lets say, Class MyLogger { Logger LOGGER = LoggerFactory.getLogger(clazz); LOGGER.debug("Some message"); } Now debug method is the non-static method declared in the LOGGER class for which some concrete implementation has been provided. The problem here is I am seeing lots of implementation classes when I try to search for the references. So in order to override debug method what should I do
Updated the original class like this:
public class MyLogger implements Logger {
private static final Logger LOGGER = LoggerFactory.getLogger(MyLogger.class);
public static org.slf4j.Logger init(Class clazz) {
final Logger loggerOut = LoggerFactory.getLogger(clazz);
setContainerId();
LOGGER.debug("Logger is initialized for [{}].", clazz.getName());
return loggerOut;
}
public void debug(String msg, Object arg1)
{
LOGGER.debug("My message",arg1);
}
}
Still not able to get result. Please suggest what am I missing here?
Static methods cannot be overriden. If you see here the functions of LoggerFactory in documentation
I was taking over an old java projcet. And the original designer has gone.
In this project, it uses Log4j in a static way, like this:
public class LogUtil {
private static final String FQCN = LogUtil.class.getName();
private static final Logger logger1 = Logger.getLogger("INFO");
private static final Logger logger2 = Logger.getLogger("ERROR");
public static void info(Object message) {
if (logger1.isInfoEnabled()) {
forcedLog(logger1, Level.INFO, message);
}
}
public static void error(Object message) {
forcedLog(logger2, Level.ERROR, message);
}
private static void forcedLog(Logger logger, Level level, Object message) {
logger.callAppenders(new LoggingEvent(FQCN, logger, level, message, null));
}
}
Then other class can easily write logs with LogUtil.error("") and LogUtil.info("") .
And the INFO logger and ERROR logger were configured to write in separate files.
But in Log4j2, the class LoggingEvent can not be found.
So the question is, if I want to use Log4j2, how should I modify this class?
(maybe use Log4j 1.x bridge provided in log4j2 packages?)
Is using logger in this way reasonable? It seems that it is easier than creating loggers per class. Is there any problems like performance or others?
So the question is, if I want to use Log4j2, how should I modify this class? (maybe use Log4j 1.x bridge provided in log4j2 packages?)
You could rewrite it to use the public API instead of relying on underlying implementation details. So, something like this:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class LogUtil {
private static final Logger TRACE_LOGGER = LogManager.getLogger("TRACE");
private static final Logger DEBUG_LOGGER = LogManager.getLogger("DEBUG");
private static final Logger INFO_LOGGER = LogManager.getLogger("INFO");
private static final Logger WARN_LOGGER = LogManager.getLogger("WARN");
private static final Logger ERROR_LOGGER = LogManager.getLogger("ERROR");
private static final Logger FATAL_LOGGER = LogManager.getLogger("FATAL");
public static void trace(Object msg){
TRACE_LOGGER.trace(msg);
}
public static void debug(Object msg){
DEBUG_LOGGER.debug(msg);
}
public static void info(Object msg) {
INFO_LOGGER.info(msg);
}
public static void warn(Object msg){
WARN_LOGGER.warn(msg);
}
public static void error(Object msg) {
ERROR_LOGGER.error(msg);
}
public static void fatal(Object msg){
FATAL_LOGGER.fatal(msg);
}
...
}
Is using logger in this way reasonable? It seems that it is easier than creating loggers per class. Is there any problems like performance or others?
I don't see how adding 3 lines to a class is anything other than easy. All it takes to create a logger (in log4j2) is this:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
...
private static final Logger logger = LogManager.getLogger();
As for potential problems, with this implementation you give up a lot of the functionality of log4j.
You can't change the log level on a package or class basis because all of the classes share the same loggers. Perhaps you want to turn on TRACE logging for a new class you're working on, but you don't want any TRACE logs from other classes as it clutters the log file - you would not be able to make this kind of change easily.
You can't change the appenders on a package or class basis because once again all classes share the same loggers. Perhaps you want to send all of the logs from a new package that you're working on to a separate file so that you can more easily see what your new code is doing without having to filter the logs manually. Maybe you want to see all logs from a particular class or package in a single file during development so that you can follow the execution more easily without having to jump around to different files.
Is it possible to handle all running Logger classes and copy their output to some another hub during some timeperiod?
For example:
package com.ubs.testing;
import org.apache.log4j.Logger;
public class ClassA {
private static final Logger LOG = Logger.getLogger(ClassA.class);
public void classAMethod() {
LOG.info("Class A starts logging");
}
}
package com.ubs.testing;
import org.apache.log4j.Logger;
public class ClassB {
private static final Logger LOG = Logger.getLogger(ClassB.class);
public void classBMethod() {
LOG.info("Class B starts logging");
}
}
package com.ubs.testing;
import org.apache.log4j.Logger;
import org.testng.annotations.Test;
public class ClassABTest {
private static final Logger LOG = Logger.getLogger(ClassABTest.class);
#Test
public void testClassAB() throws Exception {
LOG.info("Test class AB starts");
/*Some logic*/
/* >>>HERE I WANT TO START HANDLING OF THE LOGGING OUTPUT AND STORE IT IN SOME OTHER OBJECT<<<*/
ClassA a = new ClassA();
ClassB b = new ClassB();
a.classAMethod(); // I want to get "Class A starts logging" message from ClassA Logger here
b.classBMethod(); // I want to get "Class B starts logging" message from ClassA Logger here
/* >>>HERE I WANT TO FINISH HANDLING OF THE LOGGING OUTPUT IN SOME OTHER OBJECT<<<*/
LOG.info("Test class AB ends");
}
}
Sorry if similar questions were posted before.
Thanks in advance for suggestions.
Forgot to left respone erlier.
Just switching from log4j to logback gave me a possibility to left markers, which can be handled by custom appender.
Another solution can be realized using Spring aop. Unfortunatelly mentioned issue cannot be resolved in this way, due to absence of the Spring framework within a project.