1 import java.io.File;
2 import java.io.IOException;
3 import java.text.SimpleDateFormat;
4 import java.util.ArrayList;
5 import java.util.Calendar;
6 import java.util.Date;
7 import java.util.List;
8
9 import org.apache.log4j.FileAppender;
10 import org.apache.log4j.Layout;
11 import org.apache.log4j.helpers.LogLog;
12 import org.apache.log4j.spi.LoggingEvent;
13
14
15 /**
16 * this is an extend class of appender, which is suitable for the specified
17 * datePattern--"yyyy-MM-dd" and the maxBackupIdex is not configurable.
18 *
19 */
20 public class DayRollingFileAppender extends FileAppender {
21
22 /** datepattern was fixed as yyyy-MM-dd */
23 private final String datePattern = "'.'yyyy-MM-dd";
24
25 /** the default max count of log files */
26 private int maxBackupIndex = 10;
27
28 /** file name + date of last time */
29 private String scheduledFilename;
30
31 /**
32 * The next time we estimate a rollover should occur.
33 */
34 private long nextCheck = System.currentTimeMillis() - 1;
35
36 Date now = new Date();
37
38 SimpleDateFormat sdf;
39
40 /**
41 * The default constructor does nothing.
42 */
43 public DayRollingFileAppender() {
44 }
45
46 public DayRollingFileAppender(Layout layout, String filename,
47 int maxBackupIndex) throws IOException {
48 super(layout, filename, true);
49 this.maxBackupIndex = maxBackupIndex;
50 activateOptions();
51 }
52
53 /**
54 * used for inital the appender
55 */
56 public void activateOptions() {
57 super.activateOptions();
58 if (fileName != null) { // perf.log
59 now.setTime(System.currentTimeMillis());
60 sdf = new SimpleDateFormat(datePattern);
61 File file = new File(fileName);
62 // include the latest time as the file name
63 scheduledFilename = fileName
64 + sdf.format(new Date(file.lastModified()));
65 } else {
66 LogLog.error("File is not set for appender [" + name + "].");
67 }
68 if (maxBackupIndex <= 0) {
69 LogLog
70 .error("maxBackupIndex reset to default value[2],orignal value is:"
71 + maxBackupIndex);
72 maxBackupIndex = 10;
73 }
74 }
75
76 /**
77 * to update, if necessary, rename the file including the current date and
78 * according to the maxBackupIndex, delete the expired file.
79 *
80 */
81 void rollOver() throws IOException {
82
83 String datedFilename = fileName + sdf.format(now);
84 // there is no need to update the file if the current date is the same
85 // as last time
86 if (scheduledFilename.equals(datedFilename)) {
87 return;
88 }
89
90 // close current file, and rename it to datedFilename
91 this.closeFile();
92
93 File target = new File(scheduledFilename);
94 if (target.exists()) {
95 target.delete();
96 }
97
98 File file = new File(fileName);
99 boolean result = file.renameTo(target);
100 if (result) {
101 LogLog.debug(fileName + " -> " + scheduledFilename);
102 } else {
103 LogLog.error("Failed to rename [" + fileName + "] to ["
104 + scheduledFilename + "].");
105 }
106
107 // delete the expired log files according to the maxBackupIndex
108 if (maxBackupIndex > 0) {
109 File folder = new File(file.getParent());
110 List<String> maxBackupIndexDates = getMaxBackupIndexDates();
111 // go through the folder and delete the files which are not in the
112 // permitted dates.
113 for (File ff : folder.listFiles()) {
114 if (ff.getName().startsWith(file.getName())
115 && !ff.getName().equals(file.getName())) {
116 // get the date string from the file name
117 String markedDate = ff.getName().substring(
118 file.getName().length());
119 if (!maxBackupIndexDates.contains(markedDate)) {
120 result = ff.delete();
121 }
122 if (result) {
123 LogLog.debug(ff.getName() + " ->deleted ");
124 } else {
125 LogLog
126 .error("Failed to deleted old DayRollingFileAppender file :"
127 + ff.getName());
128 }
129 }
130 }
131 }
132
133 try {
134 // This will also close the file. This is OK since multiple
135 // close operations are safe.
136 this.setFile(fileName, false, this.bufferedIO, this.bufferSize);
137 } catch (IOException e) {
138 errorHandler.error("setFile(" + fileName + ", false) call failed.");
139 }
140
141 // update the date of the file
142 scheduledFilename = datedFilename;
143 }
144
145 /**
146 * Actual writing occurs here.
147 * */
148 protected void subAppend(LoggingEvent event) {
149 long n = System.currentTimeMillis();
150
151 // roll over when a new day comes, the first time will roll over
152 if (n >= nextCheck) {
153 now.setTime(n);
154 nextCheck = getNextDayCheckPoint(now);
155 try {
156 rollOver();
157 } catch (IOException ioe) {
158 LogLog.error("rollOver() failed.", ioe);
159 }
160 }
161 super.subAppend(event);
162 }
163
164 /**
165 * get the exchange point of next day
166 *
167 * @param now
168 * @return
169 */
170 long getNextDayCheckPoint(Date now) {
171 Calendar calendar = Calendar.getInstance();
172 calendar.setTime(now);
173 calendar.set(Calendar.HOUR_OF_DAY, 0);
174 calendar.set(Calendar.MINUTE, 0);
175 calendar.set(Calendar.SECOND, 0);
176 calendar.set(Calendar.MILLISECOND, 0);
177 calendar.add(Calendar.DATE, 1);
178 return calendar.getTimeInMillis();
179 }
180
181 /**
182 * get the scope of the log file date according to the count of log files which need to be backup
183 *
184 * @return list<'fileName+yyyy-MM-dd'>
185 */
186 List<String> getMaxBackupIndexDates() {
187 List<String> result = new ArrayList<String>();
188 if (maxBackupIndex > 0) {
189 for (int i = 1; i <= maxBackupIndex; i++) {
190 Calendar calendar = Calendar.getInstance();
191 calendar.setTime(now);
192 calendar.set(Calendar.HOUR_OF_DAY, 0);
193 calendar.set(Calendar.MINUTE, 0);
194 calendar.set(Calendar.SECOND, 0);
195 calendar.set(Calendar.MILLISECOND, 0);
196 calendar.add(Calendar.DATE, -i);
197 result.add(sdf.format(calendar.getTime()));
198 }
199 }
200 return result;
201 }
202
203 public int getMaxBackupIndex() {
204 return maxBackupIndex;
205 }
206
207 public void setMaxBackupIndex(int maxBackupIndex) {
208 this.maxBackupIndex = maxBackupIndex;
209 }
210
211 public String getDatePattern() {
212 return datePattern;
213 }
214
215 // public static void main(String[] args) {
216 // DOMConfigurator.configure(xxx.xml);
217 // Logger log = Logger.getLogger("A.log");
218 // log.info("test");
219 // }
220 }
1 DayRollingFileAppender should be the one defined by your own2 import java.io.IOException;
3 import java.text.SimpleDateFormat;
4 import java.util.ArrayList;
5 import java.util.Calendar;
6 import java.util.Date;
7 import java.util.List;
8
9 import org.apache.log4j.FileAppender;
10 import org.apache.log4j.Layout;
11 import org.apache.log4j.helpers.LogLog;
12 import org.apache.log4j.spi.LoggingEvent;
13
14
15 /**
16 * this is an extend class of appender, which is suitable for the specified
17 * datePattern--"yyyy-MM-dd" and the maxBackupIdex is not configurable.
18 *
19 */
20 public class DayRollingFileAppender extends FileAppender {
21
22 /** datepattern was fixed as yyyy-MM-dd */
23 private final String datePattern = "'.'yyyy-MM-dd";
24
25 /** the default max count of log files */
26 private int maxBackupIndex = 10;
27
28 /** file name + date of last time */
29 private String scheduledFilename;
30
31 /**
32 * The next time we estimate a rollover should occur.
33 */
34 private long nextCheck = System.currentTimeMillis() - 1;
35
36 Date now = new Date();
37
38 SimpleDateFormat sdf;
39
40 /**
41 * The default constructor does nothing.
42 */
43 public DayRollingFileAppender() {
44 }
45
46 public DayRollingFileAppender(Layout layout, String filename,
47 int maxBackupIndex) throws IOException {
48 super(layout, filename, true);
49 this.maxBackupIndex = maxBackupIndex;
50 activateOptions();
51 }
52
53 /**
54 * used for inital the appender
55 */
56 public void activateOptions() {
57 super.activateOptions();
58 if (fileName != null) { // perf.log
59 now.setTime(System.currentTimeMillis());
60 sdf = new SimpleDateFormat(datePattern);
61 File file = new File(fileName);
62 // include the latest time as the file name
63 scheduledFilename = fileName
64 + sdf.format(new Date(file.lastModified()));
65 } else {
66 LogLog.error("File is not set for appender [" + name + "].");
67 }
68 if (maxBackupIndex <= 0) {
69 LogLog
70 .error("maxBackupIndex reset to default value[2],orignal value is:"
71 + maxBackupIndex);
72 maxBackupIndex = 10;
73 }
74 }
75
76 /**
77 * to update, if necessary, rename the file including the current date and
78 * according to the maxBackupIndex, delete the expired file.
79 *
80 */
81 void rollOver() throws IOException {
82
83 String datedFilename = fileName + sdf.format(now);
84 // there is no need to update the file if the current date is the same
85 // as last time
86 if (scheduledFilename.equals(datedFilename)) {
87 return;
88 }
89
90 // close current file, and rename it to datedFilename
91 this.closeFile();
92
93 File target = new File(scheduledFilename);
94 if (target.exists()) {
95 target.delete();
96 }
97
98 File file = new File(fileName);
99 boolean result = file.renameTo(target);
100 if (result) {
101 LogLog.debug(fileName + " -> " + scheduledFilename);
102 } else {
103 LogLog.error("Failed to rename [" + fileName + "] to ["
104 + scheduledFilename + "].");
105 }
106
107 // delete the expired log files according to the maxBackupIndex
108 if (maxBackupIndex > 0) {
109 File folder = new File(file.getParent());
110 List<String> maxBackupIndexDates = getMaxBackupIndexDates();
111 // go through the folder and delete the files which are not in the
112 // permitted dates.
113 for (File ff : folder.listFiles()) {
114 if (ff.getName().startsWith(file.getName())
115 && !ff.getName().equals(file.getName())) {
116 // get the date string from the file name
117 String markedDate = ff.getName().substring(
118 file.getName().length());
119 if (!maxBackupIndexDates.contains(markedDate)) {
120 result = ff.delete();
121 }
122 if (result) {
123 LogLog.debug(ff.getName() + " ->deleted ");
124 } else {
125 LogLog
126 .error("Failed to deleted old DayRollingFileAppender file :"
127 + ff.getName());
128 }
129 }
130 }
131 }
132
133 try {
134 // This will also close the file. This is OK since multiple
135 // close operations are safe.
136 this.setFile(fileName, false, this.bufferedIO, this.bufferSize);
137 } catch (IOException e) {
138 errorHandler.error("setFile(" + fileName + ", false) call failed.");
139 }
140
141 // update the date of the file
142 scheduledFilename = datedFilename;
143 }
144
145 /**
146 * Actual writing occurs here.
147 * */
148 protected void subAppend(LoggingEvent event) {
149 long n = System.currentTimeMillis();
150
151 // roll over when a new day comes, the first time will roll over
152 if (n >= nextCheck) {
153 now.setTime(n);
154 nextCheck = getNextDayCheckPoint(now);
155 try {
156 rollOver();
157 } catch (IOException ioe) {
158 LogLog.error("rollOver() failed.", ioe);
159 }
160 }
161 super.subAppend(event);
162 }
163
164 /**
165 * get the exchange point of next day
166 *
167 * @param now
168 * @return
169 */
170 long getNextDayCheckPoint(Date now) {
171 Calendar calendar = Calendar.getInstance();
172 calendar.setTime(now);
173 calendar.set(Calendar.HOUR_OF_DAY, 0);
174 calendar.set(Calendar.MINUTE, 0);
175 calendar.set(Calendar.SECOND, 0);
176 calendar.set(Calendar.MILLISECOND, 0);
177 calendar.add(Calendar.DATE, 1);
178 return calendar.getTimeInMillis();
179 }
180
181 /**
182 * get the scope of the log file date according to the count of log files which need to be backup
183 *
184 * @return list<'fileName+yyyy-MM-dd'>
185 */
186 List<String> getMaxBackupIndexDates() {
187 List<String> result = new ArrayList<String>();
188 if (maxBackupIndex > 0) {
189 for (int i = 1; i <= maxBackupIndex; i++) {
190 Calendar calendar = Calendar.getInstance();
191 calendar.setTime(now);
192 calendar.set(Calendar.HOUR_OF_DAY, 0);
193 calendar.set(Calendar.MINUTE, 0);
194 calendar.set(Calendar.SECOND, 0);
195 calendar.set(Calendar.MILLISECOND, 0);
196 calendar.add(Calendar.DATE, -i);
197 result.add(sdf.format(calendar.getTime()));
198 }
199 }
200 return result;
201 }
202
203 public int getMaxBackupIndex() {
204 return maxBackupIndex;
205 }
206
207 public void setMaxBackupIndex(int maxBackupIndex) {
208 this.maxBackupIndex = maxBackupIndex;
209 }
210
211 public String getDatePattern() {
212 return datePattern;
213 }
214
215 // public static void main(String[] args) {
216 // DOMConfigurator.configure(xxx.xml);
217 // Logger log = Logger.getLogger("A.log");
218 // log.info("test");
219 // }
220 }
2 log file should be the full path
3 remove the date pattern