001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017 package org.apache.logging.log4j.core.appender;
018
019 import org.apache.logging.log4j.core.Filter;
020 import org.apache.logging.log4j.core.Layout;
021 import org.apache.logging.log4j.core.LogEvent;
022 import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
023 import org.apache.logging.log4j.core.appender.rolling.RollingFileManager;
024 import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy;
025 import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
026 import org.apache.logging.log4j.core.config.Configuration;
027 import org.apache.logging.log4j.core.config.plugins.Plugin;
028 import org.apache.logging.log4j.core.config.plugins.PluginAttr;
029 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
030 import org.apache.logging.log4j.core.config.plugins.PluginElement;
031 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
032 import org.apache.logging.log4j.core.layout.PatternLayout;
033 import org.apache.logging.log4j.core.net.Advertiser;
034
035 import java.io.Serializable;
036 import java.util.HashMap;
037 import java.util.Map;
038
039 /**
040 * An appender that writes to files and can roll over at intervals.
041 */
042 @Plugin(name = "RollingFile", category = "Core", elementType = "appender", printObject = true)
043 public final class RollingFileAppender<T extends Serializable> extends AbstractOutputStreamAppender<T> {
044
045 private final String fileName;
046 private final String filePattern;
047 private Object advertisement;
048 private final Advertiser advertiser;
049
050
051 private RollingFileAppender(final String name, final Layout<T> layout, final Filter filter,
052 final RollingFileManager manager, final String fileName,
053 final String filePattern, final boolean handleException, final boolean immediateFlush,
054 Advertiser advertiser) {
055 super(name, layout, filter, handleException, immediateFlush, manager);
056 if (advertiser != null)
057 {
058 Map<String, String> configuration = new HashMap<String, String>(layout.getContentFormat());
059 configuration.put("contentType", layout.getContentType());
060 configuration.put("name", name);
061 advertisement = advertiser.advertise(configuration);
062 }
063 this.fileName = fileName;
064 this.filePattern = filePattern;
065 this.advertiser = advertiser;
066 }
067
068 @Override
069 public void stop() {
070 super.stop();
071 if (advertiser != null) {
072 advertiser.unadvertise(advertisement);
073 }
074 }
075
076 /**
077 * Write the log entry rolling over the file when required.
078
079 * @param event The LogEvent.
080 */
081 @Override
082 public void append(final LogEvent event) {
083 ((RollingFileManager) getManager()).checkRollover(event);
084 super.append(event);
085 }
086
087 /**
088 * Returns the File name for the Appender.
089 * @return The file name.
090 */
091 public String getFileName() {
092 return fileName;
093 }
094
095 /**
096 * Returns the file pattern used when rolling over.
097 * @return The file pattern.
098 */
099 public String getFilePattern() {
100 return filePattern;
101 }
102
103 /**
104 * Create a RollingFileAppender.
105 * @param fileName The name of the file that is actively written to. (required).
106 * @param filePattern The pattern of the file name to use on rollover. (required).
107 * @param append If true, events are appended to the file. If false, the file
108 * is overwritten when opened. Defaults to "true"
109 * @param name The name of the Appender (required).
110 * @param bufferedIO When true, I/O will be buffered. Defaults to "true".
111 * @param immediateFlush When true, events are immediately flushed. Defaults to "true".
112 * @param policy The triggering policy. (required).
113 * @param strategy The rollover strategy. Defaults to DefaultRolloverStrategy.
114 * @param layout The layout to use (defaults to the default PatternLayout).
115 * @param filter The Filter or null.
116 * @param suppress "true" if exceptions should be hidden from the application, "false" otherwise.
117 * The default is "true".
118 * @param advertise "true" if the appender configuration should be advertised, "false" otherwise.
119 * @param advertiseURI The advertised URI which can be used to retrieve the file contents.
120 * @param config The Configuration.
121 * @return A RollingFileAppender.
122 */
123 @PluginFactory
124 public static <S extends Serializable> RollingFileAppender<S> createAppender(
125 @PluginAttr("fileName") final String fileName,
126 @PluginAttr("filePattern") final String filePattern,
127 @PluginAttr("append") final String append,
128 @PluginAttr("name") final String name,
129 @PluginAttr("bufferedIO") final String bufferedIO,
130 @PluginAttr("immediateFlush") final String immediateFlush,
131 @PluginElement("policy") final TriggeringPolicy policy,
132 @PluginElement("strategy") RolloverStrategy strategy,
133 @PluginElement("layout") Layout<S> layout,
134 @PluginElement("filter") final Filter filter,
135 @PluginAttr("suppressExceptions") final String suppress,
136 @PluginAttr("advertise") final String advertise,
137 @PluginAttr("advertiseURI") final String advertiseURI,
138 @PluginConfiguration final Configuration config) {
139
140 final boolean isAppend = append == null ? true : Boolean.valueOf(append);
141 final boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
142 final boolean isBuffered = bufferedIO == null ? true : Boolean.valueOf(bufferedIO);
143 final boolean isFlush = immediateFlush == null ? true : Boolean.valueOf(immediateFlush);
144 boolean isAdvertise = advertise == null ? false : Boolean.valueOf(advertise);
145 if (name == null) {
146 LOGGER.error("No name provided for FileAppender");
147 return null;
148 }
149
150 if (fileName == null) {
151 LOGGER.error("No filename was provided for FileAppender with name " + name);
152 return null;
153 }
154
155 if (filePattern == null) {
156 LOGGER.error("No filename pattern provided for FileAppender with name " + name);
157 return null;
158 }
159
160 if (policy == null) {
161 LOGGER.error("A TriggeringPolicy must be provided");
162 return null;
163 }
164
165 if (strategy == null) {
166 strategy = DefaultRolloverStrategy.createStrategy(null, null, "true", config);
167 }
168
169 final RollingFileManager manager = RollingFileManager.getFileManager(fileName, filePattern, isAppend,
170 isBuffered, policy, strategy, advertiseURI);
171 if (manager == null) {
172 return null;
173 }
174
175 if (layout == null) {
176 @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
177 Layout<S> l = (Layout<S>)PatternLayout.createLayout(null, null, null, null);
178 layout = l;
179 }
180
181 return new RollingFileAppender<S>(name, layout, filter, manager, fileName, filePattern,
182 handleExceptions, isFlush, isAdvertise ? config.getAdvertiser() : null);
183 }
184 }