    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 java.io.Serializable;
    020    import java.util.HashMap;
    021    import java.util.Map;
    022    import java.util.zip.Deflater;
    023
    024    import org.apache.logging.log4j.core.Filter;
    025    import org.apache.logging.log4j.core.Layout;
    026    import org.apache.logging.log4j.core.LogEvent;
    027    import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
    028    import org.apache.logging.log4j.core.appender.rolling.RollingFileManager;
    029    import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy;
    030    import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
    031    import org.apache.logging.log4j.core.config.Configuration;
    032    import org.apache.logging.log4j.core.config.plugins.Plugin;
    033    import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
    034    import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
    035    import org.apache.logging.log4j.core.config.plugins.PluginElement;
    036    import org.apache.logging.log4j.core.config.plugins.PluginFactory;
    037    import org.apache.logging.log4j.core.layout.PatternLayout;
    038    import org.apache.logging.log4j.core.net.Advertiser;
    039    import org.apache.logging.log4j.core.util.Booleans;
    040    import org.apache.logging.log4j.core.util.Integers;
    041
    042    /**
    043     * An appender that writes to files and can roll over at intervals.
    044     */
    045    @Plugin(name = "RollingFile", category = "Core", elementType = "appender", printObject = true)
    046    public final class RollingFileAppender extends AbstractOutputStreamAppender<RollingFileManager> {
    047
    048        private static final int DEFAULT_BUFFER_SIZE = 8192;
    049        private static final long serialVersionUID = 1L;
    050
    051        private final String fileName;
    052        private final String filePattern;
    053        private Object advertisement;
    054        private final Advertiser advertiser;
    055
    056
    057        private RollingFileAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
    058                final RollingFileManager manager, final String fileName, final String filePattern,
    059                final boolean ignoreExceptions, final boolean immediateFlush, final Advertiser advertiser) {
    060            super(name, layout, filter, ignoreExceptions, immediateFlush, manager);
    061            if (advertiser != null) {
    062                final Map<String, String> configuration = new HashMap<String, String>(layout.getContentFormat());
    063                configuration.put("contentType", layout.getContentType());
    064                configuration.put("name", name);
    065                advertisement = advertiser.advertise(configuration);
    066            }
    067            this.fileName = fileName;
    068            this.filePattern = filePattern;
    069            this.advertiser = advertiser;
    070        }
    071
    072        @Override
    073        public void stop() {
    074            super.stop();
    075            if (advertiser != null) {
    076                advertiser.unadvertise(advertisement);
    077            }
    078        }
    079
    080        /**
    081         * Write the log entry rolling over the file when required.
    082
    083         * @param event The LogEvent.
    084         */
    085        @Override
    086        public void append(final LogEvent event) {
    087            getManager().checkRollover(event);
    088            super.append(event);
    089        }
    090
    091        /**
    092         * Returns the File name for the Appender.
    093         * @return The file name.
    094         */
    095        public String getFileName() {
    096            return fileName;
    097        }
    098
    099        /**
    100         * Returns the file pattern used when rolling over.
    101         * @return The file pattern.
    102         */
    103        public String getFilePattern() {
    104            return filePattern;
    105        }
    106
    107        /**
    108         * Create a RollingFileAppender.
    109         * @param fileName The name of the file that is actively written to. (required).
    110         * @param filePattern The pattern of the file name to use on rollover. (required).
    111         * @param append If true, events are appended to the file. If false, the file
    112         * is overwritten when opened. Defaults to "true"
    113         * @param name The name of the Appender (required).
    114         * @param bufferedIO When true, I/O will be buffered. Defaults to "true".
    115         * @param bufferSizeStr buffer size for buffered IO (default is 8192).
    116         * @param immediateFlush When true, events are immediately flushed. Defaults to "true".
    117         * @param policy The triggering policy. (required).
    118         * @param strategy The rollover strategy. Defaults to DefaultRolloverStrategy.
    119         * @param layout The layout to use (defaults to the default PatternLayout).
    120         * @param filter The Filter or null.
    121         * @param ignore If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise
    122         *               they are propagated to the caller.
    123         * @param advertise "true" if the appender configuration should be advertised, "false" otherwise.
    124         * @param advertiseURI The advertised URI which can be used to retrieve the file contents.
    125         * @param config The Configuration.
    126         * @return A RollingFileAppender.
    127         */
    128        @PluginFactory
    129        public static RollingFileAppender createAppender(
    130                @PluginAttribute("fileName") final String fileName,
    131                @PluginAttribute("filePattern") final String filePattern,
    132                @PluginAttribute("append") final String append,
    133                @PluginAttribute("name") final String name,
    134                @PluginAttribute("bufferedIO") final String bufferedIO,
    135                @PluginAttribute("bufferSize") final String bufferSizeStr,
    136                @PluginAttribute("immediateFlush") final String immediateFlush,
    137                @PluginElement("Policy") final TriggeringPolicy policy,
    138                @PluginElement("Strategy") RolloverStrategy strategy,
    139                @PluginElement("Layout") Layout<? extends Serializable> layout,
    140                @PluginElement("Filter") final Filter filter,
    141                @PluginAttribute("ignoreExceptions") final String ignore,
    142                @PluginAttribute("advertise") final String advertise,
    143                @PluginAttribute("advertiseURI") final String advertiseURI,
    144                @PluginConfiguration final Configuration config) {
    145
    146            final boolean isAppend = Booleans.parseBoolean(append, true);
    147            final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
    148            final boolean isBuffered = Booleans.parseBoolean(bufferedIO, true);
    149            final boolean isFlush = Booleans.parseBoolean(immediateFlush, true);
    150            final boolean isAdvertise = Boolean.parseBoolean(advertise);
    151            final int bufferSize = Integers.parseInt(bufferSizeStr, DEFAULT_BUFFER_SIZE);
    152            if (!isBuffered && bufferSize > 0) {
    153                LOGGER.warn("The bufferSize is set to {} but bufferedIO is not true: {}", bufferSize, bufferedIO);
    154            }
    155            if (name == null) {
    156                LOGGER.error("No name provided for FileAppender");
    157                return null;
    158            }
    159
    160            if (fileName == null) {
    161                LOGGER.error("No filename was provided for FileAppender with name "  + name);
    162                return null;
    163            }
    164
    165            if (filePattern == null) {
    166                LOGGER.error("No filename pattern provided for FileAppender with name "  + name);
    167                return null;
    168            }
    169
    170            if (policy == null) {
    171                LOGGER.error("A TriggeringPolicy must be provided");
    172                return null;
    173            }
    174
    175            if (strategy == null) {
    176                strategy = DefaultRolloverStrategy.createStrategy(null, null, null,
    177                        String.valueOf(Deflater.DEFAULT_COMPRESSION), config);
    178            }
    179
    180            if (layout == null) {
    181                layout = PatternLayout.createDefaultLayout();
    182            }
    183
    184            final RollingFileManager manager = RollingFileManager.getFileManager(fileName, filePattern, isAppend,
    185                isBuffered, policy, strategy, advertiseURI, layout, bufferSize);
    186            if (manager == null) {
    187                return null;
    188            }
    189
    190            return new RollingFileAppender(name, layout, filter, manager, fileName, filePattern,
    191                    ignoreExceptions, isFlush, isAdvertise ? config.getAdvertiser() : null);
    192        }
    193    }