DEBUG log rotation in JAVA - java

In a production environnement (for example) we often use INFO log level because with DEBUG log the size become quickly huge.
I know that's it's possible with SLJ4J or LOG4J to configure log rotation to split files etc.
But most of the time, we only need DEBUG logs when an exception appear, so we can have more information (HTTP Request logs for example).
I'm wondering if it's possible to keep only (for example) 1 minute of DEBUG log and save it if an exception appear. (Main log file is always on level INFO)
For example, when a HttpRequestException occurs, we have a file saved with 1 Minute of DEBUG log HttpRequestException-10-02-2015-10:28:50.log in a specific folder
So we can easily see all exceptions in this folder
/Exceptions/
- HttpRequestException-10-02-2015-10:28:50.log
- NullPointerException-10-02-2015-10:29:51.log
- IOException-10-02-2015-11:29:51.log
So... is it possible to do it with a tool like slf4j ?
And is DEBUG logging a huge performance problem on a production server?
Thanks

I found a solution.
I use cyclicBufferTracker to tell appender to use the last x lines once trigerred
And I can use the evaluator attribute to configure the trigger (default trigger is when an ERROR occurs)
Email is ok for me, but if someone want to put it in files instead of email I think you can create a custom Appender instead of SMTPAppender
Like on this page : http://jira.qos.ch/browse/LOGBACK-207
Here is the actual code : (You will need javax.activation and javax.mail if you use email implementation) and if you use gmail like me you will need to allow low security app in gmail settings : Gmail less secure apps
<appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
<smtpHost>smtp.gmail.com</smtpHost>
<smtpPort>587</smtpPort>
<asynchronousSending>false</asynchronousSending>
<STARTTLS>true</STARTTLS>
<username>GoogleUsername</username>
<password>mypassword</password>
<to>GoogleUsername#gmail.com</to>
<from>GoogleUsername#gmail.com</from>
<subject>Exception Alert</subject>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%date - %message%n</pattern>
</layout>
<cyclicBufferTracker class="ch.qos.logback.core.spi.CyclicBufferTracker">
<bufferSize>50</bufferSize>
</cyclicBufferTracker>
</appender>
Hope it will help

Related

Configuring log4j under WebSphere Application Server

We have a bunch of applications being deployed on Webshere Application Server (WAS). Somewhere on the class path we have a very basic log4j.properties with that looks similar to below:
log4j.rootLogger=ERROR, FILE, CONSOLE
#
# CONSOLE appender is a ConsoleAppender
#
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%X{component} [%-5p] %c - %m%n
#
# FILE appender is a FileAppender
#
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=##%d{dd-MM-yyyy HH:mm:ss,SSS} %X{component} [%-5p] %c - %m%n
#
# MyApp Debug Levels.
#
log4j.logger.com.my.company.my.app=INFO
Note the missing log4j.appender.FILE.File File from our log4j.properties, This is configured art WAS level via Application Servers -> MyServer -> Logging and tracing -> JVM Logs with the file name set as below:
${SERVER_LOG_ROOT}/SystemOut.log
Changing the debug level works fine e.g. adding to the log4j.properties the following line will result in getting debug entries for MySpecialClass in the logs.
log4j.logger.com.my.company.my.app.MySpecialClass=DEBUG
That makes me conclude that my properties file is considered.
However we recently received a request that in addition to the normal log entries to output some special log entries (application error related logs) to a separate file. My initial thought was to add one more rolling file appender and leave that do the work. To my surprise it did not work, everything related to that appender was just ignored.
Then I thought this may be because the log file is configured in WAS and everything goes there regardless of what we put in the log4j.properties and I said it looks a bit odd to have multiple apps writing to the same log file. However I did not want to spend too much time on this and because the special log entries were the error ones I just said lets just use the existing WAS feature of having a separate file for System.Err logs: Application Servers -> MyServer -> Logging and tracing -> JVM Logs:
${SERVER_LOG_ROOT}/SystemErr.log
To achieve this I created my own com.my.company.my.app.CustomPatternLayout and implemented this very basic format method:
public String format(LoggingEvent event) {
String log = patternLayout.format(event);
Level logLevel = event.getLevel();
if (Level.ERROR.equals(logLevel) || Level.WARN.equals(logLevel)
|| log.contains("Exception") || log.contains("PEM_LOGGER_SEV3")) {
System.err.println(log);
}
return log;
}
I also replaced the file appender in log4j.properties to use my custom pattern layout
log4j.appender.FILE.layout.com.my.company.my.app.CustomPatternLayout
Again nothing happened in my logs and the expected log entries never got written to the SystemErr.log. More than this I set some debug breakpoints and my code never gets executed. However if I remove my custom class from the class path i got some ClassNotFoundException log4j entries in the SystemErr.out which is a sign my configuration is read.
With no many ideas left the last thing I tried was to create a file called org.apache.commons.logging.LogFactory and have its content like below:
org.apache.commons.logging.impl.Log4jFactoryImpl
Our applications are running with a parent first class loading policy and we cannot change this.
This last attempt did not work either. Now I am out of ideas and can only help someone may bring some light in what am I missing.
Thank you in advance for your inputs.
UPDATE:
Actually I was wrong. If log4j is used to produce log entries then the CustomPatternLayout is used. It was only when the log entry was written by WAS that I could not my custom pattern being used. I think this is because WAS will use JDK java.util.logging.Logger. So my question would change to:
Is there a relatively easy way of intercepting WAS calls to writing log entries and apply a logic similar to the one I put in my custom pattern.
Thanks again for your inputs.

