View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.core.appender;
18  
19  import java.util.HashMap;
20  import java.util.Map;
21  
22  import org.apache.logging.log4j.core.Filter;
23  import org.apache.logging.log4j.core.Layout;
24  import org.apache.logging.log4j.core.LogEvent;
25  import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
26  import org.apache.logging.log4j.core.appender.rolling.FastRollingFileManager;
27  import org.apache.logging.log4j.core.appender.rolling.RollingFileManager;
28  import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy;
29  import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
30  import org.apache.logging.log4j.core.config.Configuration;
31  import org.apache.logging.log4j.core.config.plugins.Plugin;
32  import org.apache.logging.log4j.core.config.plugins.PluginAttr;
33  import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
34  import org.apache.logging.log4j.core.config.plugins.PluginElement;
35  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
36  import org.apache.logging.log4j.core.layout.PatternLayout;
37  import org.apache.logging.log4j.core.net.Advertiser;
38  
39  /**
40   * An appender that writes to random access files and can roll over at
41   * intervals.
42   */
43  @Plugin(name = "FastRollingFile", type = "Core", elementType = "appender", printObject = true)
44  public final class FastRollingFileAppender extends AbstractOutputStreamAppender {
45  
46      private final String fileName;
47      private final String filePattern;
48      private Object advertisement;
49      private final Advertiser advertiser;
50  
51      private FastRollingFileAppender(String name, Layout<?> layout,
52              Filter filter, RollingFileManager manager, String fileName,
53              String filePattern, boolean handleException,
54              boolean immediateFlush, Advertiser advertiser) {
55          super(name, layout, filter, handleException, immediateFlush, manager);
56          if (advertiser != null) {
57              Map<String, String> configuration = new HashMap<String, String>(
58                      layout.getContentFormat());
59              configuration.put("contentType", layout.getContentType());
60              configuration.put("name", name);
61              advertisement = advertiser.advertise(configuration);
62          }
63          this.fileName = fileName;
64          this.filePattern = filePattern;
65          this.advertiser = advertiser;
66      }
67  
68      @Override
69      public void stop() {
70          super.stop();
71          if (advertiser != null) {
72              advertiser.unadvertise(advertisement);
73          }
74      }
75  
76      /**
77       * Write the log entry rolling over the file when required.
78       * 
79       * @param event The LogEvent.
80       */
81      @Override
82      public void append(final LogEvent event) {
83          FastRollingFileManager manager = (FastRollingFileManager) getManager();
84          manager.checkRollover(event);
85  
86          // Leverage the nice batching behaviour of async Loggers/Appenders:
87          // we can signal the file manager that it needs to flush the buffer
88          // to disk at the end of a batch.
89          // From a user's point of view, this means that all log events are
90          // _always_ available in the log file, without incurring the overhead
91          // of immediateFlush=true.
92          manager.setEndOfBatch(event.isEndOfBatch());
93          super.append(event);
94      }
95  
96      /**
97       * Returns the File name for the Appender.
98       * 
99       * @return The file name.
100      */
101     public String getFileName() {
102         return fileName;
103     }
104 
105     /**
106      * Returns the file pattern used when rolling over.
107      * 
108      * @return The file pattern.
109      */
110     public String getFilePattern() {
111         return filePattern;
112     }
113 
114     /**
115      * Create a FastRollingFileAppender.
116      * 
117      * @param fileName The name of the file that is actively written to.
118      *            (required).
119      * @param filePattern The pattern of the file name to use on rollover.
120      *            (required).
121      * @param append If true, events are appended to the file. If false, the
122      *            file is overwritten when opened. Defaults to "true"
123      * @param name The name of the Appender (required).
124      * @param immediateFlush When true, events are immediately flushed. Defaults
125      *            to "true".
126      * @param policy The triggering policy. (required).
127      * @param strategy The rollover strategy. Defaults to
128      *            DefaultRolloverStrategy.
129      * @param layout The layout to use (defaults to the default PatternLayout).
130      * @param filter The Filter or null.
131      * @param suppress "true" if exceptions should be hidden from the
132      *            application, "false" otherwise. The default is "true".
133      * @param advertise "true" if the appender configuration should be
134      *            advertised, "false" otherwise.
135      * @param advertiseURI The advertised URI which can be used to retrieve the
136      *            file contents.
137      * @param config The Configuration.
138      * @return A FastRollingFileAppender.
139      */
140     @PluginFactory
141     public static FastRollingFileAppender createAppender(
142             @PluginAttr("fileName") final String fileName,
143             @PluginAttr("filePattern") final String filePattern,
144             @PluginAttr("append") final String append,
145             @PluginAttr("name") final String name,
146             @PluginAttr("immediateFlush") final String immediateFlush,
147             @PluginElement("policy") final TriggeringPolicy policy,
148             @PluginElement("strategy") RolloverStrategy strategy,
149             @PluginElement("layout") Layout<?> layout,
150             @PluginElement("filter") final Filter filter,
151             @PluginAttr("suppressExceptions") final String suppress,
152             @PluginAttr("advertise") final String advertise,
153             @PluginAttr("advertiseURI") final String advertiseURI,
154             @PluginConfiguration final Configuration config) {
155 
156         final boolean isAppend = append == null ? true : Boolean
157                 .valueOf(append);
158         final boolean handleExceptions = suppress == null ? true : Boolean
159                 .valueOf(suppress);
160         final boolean isFlush = immediateFlush == null ? true : Boolean
161                 .valueOf(immediateFlush);
162         boolean isAdvertise = advertise == null ? false : Boolean
163                 .valueOf(advertise);
164 
165         if (name == null) {
166             LOGGER.error("No name provided for FileAppender");
167             return null;
168         }
169 
170         if (fileName == null) {
171             LOGGER.error("No filename was provided for FileAppender with name "
172                     + name);
173             return null;
174         }
175 
176         if (filePattern == null) {
177             LOGGER.error("No filename pattern provided for FileAppender with name "
178                     + name);
179             return null;
180         }
181 
182         if (policy == null) {
183             LOGGER.error("A TriggeringPolicy must be provided");
184             return null;
185         }
186 
187         if (strategy == null) {
188             strategy = DefaultRolloverStrategy.createStrategy(null, null,
189                     "true", config);
190         }
191 
192         final FastRollingFileManager manager = FastRollingFileManager
193                 .getFastRollingFileManager(fileName, filePattern, isAppend,
194                         isFlush, policy, strategy, advertiseURI);
195         if (manager == null) {
196             return null;
197         }
198 
199         if (layout == null) {
200             layout = PatternLayout.createLayout(null, null, null, null);
201         }
202 
203         return new FastRollingFileAppender(name, layout, filter, manager,
204                 fileName, filePattern, handleExceptions, isFlush,
205                 isAdvertise ? config.getAdvertiser() : null);
206     }
207 }