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.filter; 018 019import java.text.ParseException; 020import java.text.SimpleDateFormat; 021import java.util.Calendar; 022import java.util.TimeZone; 023 024import org.apache.logging.log4j.core.Filter; 025import org.apache.logging.log4j.core.LogEvent; 026import org.apache.logging.log4j.core.config.Node; 027import org.apache.logging.log4j.core.config.plugins.Plugin; 028import org.apache.logging.log4j.core.config.plugins.PluginAttribute; 029import org.apache.logging.log4j.core.config.plugins.PluginFactory; 030 031/** 032 * Filters events that fall within a specified time period in each day. 033 */ 034@Plugin(name = "TimeFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true) 035public final class TimeFilter extends AbstractFilter { 036 037 /** 038 * Length of hour in milliseconds. 039 */ 040 private static final long HOUR_MS = 3600000; 041 042 /** 043 * Length of minute in milliseconds. 044 */ 045 private static final long MINUTE_MS = 60000; 046 047 /** 048 * Length of second in milliseconds. 049 */ 050 private static final long SECOND_MS = 1000; 051 052 /** 053 * Starting offset from midnight in milliseconds. 054 */ 055 private final long start; 056 /** 057 * Ending offset from midnight in milliseconds. 058 */ 059 private final long end; 060 /** 061 * Timezone. 062 */ 063 private final TimeZone timezone; 064 065 066 private TimeFilter(final long start, final long end, final TimeZone tz, final Result onMatch, 067 final Result onMismatch) { 068 super(onMatch, onMismatch); 069 this.start = start; 070 this.end = end; 071 timezone = tz; 072 } 073 074 @Override 075 public Result filter(final LogEvent event) { 076 final Calendar calendar = Calendar.getInstance(timezone); 077 calendar.setTimeInMillis(event.getTimeMillis()); 078 // 079 // get apparent number of milliseconds since midnight 080 // (ignores extra or missing hour on daylight time changes). 081 // 082 final long apparentOffset = calendar.get(Calendar.HOUR_OF_DAY) * HOUR_MS + 083 calendar.get(Calendar.MINUTE) * MINUTE_MS + 084 calendar.get(Calendar.SECOND) * SECOND_MS + 085 calendar.get(Calendar.MILLISECOND); 086 return apparentOffset >= start && apparentOffset < end ? onMatch : onMismatch; 087 } 088 089 @Override 090 public String toString() { 091 final StringBuilder sb = new StringBuilder(); 092 sb.append("start=").append(start); 093 sb.append(", end=").append(end); 094 sb.append(", timezone=").append(timezone.toString()); 095 return sb.toString(); 096 } 097 098 /** 099 * Create a TimeFilter. 100 * @param start The start time. 101 * @param end The end time. 102 * @param tz timezone. 103 * @param match Action to perform if the time matches. 104 * @param mismatch Action to perform if the action does not match. 105 * @return A TimeFilter. 106 */ 107 @PluginFactory 108 public static TimeFilter createFilter( 109 @PluginAttribute("start") final String start, 110 @PluginAttribute("end") final String end, 111 @PluginAttribute("timezone") final String tz, 112 @PluginAttribute("onMatch") final Result match, 113 @PluginAttribute("onMismatch") final Result mismatch) { 114 final long s = parseTimestamp(start, 0); 115 final long e = parseTimestamp(end, Long.MAX_VALUE); 116 final TimeZone timezone = tz == null ? TimeZone.getDefault() : TimeZone.getTimeZone(tz); 117 final Result onMatch = match == null ? Result.NEUTRAL : match; 118 final Result onMismatch = mismatch == null ? Result.DENY : mismatch; 119 return new TimeFilter(s, e, timezone, onMatch, onMismatch); 120 } 121 122 private static long parseTimestamp(final String timestamp, final long defaultValue) { 123 if (timestamp == null) { 124 return defaultValue; 125 } 126 final SimpleDateFormat stf = new SimpleDateFormat("HH:mm:ss"); 127 stf.setTimeZone(TimeZone.getTimeZone("UTC")); 128 try { 129 return stf.parse(timestamp).getTime(); 130 } catch (final ParseException e) { 131 LOGGER.warn("Error parsing TimeFilter timestamp value {}", timestamp, e); 132 return defaultValue; 133 } 134 } 135 136}