Bug 40888 - Weekly rotation problem in Europe
Summary: Weekly rotation problem in Europe
Status: RESOLVED FIXED
Alias: None
Product: Log4j - Now in Jira
Classification: Unclassified
Component: Appender (show other bugs)
Version: 1.2
Hardware: All All
: P2 major
Target Milestone: ---
Assignee: log4j-dev
URL:
Keywords:
: 46851 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-11-03 07:17 UTC by Laszlo Czegledi
Modified: 2009-10-10 11:24 UTC (History)
3 users (show)



Attachments
removal of locale to rollingcalendar (1.05 KB, patch)
2008-08-09 09:13 UTC, Thorbjørn Ravn Andersen
Details | Diff
test case (935 bytes, patch)
2008-08-09 09:34 UTC, Thorbjørn Ravn Andersen
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Laszlo Czegledi 2006-11-03 07:17:05 UTC
I have a problem using DailyRollingFileAppender with weekly rotation.
The problem is that the appender rolls over every month instead of every week.
The date pattern is:
log4j.appender.A1.DatePattern='.'yyyy-ww
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender

Log4j version: 1.2.14, java 1.5.0_06-b05 on Fedora Core 5.

OS environment settings:
LANG=hu_HU
TZ=Europe/Budapest


I debugged the DailyRollingFileAppender and found that when determining the
rotation period, method computeCheckPeriod() returns TOP_OF_MONTH instead of
TOP_OF_WEEK. 
The cause probably is that the getFirstDayOfWeek() call in
RollingCalendar.getNextCheckDate() returns Sunday instead of Monday as it should
in Hungary and in most part of Europe. Because the epoch and the first Sunday
after the epoch are on the same week, the method computeCheckPeriod() advances
to the next period type, monthly rotation.
Replacing getFirstDayOfWeek() with Calendar.getInstance().getFirstDayOfWeek()
resolves the problem for us.

This simple test program logs the week number within the current year, and the
log should be rotates when a new week starts (if you change the system time).
 
import java.util.GregorianCalendar;
import org.apache.log4j.Logger;

public class LogTest 
{
  private static final Logger log = Logger.getLogger(LogTest.class);
  
  public static void main(String args[]) 
  {
      GregorianCalendar cal = new GregorianCalendar();
      System.out.println("Sunday: " + cal.SUNDAY);
      System.out.println("Monday: " + cal.MONDAY);
      System.out.println("First day: " + cal.getFirstDayOfWeek());
      System.out.println("TimeZone: " + cal.getTimeZone().getDisplayName());
      try {
          for(int i = 0; i < 100;i++) {
              cal = new GregorianCalendar();
              log.warn("Hello, " + "week number: " + cal.get(cal.WEEK_OF_YEAR));
              Thread.currentThread().sleep(10 * 1000); // sleep 10 seconds
              System.out.println(i);
          }
      }
      catch(Exception ex) { log.error(ex); }
  }
} 


I tested with the following settings and got the same result:
LANG=en_GB
TZ=Europe/London

Thanks,
Laszlo
Comment 1 Thorbjørn Ravn Andersen 2008-06-30 14:18:02 UTC
This does not appear to have been addressed yet.  The code in question is that

the "roll over"-time is calculated to be

    case DailyRollingFileAppender.TOP_OF_WEEK:
	this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());
	this.set(Calendar.HOUR_OF_DAY, 0);
	this.set(Calendar.MINUTE, 0);
	this.set(Calendar.SECOND, 0);
	this.set(Calendar.MILLISECOND, 0);
	this.add(Calendar.WEEK_OF_YEAR, 1);
	break;


and the loop is

     for(int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {
	SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
	simpleDateFormat.setTimeZone(gmtTimeZone); // do all date formatting in GMT
	String r0 = simpleDateFormat.format(epoch);
	rollingCalendar.setType(i);
	Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
	String r1 =  simpleDateFormat.format(next);
	//System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);
	if(r0 != null && r1 != null && !r0.equals(r1)) {
	  return i;
	}
      }
 
The r1 and r0 will be identical in the case described by the original poster.

Will it be sufficient in all cases to just ask the Calendar what the first day of the week is as suggested in the bug report?
Comment 2 Thorbjørn Ravn Andersen 2008-08-09 09:13:35 UTC
Created attachment 22420 [details]
removal of locale to rollingcalendar
Comment 3 Thorbjørn Ravn Andersen 2008-08-09 09:21:06 UTC
The problem is that RollingCalendar is using Locale.ENGLISH, and SimpleDateFormatter is using the default locale from the surroundings.

The default locale for the original poster has first day of the week to Monday, but RollingCalendar calculated to Sunday which is the first day of the week in Locale.English.  Hence this fails.

The patch sets RollingCalendar to use the default locale too.

(I am in a similar locale so I see the bug too)

Comment 4 Thorbjørn Ravn Andersen 2008-08-09 09:34:45 UTC
Created attachment 22421 [details]
test case
Comment 5 Curt Arnold 2008-08-12 15:06:25 UTC
Committed slightly different change in 685338.  Attached patches changed the signature of RollingCalendar which is not private so would be considered a breaking API change.  Was simpler just to pass Locale.getDefault() instead of Locale.ENGLISH in the call to new RollingCalendar.
Comment 6 Curt Arnold 2009-10-10 11:24:26 UTC
*** Bug 46851 has been marked as a duplicate of this bug. ***