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