I have an app in java using log4j as my logging jar, but when I try to debug my app and open the log file I find it short and with only the last lines I logged and the rotation files don't show any of the logs that I have seen before.
Is there something wrong with my configuration file? I have multiple projects pointing to the same log file, Could this be the problem?
Here is my log4j.properties:
log4j.rootLogger=ERROR,logfile
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=/opt/tomcat7/logs/mylogs.log
log4j.appender.logfile.MaxFileSize=500KB
# Keep one backup file
log4j.appender.logfile.MaxBackupIndex=2
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %5p (%F:%L) - %m%n
Thanks
You specified level of root logger to be ERROR, while in most cases there won't be a lot of ERROR messages - maybe one-two per many INFO level messages, while you suppressed them: ERROR level allows only ERROR and FATAL messages to be logged. And it filders out any INFO, WARN, DEBUG, TRACE level. Usually you don't use such setup in development. And in production you usually suppress only some verbose classes/packages, but not everything like in config you posted (meaning here ERROR level applies to every class).
So I suppose you should replace ERROR with INFO in your config.
UPDATE: Also likely log4j simply doesn't see your config file. I encountered this issues several times personally and each time I had a workaround like this:
public class Log4JProperties {
public static void setupLog4j(){
String log4jPathFile = Log4JProperties.class.getResource("/log4j.properties").getFile();
Properties props = new Properties();
try {
InputStream configStream = new FileInputStream(log4jPathFile);
props.load(configStream);
configStream.close();
} catch (IOException e) {
System.out.println("log4j configuration file not found");
}
LogManager.resetConfiguration();
PropertyConfigurator.configure(props);
}
}
This is not necessary when I run code from inside Intellij, but when I run using Maven, logging doesn't work without calling this function in the beginning of the execution.
When you specify MaxBackupIndex=2 it will only keep last 2 backups, if log file fills up quickly old backup files will be overridden.
You might have to increase the MaxFileSize or MaxBackupIndex based on your file logging behaviour…
https://logging.apache.org/log4php/docs/appenders/rolling-file.html
Related
I need create a lot of .log file in different folders from one java method.
Example:
home/work/folder1/log1.log
home/work/folder1/log2.log
home/work/folder2/log3.log
...............................
In java method i create dynamic Logger:
private Logger getLogger(String extId, String workId) {
String postfix = String.join(
".",
getClass().getName(),
extId, //folder1, folder2
String.valueOf(workId) //log1, log2
);
return LoggerFactory.getLogger(postfix);
}
How i can configurate logback to runtime create files?
I see ch.qos.logback.classic.spi.Configurator, but don't inderstand what do next.
Thank for any helps!
Why do you care about your log folders?
You can log in one folder and use the elk-stack to verify them.
I always do it with one sperate folder per log level and configure my logpattern with log4j2. Logstash reads the logs immediatly when new ones are available und pushes them to elastic search. With kibana you can do many cool dashboards to analyze them.
I have a scenario where I have a separate custom level defined XYZLogLevel for logging and I have 2 rolling file appenders where 2nd appender is specifically reserved to log log messages from XYZLogLevel. However the logs are going in both the files which is undesirable.
Note:-
Logs are not package specific, so adding additivity for package wont
work.
Everything has to be done through log4j.properties file.
Adding LevelRangeFilter to first appender partially resolves it, but
when I add 3rd appender for another custom level, then I again see
duplication in 2nd and 3rd appender.
log4j.rootCategory=ERROR, F, XYZLOG, LMNLOG
log4j.appender.F=org.apache.log4j.RollingFileAppender
log4j.appender.F.File=f_log.log
log4j.appender.F.MaxFileSize=5MB
log4j.appender.F.MaxBackupIndex=10
log4j.appender.F.layout = org.apache.log4j.PatternLayout
log4j.appender.F.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} %c{1} [%p] %m%n
log4j.appender.XYZLOG=org.apache.log4j.RollingFileAppender
log4j.appender.XYZLOG.File=xyz_reporting.log
log4j.appender.XYZLOG.threshold=XYZLOG#com.services.domain.xyzlogs.XYZLogLevel
log4j.appender.XYZLOG.filter.a=org.apache.log4j.varia.LevelMatchFilter
log4j.appender.XYZLOG.filter.a.LevelToMatch=XYZLOG#com.services.domain.xyzlogs.XYZLogLevel
log4j.appender.XYZLOG.filter.a.AcceptOnMatch=true
log4j.appender.XYZLOG.MaxFileSize=100KB
log4j.appender.XYZLOG.MaxBackupIndex=10
log4j.appender.XYZLOG.layout=org.apache.log4j.PatternLayout
log4j.appender.XYZLOG.layout.ConversionPattern=%m%n
log4j.appender.LMNLOG=org.apache.log4j.RollingFileAppender
log4j.appender.LMNLOG.File=lmn_reporting.log
log4j.appender.LMNLOG.threshold=LMNLOG#com.services.domain.lmnlogs.LMNLogLevel
log4j.appender.LMNLOG.filter.a=org.apache.log4j.varia.LevelMatchFilter
log4j.appender.LMNLOG.filter.a.LevelToMatch=LMNLOG#com.services.domain.lmnlogs.LMNLogLevel
log4j.appender.LMNLOG.filter.a.AcceptOnMatch=true
log4j.appender.LMNLOG.MaxFileSize=100KB
log4j.appender.LMNLOG.MaxBackupIndex=10
log4j.appender.LMNLOG.layout=org.apache.log4j.PatternLayout
log4j.appender.LMNLOG.layout.ConversionPattern=%m%n
Maybe this can be solved through org.apache.log4j.varia.DenyAllFilter but somehow I was not able to configure that for properties file. I believe that functionality is only for XML configuration.
Its a very tricky sitution as I dont have the liberty to switch to XML configuration, any help on this would be appreciated guys.
Link and examples would be great as I understand them quickly.
I am answering my own question.
First you need to create a logger and set additivity as FALSE.
log4j.logger.XZYLOG=XZYLOG#XYZLOG#com.services.domain.xyzlogs.XYZLogLevel, XYZAPPENDER
log4j.additivity.XZYLOG=false
log4j.logger.LMNLOG=LMNLOG#XYZLOG#com.services.domain.lmnlogs.LMNLogLevel, LMNAPPENDER
log4j.additivity.LMNLOG=false
Then configure the appenders in following way.
log4j.appender.XYZLOGAPPENDER=org.apache.log4j.RollingFileAppender
log4j.appender.XYZLOGAPPENDER.File=xyz_reporting.log
log4j.appender.XYZLOGAPPENDER.threshold=XYZLOG#com.services.domain.xyzlogs.XYZLogLevel
log4j.appender.XYZLOGAPPENDER.MaxFileSize=100KB
log4j.appender.XYZLOGAPPENDER.MaxBackupIndex=10
log4j.appender.XYZLOGAPPENDER.layout=org.apache.log4j.PatternLayout
log4j.appender.XYZLOGAPPENDER.layout.ConversionPattern=%m%n
log4j.appender.LMNLOGAPPENDER=org.apache.log4j.RollingFileAppender
log4j.appender.LMNLOGAPPENDER.File=lmn_reporting.log
log4j.appender.LMNLOGAPPENDER.threshold=LMNLOG#com.services.domain.lmnlogs.LMNLogLevel
log4j.appender.LMNLOGAPPENDER.MaxFileSize=100KB
log4j.appender.LMNLOGAPPENDER.MaxBackupIndex=10
log4j.appender.LMNLOGAPPENDER.layout=org.apache.log4j.PatternLayout
log4j.appender.LMNLOGAPPENDER.layout.ConversionPattern=%m%n
You may or may not need the filter in this case.
Note: I cannot post company code here thats why I modified the solution.
This is to give you general idea how I have solved this problem.
I've seen questions about it, but none of it helped me.
I'm using log4j, but as it works fine on console, it doesn't write anything to declared files. What is more, files were created, but nothing is saved in them.
Code:
#default
log4j.rootLogger=ERROR,console
#Console Appender
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%5p] [%t %d{hh:mm:ss}] (%F:%M:%L) %m%n
#Custom assignments
log4j.logger.controller=DEBUG,console
log4j.logger.service=DEBUG,console
log4j.logger.dao=DEBUG,console
#Disable additivity
log4j.additivity.controller=false
log4j.additivity.service=false
log4j.additivity.dao=false
#MyLogger
log4j.logger.classPath.myClass = INFO, CACHE
log4j.appender.CACHE=org.apache.log4j.RollingFileAppender
log4j.appender.CACHE.File = ./logs/cache.log
log4j.appender.CACHE.bufferedIO = false
log4j.appender.CACHE.ImmediateFlush=true
log4j.appender.CACHE.Threshold=info
log4j.appender.CACHE.layout=org.apache.log4j.PatternLayout
log4j.appender.CACHE.layout.ConversionPattern=[%5p] [%t %d{hh:mm:ss}] (%F:%M:%L) %m%n
I'm sure that logger is defined properly, because when additivity=false, logs are not showed in console as expected. And when log4j.logger.myClass = INFO, CACHE, console is added as well, logs are showed in console again. So logger declaration seems fine. So why are they not showed in log file?
I'm using org.apache.log4j.Logger.getLogger(myClass.class).info('msg') syntax to use logger.
org.apache.log4j.Logger.getLogger("classPath.myClass").info('msg') is not working either.
When trying log4j.rootLogger=INFO,console,CACHE also nothing appears in the file.
The logger name is specified wrongly. Please change it as follows
#MyLogger
log4j.logger.MyClass = INFO, CACHE
instead of
#MyLogger
log4j.logger.myClass = INFO, CACHE
MyClass is wrongly denoted as myClass. You can also make the logger instantiation as follows
Logger.getLogger("MyClass").info('msg');
Hope this helps!
Some logging levels appear to be broke?
I run a Java web start (which I will begin to call JWS from now on) application straight from a GlassFish 3.1.2.2 instance. The client has a static logger like so:
private final static Logger LOGGER;
static {
LOGGER = Logger.getLogger(App.class.getName());
// Not sure how one externalize this setting or even if we want to:
LOGGER.setLevel(Level.FINER);
}
In the main method, I begin my logic with some simple testing of the logging feature:
alert("isLoggable() INFO? " + LOGGER.isLoggable(Level.INFO)); // Prints TRUE!
alert("isLoggable() FINE? " + LOGGER.isLoggable(Level.FINE)); // ..TRUE
alert("isLoggable() FINER? " + LOGGER.isLoggable(Level.FINER)); // ..TRUE
alert("isLoggable() FINEST? " + LOGGER.isLoggable(Level.FINEST)); // ..FALSE
My alert methods will display a JOptionPane dialog box for "true GUI logging". Anyways, you see the printouts in my comments I added to the code snippet. As expected, the logger is enabled for levels INFO, FINE and FINER but not FINEST.
After my alert methods, I type:
// Info
LOGGER.info("Level.INFO");
LOGGER.log(Level.INFO, "Level.INFO");
// Fine
LOGGER.fine("Level.FINE");
LOGGER.log(Level.FINE, "Level.FINE");
// Finer
LOGGER.finer("Level.FINER");
LOGGER.log(Level.FINER, "Level.FINER");
LOGGER.entering("", "Level.FINER", args); // <-- Uses Level.FINER!
// Finest
LOGGER.finest("Level.FINEST");
LOGGER.log(Level.FINEST, "Level.FINEST");
I go to my Java console and click on the tab "Advanced", then I tick "Enable logging". Okay let's start the application. Guess what happens? Only Level.INFO prints! Here's my proof (look at the bottom):
I've done my best to google for log files on my computer and see if not Level.FINE and Level.FINER end up somewhere on the file system. However, I cannot find the log messages anywhere.
Summary of Questions
Why does it appear that logging of Level.FINE and Level.FINER does not work in the example provided?
I set the logging level in my static initializing block, but I'd sure like to externalize this setting to a configuration file of some sort, perhaps packaged together with the EAR file I deploy on GlassFish. Or why not manually write in some property in the JNLP file we download from the server. Is this possible somehow?
Solution for problem no 1.
After doing a little bit more reading on the topic, I concluded that a logger in Java uses a handler to publish his logs. And this handler in his turn has his own set of "walls" for what levels he handles. But this handler need not be attached directly to our logger! You see loggers are organized in a hierarchical namespace and a child logger may inherit his parents handlers. If so, then By default a Logger will log any output messages to its parent's handlers, and so on recursively up the tree (see Java Logging Overview - Oracle).
I ain't saying I get the full picture just yet, and I sure didn't find any quotes about how all of this relates to a Java Web Start application. Surely there has to be some differences. Anyways, I did manage to write together this static initializing block that solves my immediate problem:
static {
LOGGER = Logger.getLogger(App.class.getName());
/*
* This logic can be externalized. See the next solution!
*/
// DEPRECATED: LOGGER.setLevel(Level.FINER);
if (LOGGER.getUseParentHandlers())
LOGGER.getParent().getHandlers()[0].setLevel(Level.FINER);
else
LOGGER.setLevel(Level.FINER);
}
Solution for problem no 2.
The LogManager API docs provided much needed information for the following solution. In a subdirectory of your JRE installation, there is a subdirectory called "lib" and in there you shall find a "logging.properties" file. This is the full path to my file on my Windows machine:
C:\Program Files (x86)\Java\jre7\lib\logging.properties
In here you can change a lot of flavors. One cool thing you could do is to change the global logging level. In my file, this was done on row 29 (why do we see only a dot in front of the "level"? The root-parent of all loggers is called ""!). That will produce a hole lot of output; on my machine I received about one thousand log messages per second. Thus changing the global level isn't even plausible enough to be considered an option. Instead, add a new row where you specify the level of your logger. In my case, I added this row:
martinandersson.com.malivechat.app.App.level = FINER
However, chances are you still won't see any results. In solution no 1, I talked about how loggers are connected to handlers. The default handler is specified in logging.properties, most likely on row 18. Here's how my line reads:
handlers= java.util.logging.ConsoleHandler
Also previously, I talked about how these handlers in their turn use levels for what should trouble their mind. So, find the line that reads something like this (should now be on row 44?):
java.util.logging.ConsoleHandler.level = INFO
..and in my case I swapped "INFO" to "FINER". Problem solved.
But!
My original inquiry into this matter still hasn't provided an answer how one can set these properties closer in par with the application deployment. More specifically, I would like to attach these properties in a separate file, bundled with the application EAR file I deploy on GlassFish or something like that. Do you have more information? Please share!
Situation: I have this log4j logger:
private static final Logger logger = Logger.getLogger(ThisClassName.class);
And am trying to set it programatically through:
Logger.getLogger(ThisClassName.class).setLevel(Level.DEBUG);
Still, DEBUG level prints are swalloed (while INFO prints are printed successfully).
Even this bit has no effect: Logger.getRootLogger().setLevel(Level.DEBUG);
Calling logger.debug("foo") reaches Category.forcedLog() and ConsoleAppender.doAppend(), and then fails (quits) at:
if(!isAsSevereAsThreshold(event.getLevel()))
Any idea why this is happening?
Your appender is configured with a threshold greater than debug, so while the logger doesn't ignore the entries, your appender doesn't record it. You need to configure the threshold of your ConsoleAppender to be DEBUG as well, either through your config file or programatically:
((ConsoleAppender)someLogger.getAppender("CONSOLE")).setThreshold(Level.DEBUG);
Config files are usually the more elegant solution for this sort of thing.
Edit: Note that apparently, any subclass of AppenderSkeleton (including ConsoleAppender) shouldn't have a threshold filter set by default. So it's likely that somewhere in your configuration you're actually manually assigning a threshold ( > Debug) to that appender, as #justkt hints.