1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.appender;
18
19 import java.io.Serializable;
20 import java.util.HashMap;
21 import java.util.Map;
22 import java.util.concurrent.TimeUnit;
23 import java.util.zip.Deflater;
24
25 import org.apache.logging.log4j.core.Appender;
26 import org.apache.logging.log4j.core.Filter;
27 import org.apache.logging.log4j.core.Layout;
28 import org.apache.logging.log4j.core.LogEvent;
29 import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
30 import org.apache.logging.log4j.core.appender.rolling.RollingFileManager;
31 import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy;
32 import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
33 import org.apache.logging.log4j.core.config.Configuration;
34 import org.apache.logging.log4j.core.config.plugins.Plugin;
35 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
36 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
37 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
38 import org.apache.logging.log4j.core.config.plugins.PluginElement;
39 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
40 import org.apache.logging.log4j.core.net.Advertiser;
41 import org.apache.logging.log4j.core.util.Booleans;
42 import org.apache.logging.log4j.core.util.Integers;
43
44
45
46
47 @Plugin(name = RollingFileAppender.PLUGIN_NAME, category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
48 public final class RollingFileAppender extends AbstractOutputStreamAppender<RollingFileManager> {
49
50 public static final String PLUGIN_NAME = "RollingFile";
51
52
53
54
55
56
57
58 public static class Builder<B extends Builder<B>> extends AbstractOutputStreamAppender.Builder<B>
59 implements org.apache.logging.log4j.core.util.Builder<RollingFileAppender> {
60
61 @PluginBuilderAttribute
62 @Required
63 private String fileName;
64
65 @PluginBuilderAttribute
66 @Required
67 private String filePattern;
68
69 @PluginBuilderAttribute
70 private boolean append = true;
71
72 @PluginBuilderAttribute
73 private boolean locking;
74
75 @PluginElement("Policy")
76 @Required
77 private TriggeringPolicy policy;
78
79 @PluginElement("Strategy")
80 private RolloverStrategy strategy;
81
82 @PluginBuilderAttribute
83 private boolean advertise;
84
85 @PluginBuilderAttribute
86 private String advertiseUri;
87
88 @PluginBuilderAttribute
89 private boolean createOnDemand;
90
91 @PluginConfiguration
92 private Configuration configuration;
93
94 @Override
95 public RollingFileAppender build() {
96
97
98 final boolean isBufferedIo = isBufferedIo();
99 final int bufferSize = getBufferSize();
100 if (getName() == null) {
101 LOGGER.error("RollingFileAppender '{}': No name provided.", getName());
102 return null;
103 }
104
105 if (!isBufferedIo && bufferSize > 0) {
106 LOGGER.warn("RollingFileAppender '{}': The bufferSize is set to {} but bufferedIO is not true", getName(), bufferSize);
107 }
108
109 if (fileName == null) {
110 LOGGER.error("RollingFileAppender '{}': No file name provided.", getName());
111 return null;
112 }
113
114 if (filePattern == null) {
115 LOGGER.error("RollingFileAppender '{}': No file name pattern provided.", getName());
116 return null;
117 }
118
119 if (policy == null) {
120 LOGGER.error("RollingFileAppender '{}': No TriggeringPolicy provided.", getName());
121 return null;
122 }
123
124 if (strategy == null) {
125 strategy = DefaultRolloverStrategy.createStrategy(null, null, null,
126 String.valueOf(Deflater.DEFAULT_COMPRESSION), null, true, configuration);
127 }
128
129 if (strategy == null) {
130 strategy = DefaultRolloverStrategy.createStrategy(null, null, null,
131 String.valueOf(Deflater.DEFAULT_COMPRESSION), null, true, configuration);
132 }
133
134 final Layout<? extends Serializable> layout = getOrCreateLayout();
135 final RollingFileManager manager = RollingFileManager.getFileManager(fileName, filePattern, append,
136 isBufferedIo, policy, strategy, advertiseUri, layout, bufferSize, isImmediateFlush(),
137 createOnDemand, configuration);
138 if (manager == null) {
139 return null;
140 }
141
142 manager.initialize();
143
144 return new RollingFileAppender(getName(), layout, getFilter(), manager, fileName, filePattern,
145 isIgnoreExceptions(), isImmediateFlush(), advertise ? configuration.getAdvertiser() : null);
146 }
147
148 public String getAdvertiseUri() {
149 return advertiseUri;
150 }
151
152 public Configuration getConfiguration() {
153 return configuration;
154 }
155
156 public String getFileName() {
157 return fileName;
158 }
159
160 public boolean isAdvertise() {
161 return advertise;
162 }
163
164 public boolean isAppend() {
165 return append;
166 }
167
168 public boolean isCreateOnDemand() {
169 return createOnDemand;
170 }
171
172 public boolean isLocking() {
173 return locking;
174 }
175
176 public B withAdvertise(final boolean advertise) {
177 this.advertise = advertise;
178 return asBuilder();
179 }
180
181 public B withAdvertiseUri(final String advertiseUri) {
182 this.advertiseUri = advertiseUri;
183 return asBuilder();
184 }
185
186 public B withAppend(final boolean append) {
187 this.append = append;
188 return asBuilder();
189 }
190
191 public B withConfiguration(final Configuration config) {
192 this.configuration = config;
193 return asBuilder();
194 }
195
196 public B withFileName(final String fileName) {
197 this.fileName = fileName;
198 return asBuilder();
199 }
200
201 public B withCreateOnDemand(final boolean createOnDemand) {
202 this.createOnDemand = createOnDemand;
203 return asBuilder();
204 }
205
206 public B withLocking(final boolean locking) {
207 this.locking = locking;
208 return asBuilder();
209 }
210
211 public String getFilePattern() {
212 return filePattern;
213 }
214
215 public TriggeringPolicy getPolicy() {
216 return policy;
217 }
218
219 public RolloverStrategy getStrategy() {
220 return strategy;
221 }
222
223 public B withFilePattern(final String filePattern) {
224 this.filePattern = filePattern;
225 return asBuilder();
226 }
227
228 public B withPolicy(final TriggeringPolicy policy) {
229 this.policy = policy;
230 return asBuilder();
231 }
232
233 public B withStrategy(final RolloverStrategy strategy) {
234 this.strategy = strategy;
235 return asBuilder();
236 }
237
238 }
239
240 private static final int DEFAULT_BUFFER_SIZE = 8192;
241
242 private final String fileName;
243 private final String filePattern;
244 private Object advertisement;
245 private final Advertiser advertiser;
246
247 private RollingFileAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
248 final RollingFileManager manager, final String fileName, final String filePattern,
249 final boolean ignoreExceptions, final boolean immediateFlush, final Advertiser advertiser) {
250 super(name, layout, filter, ignoreExceptions, immediateFlush, manager);
251 if (advertiser != null) {
252 final Map<String, String> configuration = new HashMap<>(layout.getContentFormat());
253 configuration.put("contentType", layout.getContentType());
254 configuration.put("name", name);
255 advertisement = advertiser.advertise(configuration);
256 }
257 this.fileName = fileName;
258 this.filePattern = filePattern;
259 this.advertiser = advertiser;
260 }
261
262 @Override
263 public boolean stop(final long timeout, final TimeUnit timeUnit) {
264 setStopping();
265 final boolean stopped = super.stop(timeout, timeUnit, false);
266 if (advertiser != null) {
267 advertiser.unadvertise(advertisement);
268 }
269 setStopped();
270 return stopped;
271 }
272
273
274
275
276
277
278 @Override
279 public void append(final LogEvent event) {
280 getManager().checkRollover(event);
281 super.append(event);
282 }
283
284
285
286
287
288 public String getFileName() {
289 return fileName;
290 }
291
292
293
294
295
296 public String getFilePattern() {
297 return filePattern;
298 }
299
300
301
302
303
304
305 public <T extends TriggeringPolicy> T getTriggeringPolicy() {
306 return getManager().getTriggeringPolicy();
307 }
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331 @Deprecated
332 public static RollingFileAppender createAppender(
333
334 final String fileName,
335 final String filePattern,
336 final String append,
337 final String name,
338 final String bufferedIO,
339 final String bufferSizeStr,
340 final String immediateFlush,
341 final TriggeringPolicy policy,
342 final RolloverStrategy strategy,
343 final Layout<? extends Serializable> layout,
344 final Filter filter,
345 final String ignore,
346 final String advertise,
347 final String advertiseUri,
348 final Configuration config) {
349
350 final int bufferSize = Integers.parseInt(bufferSizeStr, DEFAULT_BUFFER_SIZE);
351
352 return newBuilder()
353 .withAdvertise(Boolean.parseBoolean(advertise))
354 .withAdvertiseUri(advertiseUri)
355 .withAppend(Booleans.parseBoolean(append, true))
356 .withBufferedIo(Booleans.parseBoolean(bufferedIO, true))
357 .withBufferSize(bufferSize)
358 .withConfiguration(config)
359 .withFileName(fileName)
360 .withFilePattern(filePattern)
361 .withFilter(filter)
362 .withIgnoreExceptions(Booleans.parseBoolean(ignore, true))
363 .withImmediateFlush(Booleans.parseBoolean(immediateFlush, true))
364 .withLayout(layout)
365 .withCreateOnDemand(false)
366 .withLocking(false)
367 .withName(name)
368 .withPolicy(policy)
369 .withStrategy(strategy)
370 .build();
371
372 }
373
374 @PluginBuilderFactory
375 public static <B extends Builder<B>> B newBuilder() {
376 return new Builder<B>().asBuilder();
377 }
378 }