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 private static final long serialVersionUID = 1L; 038 039 /** 040 * Length of hour in milliseconds. 041 */ 042 private static final long HOUR_MS = 3600000; 043 044 /** 045 * Length of minute in milliseconds. 046 */ 047 private static final long MINUTE_MS = 60000; 048 049 /** 050 * Length of second in milliseconds. 051 */ 052 private static final long SECOND_MS = 1000; 053 054 /** 055 * Starting offset from midnight in milliseconds. 056 */ 057 private final long start; 058 /** 059 * Ending offset from midnight in milliseconds. 060 */ 061 private final long end; 062 /** 063 * Timezone. 064 */ 065 private final TimeZone timezone; 066 067 068 private TimeFilter(final long start, final long end, final TimeZone tz, final Result onMatch, 069 final Result onMismatch) { 070 super(onMatch, onMismatch); 071 this.start = start; 072 this.end = end; 073 timezone = tz; 074 } 075 076 @Override 077 public Result filter(final LogEvent event) { 078 final Calendar calendar = Calendar.getInstance(timezone); 079 calendar.setTimeInMillis(event.getTimeMillis()); 080 // 081 // get apparent number of milliseconds since midnight 082 // (ignores extra or missing hour on daylight time changes). 083 // 084 final long apparentOffset = calendar.get(Calendar.HOUR_OF_DAY) * HOUR_MS + 085 calendar.get(Calendar.MINUTE) * MINUTE_MS + 086 calendar.get(Calendar.SECOND) * SECOND_MS + 087 calendar.get(Calendar.MILLISECOND); 088 return apparentOffset >= start && apparentOffset < end ? onMatch : onMismatch; 089 } 090 091 @Override 092 public String toString() { 093 final StringBuilder sb = new StringBuilder(); 094 sb.append("start=").append(start); 095 sb.append(", end=").append(end); 096 sb.append(", timezone=").append(timezone.toString()); 097 return sb.toString(); 098 } 099 100 /** 101 * Create a TimeFilter. 102 * @param start The start time. 103 * @param end The end time. 104 * @param tz timezone. 105 * @param match Action to perform if the time matches. 106 * @param mismatch Action to perform if the action does not match. 107 * @return A TimeFilter. 108 */ 109 @PluginFactory 110 public static TimeFilter createFilter( 111 @PluginAttribute("start") final String start, 112 @PluginAttribute("end") final String end, 113 @PluginAttribute("timezone") final String tz, 114 @PluginAttribute("onMatch") final Result match, 115 @PluginAttribute("onMismatch") final Result mismatch) { 116 final SimpleDateFormat stf = new SimpleDateFormat("HH:mm:ss"); 117 long s = 0; 118 if (start != null) { 119 stf.setTimeZone(TimeZone.getTimeZone("UTC")); 120 try { 121 s = stf.parse(start).getTime(); 122 } catch (final ParseException ex) { 123 LOGGER.warn("Error parsing start value " + start, ex); 124 } 125 } 126 long e = Long.MAX_VALUE; 127 if (end != null) { 128 stf.setTimeZone(TimeZone.getTimeZone("UTC")); 129 try { 130 e = stf.parse(end).getTime(); 131 } catch (final ParseException ex) { 132 LOGGER.warn("Error parsing start value " + end, ex); 133 } 134 } 135 final TimeZone timezone = tz == null ? TimeZone.getDefault() : TimeZone.getTimeZone(tz); 136 final Result onMatch = match == null ? Result.NEUTRAL : match; 137 final Result onMismatch = mismatch == null ? Result.DENY : mismatch; 138 return new TimeFilter(s, e, timezone, onMatch, onMismatch); 139 } 140 141}