Configure Tomcat Log rotation windows - java

I use tomcat 9.0,slf4j for logging.
The problem was that log files are too big(17GM - the max i saw). I created java-based deleting system for logs. Because tomcat creates new log file every day.
But here is one unexpected moment. Tomcat creates log files whenever it may, sometimes it may use old days file.
For example today is 16th. This file may be used till 18th.
And thats why the size becomes big.
Even if configure correct(for my case) log creation i may have logs for 2 days in one file.
For example from 16th 1:00 pm till 17th 12:00 am.
So, i want to configure rotation for somehow.
Can somebody help?

slf4j is just an interface, you must be using log4j, logback, common-logging, etc (implmentation of slf4j).
If you are using slf4j + logback, you can set your rollingPolicy in logback.xml file. It cab be TimeBasedRollingPolicy, Size or combination of both.
For example, to set Time based policy to create log file per day and move older files to archive folder and just keep last 30 days logs, you can add this in your logback.xml file
<appender name="app" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${catalina.home}/logs/appname/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${catalina.home}/logs/archive/appname/app.%d{yyyy-MM-dd}.old.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>[%X{key}]%date{"yyyy-MM-dd'T'HH:mm:ss,SSSXXX", UTC} %-5level %logger{35}.%M[%L]-[%t] - %msg %n</pattern>
</encoder>

Related

Writing a log in to specific file for particular Class special log

In my application currently I am using the log4j for log. All the logs are getting written in to same log file. there is one common log file, where some others application also used write the log.
Lets assume i have aap.log and common.log. I want that all the log will get in app.log file but for some specific class log will get in common.log.
My log4j config is as below for app.log
<appender name="logFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${home}/logs/app.log</File>
<encoder>
<pattern>%d{MM.dd HH:mm:ss.SSS} [%2.2t][%c{1}.%M] %-5p - %m%n</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<maxIndex>20</maxIndex>
<FileNamePattern>${home}/logs/app.log.%i</FileNamePattern>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>25MB</MaxFileSize>
</triggeringPolicy>
</appender>
I don't want to create a new appender here for the common.log or addadditivity="false for that class. I want to use one CustomUtility class to write the log in to common.log instead of configuring it from log4.xml.
How can i write the log in same common.log file so other applications data or mine will not get messed up.
So in a nutshell, you need to do the following:
Define an another File appender (basically duplicate the section that you've presented in the question, change the name pattern). I don't think you should use app.log and app1.log to avoid confusion related to log rotation policies. So just pick other name for this new log file and associate appender with it.
When you have an appender - associate the logger of the utility class with this appender. You don't show it in the question but the chances are that a special "root" logger is associated with the presented appender. So you should define a logger for the utility class (use fully qualified name of the class including the package) and associate the appender that you've created in "1" with it.
After this step, logs coming from this utility class will be written into 2 files.
Why? Because of additivity feature of logging libraries:
So you should define the log created in "2" with "additivity=false".
Basically additivity means that you should resolve the actual appenders not only from the logger itself but from its parents as well, setting additivity=false breaks this chain

rolling log file is not being cleared

I'm trying to set up a rolling log appender that will rollover every day, as well as rollover when the log file reaches a certain threshold size. I've got a mostly-working setup, but if I restart the application, the rollover behavior completely breaks.
My current appender config, based on http://logback.qos.ch/manual/appenders.html#SizeAndTimeBasedFNATP
<appender name="logFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${my.log.dir}/mylog.txt</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>${my.log.dir}/mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- or whenever the file size reaches 10KB -->
<maxFileSize>10KB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>%-5level %d{HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n</pattern>
</encoder>
</appender>
I added a "LogSpammer" script to quickly generate log data, and the first time I run the app, everything seems fine. mylog.txt reaches ~10KB and gets dumped to one of the date-stamped files.
But if I restart the application, things go haywire. The main log file never gets cleared, but it does get copied over and over, with the size of the copy growing each time. Nothing gets cleared anymore.
I allowed this to run until each "rollover" was over 500KB, well above my maxFileSize of 10KB.
Is this behavior simply a bug? If not, am I doing something wrong with the configuration? How can I fix this?
The issue was caused by failing to fully shut down the logback LoggerContext when the (web)application was restarted.
In my case, the webapp was being stopped and started via container:start and container:stop in sbt. This is similar to "deploying" and "undeploying" a .war file on Tomcat. Since the JVM was not shutting down, nor was logback explicitly being stopped, it was able to retain a lock on the main log file. Calling container:start after that leads to the weirdness described in the question.
Fully shutting down the JVM and then running container:start allowed the logger/rollover to function normally.
Calling the LoggerContext's stop method during the webapp's "unload" hook solves the problem:
// I happened to be using slf4j's, so I use its LoggerFactory
// class to get the LoggerContext instance
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
lc.stop();

DEBUG log rotation in 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

How to force logback to create a new file on rollover

I'm trying to achieve with logback the same thing that currently works with log4j - a size and time base rolling file appender.
Upon rolling a new file should be created with the current timestamp but logback still writes to the old file.
I'm using something like:
<timestamp key="bySecond" datePattern="yyyyMMddkkmmss"/>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logback.PREFIX}-${bySecond}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logback.PREFIX}-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1GB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
Wanted behaviour:
application starts with my-20131206105823.log
a rolling event occurs (1GB or midnight)
the my-2013-12-06.0.log.gz file is created
the application resumes logging in my-20131207000001.log
Current behavior:
application starts with my-20131206105823.log
a rolling event occurs (1GB or midnight)
the my-2013-12-06.0.log.gz file is created
the application resumes logging in my-20131206105823.log
It would be nice if I would also find out how to have this done only on the day rollover and not on the size, but this could be enough.
Java 1.7 with logback-1.0.9
I am not sure but let me try to resolve it. Once the rolling event occurred, the content of "my-20131206105823.log" file get copied to "my-2013-12-06.0.log.gz" and you will again get the new file with the same old name i,e "my-20131206105823.log".
<file>${logback.PREFIX}-${bySecond}.log</file>
$bySecond get assigned just once when you start your application, It won't change on every rollback. Timestamp is just a variable. Check here
Also check this one.

