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 */ 017package org.apache.logging.log4j.core.appender.rolling; 018 019import java.util.concurrent.ThreadLocalRandom; 020import java.util.concurrent.TimeUnit; 021 022import org.apache.logging.log4j.core.Core; 023import org.apache.logging.log4j.core.LogEvent; 024import org.apache.logging.log4j.core.config.plugins.Plugin; 025import org.apache.logging.log4j.core.config.plugins.PluginAttribute; 026import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute; 027import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory; 028import org.apache.logging.log4j.core.util.Integers; 029 030/** 031 * Rolls a file over based on time. 032 */ 033@Plugin(name = "TimeBasedTriggeringPolicy", category = Core.CATEGORY_NAME, printObject = true) 034public final class TimeBasedTriggeringPolicy extends AbstractTriggeringPolicy { 035 036 037 public static class Builder implements org.apache.logging.log4j.core.util.Builder<TimeBasedTriggeringPolicy> { 038 039 @PluginBuilderAttribute 040 private int interval = 1; 041 042 @PluginBuilderAttribute 043 private boolean modulate = false; 044 045 @PluginBuilderAttribute 046 private int maxRandomDelay = 0; 047 048 @Override 049 public TimeBasedTriggeringPolicy build() { 050 final long maxRandomDelayMillis = TimeUnit.SECONDS.toMillis(maxRandomDelay); 051 return new TimeBasedTriggeringPolicy(interval, modulate, maxRandomDelayMillis); 052 } 053 054 public int getInterval() { 055 return interval; 056 } 057 058 public boolean isModulate() { 059 return modulate; 060 } 061 062 public int getMaxRandomDelay() { 063 return maxRandomDelay; 064 } 065 066 public Builder withInterval(final int interval){ 067 this.interval = interval; 068 return this; 069 } 070 071 public Builder withModulate(final boolean modulate){ 072 this.modulate = modulate; 073 return this; 074 } 075 076 public Builder withMaxRandomDelay(final int maxRandomDelay){ 077 this.maxRandomDelay = maxRandomDelay; 078 return this; 079 } 080 081 } 082 083 private long nextRolloverMillis; 084 private final int interval; 085 private final boolean modulate; 086 private final long maxRandomDelayMillis; 087 088 private RollingFileManager manager; 089 090 private TimeBasedTriggeringPolicy(final int interval, final boolean modulate, final long maxRandomDelayMillis) { 091 this.interval = interval; 092 this.modulate = modulate; 093 this.maxRandomDelayMillis = maxRandomDelayMillis; 094 } 095 096 public int getInterval() { 097 return interval; 098 } 099 100 public long getNextRolloverMillis() { 101 return nextRolloverMillis; 102 } 103 104 /** 105 * Initializes the policy. 106 * @param aManager The RollingFileManager. 107 */ 108 @Override 109 public void initialize(final RollingFileManager aManager) { 110 this.manager = aManager; 111 112 // LOG4J2-531: call getNextTime twice to force initialization of both prevFileTime and nextFileTime 113 aManager.getPatternProcessor().getNextTime(aManager.getFileTime(), interval, modulate); 114 115 nextRolloverMillis = ThreadLocalRandom.current().nextLong(0, 1 + maxRandomDelayMillis) 116 + aManager.getPatternProcessor().getNextTime(aManager.getFileTime(), interval, modulate); 117 } 118 119 /** 120 * Determines whether a rollover should occur. 121 * @param event A reference to the currently event. 122 * @return true if a rollover should occur. 123 */ 124 @Override 125 public boolean isTriggeringEvent(final LogEvent event) { 126 if (manager.getFileSize() == 0) { 127 return false; 128 } 129 final long nowMillis = event.getTimeMillis(); 130 if (nowMillis >= nextRolloverMillis) { 131 nextRolloverMillis = ThreadLocalRandom.current().nextLong(0, 1 + maxRandomDelayMillis) 132 + manager.getPatternProcessor().getNextTime(nowMillis, interval, modulate); 133 return true; 134 } 135 return false; 136 } 137 138 /** 139 * Creates a TimeBasedTriggeringPolicy. 140 * @param interval The interval between rollovers. 141 * @param modulate If true the time will be rounded to occur on a boundary aligned with the increment. 142 * @return a TimeBasedTriggeringPolicy. 143 * @deprecated Use {@link #newBuilder()}. 144 */ 145 @Deprecated 146 public static TimeBasedTriggeringPolicy createPolicy( 147 @PluginAttribute("interval") final String interval, 148 @PluginAttribute("modulate") final String modulate) { 149 return newBuilder() 150 .withInterval(Integers.parseInt(interval, 1)) 151 .withModulate(Boolean.parseBoolean(modulate)) 152 .build(); 153 } 154 155 @PluginBuilderFactory 156 public static TimeBasedTriggeringPolicy.Builder newBuilder() { 157 return new Builder(); 158 } 159 160 @Override 161 public String toString() { 162 return "TimeBasedTriggeringPolicy(nextRolloverMillis=" + nextRolloverMillis + ", interval=" + interval 163 + ", modulate=" + modulate + ")"; 164 } 165 166}