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 long current = aManager.getFileTime(); 112 if (current == 0) { 113 current = System.currentTimeMillis(); 114 } 115 116 // LOG4J2-531: call getNextTime twice to force initialization of both prevFileTime and nextFileTime 117 aManager.getPatternProcessor().getNextTime(current, interval, modulate); 118 aManager.getPatternProcessor().setTimeBased(true); 119 120 nextRolloverMillis = ThreadLocalRandom.current().nextLong(0, 1 + maxRandomDelayMillis) 121 + aManager.getPatternProcessor().getNextTime(current, interval, modulate); 122 } 123 124 /** 125 * Determines whether a rollover should occur. 126 * @param event A reference to the currently event. 127 * @return true if a rollover should occur. 128 */ 129 @Override 130 public boolean isTriggeringEvent(final LogEvent event) { 131 final long nowMillis = event.getTimeMillis(); 132 if (nowMillis >= nextRolloverMillis) { 133 nextRolloverMillis = ThreadLocalRandom.current().nextLong(0, 1 + maxRandomDelayMillis) 134 + manager.getPatternProcessor().getNextTime(nowMillis, interval, modulate); 135 manager.getPatternProcessor().setCurrentFileTime(System.currentTimeMillis()); 136 return true; 137 } 138 return false; 139 } 140 141 /** 142 * Creates a TimeBasedTriggeringPolicy. 143 * @param interval The interval between rollovers. 144 * @param modulate If true the time will be rounded to occur on a boundary aligned with the increment. 145 * @return a TimeBasedTriggeringPolicy. 146 * @deprecated Use {@link #newBuilder()}. 147 */ 148 @Deprecated 149 public static TimeBasedTriggeringPolicy createPolicy( 150 @PluginAttribute("interval") final String interval, 151 @PluginAttribute("modulate") final String modulate) { 152 return newBuilder() 153 .withInterval(Integers.parseInt(interval, 1)) 154 .withModulate(Boolean.parseBoolean(modulate)) 155 .build(); 156 } 157 158 @PluginBuilderFactory 159 public static TimeBasedTriggeringPolicy.Builder newBuilder() { 160 return new Builder(); 161 } 162 163 @Override 164 public String toString() { 165 return "TimeBasedTriggeringPolicy(nextRolloverMillis=" + nextRolloverMillis + ", interval=" + interval 166 + ", modulate=" + modulate + ")"; 167 } 168 169}