How to configure Tomcat JULI logging to roll log files?

I have a several webapps which use java.util.logging. Tomcat 5.5 is configured to use the Juli logger so that each webapp has its own log file. The problem is that Juli does not have properties for maximum file size and file count. Using Juli the files will grow unbounded and only roll at the end of the day. Also, an unlimited number of log files are retained.
You can see the FileHandler properties on this page - Apache Tomcat 5.5 Documentation
There is no limit or count property (the following lines do nothing)
org.apache.juli.FileHandler.limit=102400
org.apache.juli.FileHandler.count=5
Without changing the webapps is there a way to get unique log files for each application with some type of bounds on the log file sizes?
UPDATE:
The solution I found was not use the Juli logger at all!
java.util.logging.FileHandler.limit=102400
java.util.logging.FileHandler.count=5
Thanks,
Greg
Update: I see your point now after reading more. "Tomcat's JULI implementation is not intended to be a fully-featured logging libary, only a simple bridge to those libraries. However, JULI does provide several properties for configuring the its handlers. These are listed below." Funny that they say that the default java.util.Logging implementation is too limited then they work around it by providing an even more limiting implementation.
FileHandler javadocs
java.util.logging.FileHandler.limit specifies an approximate maximum amount to write (in bytes) to any one file. If this is zero, then there is no limit. (Defaults to no limit).
java.util.logging.FileHandler.count specifies how many output files to cycle through (defaults to 1).
for the one file per web app, you probably want to separate it by the name of the logger and it depends on how the loggers are created for each app. If they're based off the package or class name then you can filter the logs based on that. It looks like the sample on the link you provided tells how to do this
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = \
2localhost.org.apache.juli.FileHandler
EDIT: Just realized you wanted per webapp logging which might not be possible with this setup...
My suggestion, assuming your are using Tomcat 6.0, is to compile the extra component for full commons-logging and use Log4j to configure rolling logs.
Building instructions here
http://tomcat.apache.org/tomcat-6.0-doc/building.html
Then replace the tomcat-juli.jar in the /bin directory of Tomcat and place the tomcat-juli-adapters.jar in the /lib directory along with log4j.jar and log4j.properties.
Then using something like:
<appender name="file" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="logfile.log"/>
<param name="Threshold" value="INFO"/>
<param name="MaxFileSize" value="10MB"/>
<param name="MaxBackupIndex" value="3"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ISO8601} %p %m%n"/>
</layout>
</appender>

Categories

Resources