In Java, using the logback framework, is there a way to dynamically configure throttling for a chatty log message

We have a system deployed in the field that has Java services that use the logback logging framework. Each service has its own logback configuration file.
We're finding a particular log message being issued at WARN level many times per second. We're really only interested in seeing this message, for example, once/minute, so that we know the issue is occurring; but we don't want to raise the logging level of the class, such that other messages at INFO level are discarded.
Modifying the code is not an option, nor is doing any modifications to the system that would involve restarting the offending service. However, we can modify the log configuration.
Is there any way in logback, through the XML configuration file, to achieve this behavior?
Update
The messages are similar, but not identical; for example:
WARN The following ID will be dropped: 12345
WARN The following ID will be dropped: 54321
If the messages are exactly the same you might look at using the Duplicate Message filter.
http://logback.qos.ch/manual/filters.html#DuplicateMessageFilter
Or you can use an evaluator filter expression:
http://logback.qos.ch/manual/filters.html#evalutatorFilter
Like so
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator name="loggingTaskEval">
<expression>
message.contains("following ID will be dropped") &&
(timeStamp - event.getStartTime()) >= 20000
</expression>
</evaluator>
<OnMatch>DENY</OnMatch>
</filter>
Found that example here: http://logback.qos.ch/demo.html

Log4J fileappender doesn't roll on Websphere 7

