View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.core.filter;
18  
19  import java.text.ParseException;
20  import java.text.SimpleDateFormat;
21  import java.util.Calendar;
22  import java.util.TimeZone;
23  
24  import org.apache.logging.log4j.core.Filter;
25  import org.apache.logging.log4j.core.LogEvent;
26  import org.apache.logging.log4j.core.config.Node;
27  import org.apache.logging.log4j.core.config.plugins.Plugin;
28  import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
29  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
30  
31  /**
32   * Filters events that fall within a specified time period in each day.
33   */
34  @Plugin(name = "TimeFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
35  public final class TimeFilter extends AbstractFilter {
36  
37      private static final long serialVersionUID = 1L;
38  
39      /**
40       * Length of hour in milliseconds.
41       */
42      private static final long HOUR_MS = 3600000;
43  
44      /**
45       * Length of minute in milliseconds.
46       */
47      private static final long MINUTE_MS = 60000;
48  
49      /**
50       * Length of second in milliseconds.
51       */
52      private static final long SECOND_MS = 1000;
53  
54      /**
55       * Starting offset from midnight in milliseconds.
56       */
57      private final long start;
58      /**
59       * Ending offset from midnight in milliseconds.
60       */
61      private final long end;
62      /**
63       * Timezone.
64       */
65      private final TimeZone timezone;
66  
67  
68      private TimeFilter(final long start, final long end, final TimeZone tz, final Result onMatch,
69                         final Result onMismatch) {
70          super(onMatch, onMismatch);
71          this.start = start;
72          this.end = end;
73          timezone = tz;
74      }
75  
76      @Override
77      public Result filter(final LogEvent event) {
78          final Calendar calendar = Calendar.getInstance(timezone);
79          calendar.setTimeInMillis(event.getTimeMillis());
80          //
81          //   get apparent number of milliseconds since midnight
82          //      (ignores extra or missing hour on daylight time changes).
83          //
84          final long apparentOffset = calendar.get(Calendar.HOUR_OF_DAY) * HOUR_MS +
85              calendar.get(Calendar.MINUTE) * MINUTE_MS +
86              calendar.get(Calendar.SECOND) * SECOND_MS +
87              calendar.get(Calendar.MILLISECOND);
88          return apparentOffset >= start && apparentOffset < end ? onMatch : onMismatch;
89      }
90  
91      @Override
92      public String toString() {
93          final StringBuilder sb = new StringBuilder();
94          sb.append("start=").append(start);
95          sb.append(", end=").append(end);
96          sb.append(", timezone=").append(timezone.toString());
97          return sb.toString();
98      }
99  
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 }