I'am still working on a problem with the Http Builder in Java. The Builder is using a Log which is private. This Log is generated with the Logger Factory.
On debugging I notice that the logger level is null and so the logs are not printed. On debugging I can change the logger level and the logs are printed.
The Problem is that i can not set the Logger Level from outside of the HTTP Builder.
So is it possible to set the Level of all Log property which are generated by the Log Factory ?
I managed to find a solution
Just import
import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
And Set
Logger rootLogger = (Logger)LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)
rootLogger.setLevel(mLevel)
Related
I'm trying to capture bean allocation logs in a test - I've got code that I've tested, and will successfully capture logs from my classes - but when I try to do it on spring classes it is seemingly not working - here is the code I use to try and capture:
LoggerContext context = (LoggerContext) (LoggerFactory.getILoggerFactory());
Logger log = context.getLogger("org.springframework.beans.factory.support.DefaultListableBeanFactory");
log.setLevel(Level.DEBUG);
MyAppender appender = new MyAppender();
appender.setContext( context);
log.addAppender( appender );
SpringApplication newApplication = new SpringApplication( Application.class);
newApplication.run( new String [] {});
Now if I trace in and look at the logger that spring is using - it looks like a completely different style of logger - (its hooked to a logmanager, not a loggercontext) - and go into that and it seems like it might be a different context?
Any idea what I'm doing wrong, and how I can in a unit test capture spring bean creation logs?
Spring boot is using Logback logger by default
It uses LogbackLoggingSystem implementation which
extends from AbstractLoggingSystem
Spring boot LoggingSystem runs before context is initialized
To override default properties you can define logback.xml or logback-spring.xml
Or you can use application.yml or properties file to define log configurations :
logging.level.* : It is used as prefix with package name to set log level.
logging.file : It configures a log file name to log message in file. We can also configure file name with absolute path.
logging.path : It only configures path for log file. Spring boot creates a log file with name spring.log
logging.pattern.console : It defines logging pattern in console.
logging.pattern.file: It defines logging pattern in file.
logging.pattern.level: It defines the format to render log level. Default is %5p.
As documentation says:
You can force Spring Boot to use a particular logging system by using the org.springframework.boot.logging.LoggingSystem system property. The value should be the fully qualified class name of a LoggingSystem implementation. You can also disable Spring Boot’s logging configuration entirely by using a value of none.
If you use static Loggers in your Class under Test, you could use Powermock to mock the logger and assert the output, as descirbed in this question.
We use it in our Spring-Tests and formatting and style is the same.
for anyone interested - this finally worked for me:
Logger logger = Logger.getLogger(
"org.springframework.beans.factory.support.DefaultListableBeanFactory");
logger.addHandler( this );
logger.setLevel( java.util.logging.Level.FINE);
_logger = logger;
now I can capture, trace and time all bean allocations.
There is an maven OSGI component in which I have a call to EclipseStarter.stop() statement which shuts down the OSGI framework. There are a couple of log statements printed after this line. I have used pax-logging with log4j2 as the logging backend and JCL at the frontend.
Since OSGI framework is down the log messages do not print through pax-logging-log4j2. Therefore I am trying to use java util logging to print these messages. The logger initialization in the java file is done as follows.
private static final Log log = LogFactory.getLog(MyClass.class);
private static final Logger logger = Logger.getLogger(MyClass.class.getName());
log.info("Before shutdown");
EclipseStarter.stop();
logger.log(Level.INFO, "After shutdown JUL");
log.info("After shutdown JCL");
The util logging statement seems to be skipping when I debugged.
In order to see output from a logger you have to attach a Handler subclass. You can add them from code or you can create a logging.properties.
I want to change the level of logging for all (about) of my web application controller classes dynamically. Each class that does logging contains this code:
private static final Logger logger = LoggerFactory
.getLogger(HomeController.class);
I learned that slf4j doesn't offer the functionality of setting a log level, so that one has to use the underlying log4j:
public static void setLogLevel(String level) {
org.apache.log4j.Logger logger4j = org.apache.log4j.Logger.getRootLogger();
logger4j.setLevel(org.apache.log4j.Level.toLevel(level.toUpperCase()));
logger.info("Sample Info After setLevel");
logger.debug("Sample Debug After setLevel");
logger.error("Sample Error After setLevel");
logger.trace("Sample Trace After setLevel");
logger.warn("Sample Warn After setLevel");
}
My idea is to have a controller method which changes the logLevel and maybe stores it in the database. My question is: How I can solve this elegantly without copy and pasting everything in 40+ files and modifying every controller method? Also note that the logger code is static, while my database access is not static.
How I can solve this elegantly without copy and pasting everything in 40+ files and modifying every controller method?
You use a single controller method, taking the logger name and desired log level as a query parameters, and call the string version of LogManager.getLogger(String name).
Also saving to the database and re-loading on restart is of course extra work to be done by you.
Alternatively, the controller can update the Log4j configuration file used at startup, and force Log4j to reload it whenever it's changed, e.g. by calling PropertyConfigurator.configure(String configFilename).
You can use Slf4j and externalize your application.properties file . You can configure the logging level in this file as per your needs.
logging.level.com.test=DEBUG
logging.level.org=INFO
I am not sure why you need to store this logging level in the Database.
I want to be able to programmatically set the logging level for all loggers.
This works:
Logger log = Logger.getLogger(Example.class);
LogManager.getLogger(Example.class).setLevel(Level.FATAL);
log.debug("Should not see!");
LogManager.getLogger(Example.class).setLevel(Level.DEBUG);
log.debug("Should see!");
However this does not:
Logger log = Logger.getLogger(Example.class);
LogManager.getRootLogger().setLevel(Level.FATAL);
log.debug("Should not see!");
LogManager.getRootLogger().setLevel(Level.DEBUG);
log.debug("Should see!");
Get the logger names from LogManager.getCurrentLoggers() and then set the LogManager.getLogger("<name from loop>").setLevel(Level.FATAL); using loop.
When you are getting LogManager.getRootLogger() gets the root level logger. It is not going to affect all the individual configuration.
Im using Log4j and i have the following problem: is there a way to add one more logger from your code ? (not root logger).
In my config file, i set up the following two loggers :
log4j.rootCategory=INFO, ALogFile
log4j.logger.BLog=INFO,BLog
I would like to remove second line from config file and add BLog from code. Is that possible?
The equivalent code should be:
Logger logger = Logger.getLogger("BLog");
logger.setLevel(Level.INFO);
logger.addAppender(Logger.getRootLogger().getAppender("BLog")); // see notes below
I.e. you obtain a Logger object for the name BLog, you then set the level to INFO and attach the appender you've presumable defined elsewhere in your config file, called BLog.
Note: based on the answers from this related question, you may need to attach the appender to a logger in order to be able to reference it, as my code does above. Or just define the appender in your code.