My current project taking Log4j for logging output but when it is deployed on websphere 7 it seems the logging file is always occupied by the server hence Log4J cannot close it and open a new file. Current log file can expand to 1.5 Gb if on DEBUG level. I went through a few online tutorials but didn't get a solid solution. So I open this thread for any opinion or experience on making log4J works on WS 7.
Current log4J is on 1.2.15, and the project is a plain POJO/JSP application without other containers(like Spring, I do have another project with same issue on Spring/tomcat, will open in another thread). And here is the log4j.properties:
log4j.rootCategory=INFO, ROL
#
# Rolling File Appender
#
log4j.appender.ROL=org.apache.log4j.RollingFileAppender
log4j.appender.ROL.Encoding=UTF-8
log4j.appender.ROL.File=C\:\\Logs\\AppOut.log
log4j.appender.ROL.MaxFileSize=10000KB
log4j.appender.ROL.MaxBackupIndex=10
log4j.appender.ROL.layout=org.apache.log4j.PatternLayout
log4j.appender.ROL.layout.ConversionPattern=%d -- %p -- %c -- %m%n
But this configuration just doesn't make log file roll over.
UPDATE:
It seems like each time when I try to remove the log file after stop the application(not the server), it is always saying "the file is opened by another application" which only refers to Websphere. I can guarantee that there is no other application is opening the log file. The only way to release lock on it is stop the application server.
Thanks in advance for any ideas.
we use was 7 (with portal server 6.1 on top). (We wrap our calls to the logger using the sl4j lbrary, but I don't think that is relevant to the problem here). can't really see any major difference, other than we don't set the root category, and we explicitly set the additivty to false.
Below is part of our config (showing just one of our appenders) which works just fine and rolls the logs every 10MB as expected. Perhaps it's something configured in WAS itself - I'm not a WAS admin expert and didn't install WAS myself but could ask one of our admins on Monday if you haven't solved it.
log4j.logger.com.xxx.protection=TRACE, A1
log4j.additivity.com.xxx.protection=false
# other appenders excluded
log4j.appender.A1=org.apache.log4j.RollingFileAppender
log4j.appender.A1.File=${LOG_ROOT}/applLogs/ui_and_business_logic.log
log4j.appender.A1.MaxFileSize=10MB
log4j.appender.A1.MaxBackupIndex=10
log4j.appender.A1.Append=true
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %p %t %c MSG: %m%n
I take it that you've seen this article - http://www.ibm.com/developerworks/websphere/techjournal/0802_supauth/0802_supauth.html

How to clear server.log in JBoss?

How do I clear JBoss' server.log file when JBoss is running? When I try to do
echo 1 > server.log
I get error msg that the file is being used by another program (JBoss). Is it possible to use a command-line tool (windows or linux(I do have CygWin)) or an application that I can write myself to clear that file?
P.S. I don't need that file to have 0kb, but I want it to have less than 100MB.
By default JBoss keeps the file locked, since it is writing log messages into it. It is locked as long as JBoss is running and I don't know of other way to release it than stopping JBoss itself.
To keep its size under control, you can modify your log configuration, which is by default in <server>/conf˛jboss-log4j.xml. You can specify the maximum size of a log file, and define what to do when that size is reached: roll over to a new file, truncate the existing one and start writing over it again, etc.
A basic example (not tested, so no guarantee that it works straight as it is):
<appender name="ROLL" class="org.apache.log4j.rolling.RollingFileAppender">
...
<param name="maxFileSize" value="100MB" />
...
</appender>
Moreover, with the maxBackupIndex parameter you may define the number of backup files (default is 1).
JBoss locks the file as long as the logging process is running.
If you enabled the JMX console you can stop the logging, delete / modify the log, and start the logging service again.
The url should look something like this (for log4j):
http://jboss.example.com:8080/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss.system%3Atype%3DLog4jService%2Cservice%3DLogging
I tested this with JBoss 5.
This solution should be scriptable as well.
Regarding your log file size problem: You should use a configuration approach instead of editing the log file manually.

How to ouput text to console from Servlet

I have a servlet. But it is not working as desired. Hence for debugging purposes, I want to print statements to the java console(the one that can be opened using the java icon in taskbar). However, if I use System.out.println("message"), it doesnt display in java console.
Is there any alternative way where I can display messages to the console from the servlet?
Or can anyone suggest me an alternative way to display messages to any other console?
In which console do you expect it to appear?
Depending on the servlet container (I assume Tomcat), the logs are stored in a logs folder. For Tomcat this is tomcat/logs (or more often referred to as CATALINA_HOME/logs). If you are running it from within an IDE - they should be in the IDE console.
As a sidenote, using System.out isn't advisable for a real product - use a logging framework (like log4j).
Servlet (HttpServlet) has a method log(String s) inherited from GenericServlet class.
So you can just include
log("output text")
in the servlet's code and see output.
If you use Eclipse log goes right into console.
If you use IntellijIdea log goes into Run --> "Tomcat Localhost Log" tab.
I want to print statements to the java console(the one that can be opened using the java icon in taskbar)
You need to realize that servlets actually runs at the server side, not at the client side. Those are in fact two physically different environments which communicates with each other through the network using the HTTP protocol. That Java console will only work for Java programs which runs at the client side, such as applets and JNLP.
In your case, you just need to read the server logs. That's where the stdout will by default print to, or use a better configureable logging framework such as logback. The server logs are usually found in a straightforward folder/file in the server installation directory, such as /logs in case of Tomcat.
Look for the log file in the log-folder of your servlet container (i.e. Tomcat).
As suggested use log4j to generate debug messages. This logging framework provides a configuration file where you can set things like where the logs should be written into or how the log messages should be formatted. As soon it's in place you can replace
System.out.println("message");
with
log.debug("your debug message");
or
log.info("in case of a message with info character");
log.error("routine foo has experienced an exception", e);
Now your code is much cleaner and there is even another benefit - when being placed correctly these logs act as documentation for your code segments.
You should use logging, e.g. java.util.logging or log4j
Example of relevant log4j configuration:
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<root>
<priority value ="debug" />
<appender-ref ref="console" />
</root>

Categories

Resources