Coverage Report - net.admin4j.ui.filters.PerformanceMonitoringFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
PerformanceMonitoringFilter
67%
45/67
71%
10/14
7.333
 
 1  
 /*
 2  
  * This software is licensed under the Apache License, Version 2.0
 3  
  * (the "License") agreement; you may not use this file except in compliance with
 4  
  * the License.  You may obtain a copy of the License at
 5  
  *
 6  
  *      http://www.apache.org/licenses/LICENSE-2.0
 7  
  *
 8  
  * Unless required by applicable law or agreed to in writing, software
 9  
  * distributed under the License is distributed on an "AS IS" BASIS,
 10  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 11  
  * See the License for the specific language governing permissions and
 12  
  * limitations under the License.
 13  
  */
 14  
 package net.admin4j.ui.filters;
 15  
 
 16  
 import java.io.IOException;
 17  
 import java.io.StringWriter;
 18  
 import java.util.HashMap;
 19  
 import java.util.Map;
 20  
 
 21  
 import javax.servlet.Filter;
 22  
 import javax.servlet.FilterChain;
 23  
 import javax.servlet.FilterConfig;
 24  
 import javax.servlet.ServletException;
 25  
 import javax.servlet.ServletRequest;
 26  
 import javax.servlet.ServletResponse;
 27  
 import javax.servlet.http.HttpServletRequest;
 28  
 
 29  
 import net.admin4j.config.Admin4JConfiguration;
 30  
 import net.admin4j.deps.commons.lang3.StringUtils;
 31  
 import net.admin4j.timer.TaskTimer;
 32  
 import net.admin4j.timer.TaskTimerFactory;
 33  
 import net.admin4j.ui.filters.consolidator.DefaultHttpRequestConsolidator;
 34  
 import net.admin4j.ui.filters.consolidator.HttpRequestConsolidator;
 35  
 import net.admin4j.util.Admin4jRuntimeException;
 36  
 import net.admin4j.util.FreemarkerUtils;
 37  
 import net.admin4j.util.GuiUtils;
 38  
 import net.admin4j.util.HostUtils;
 39  
 import net.admin4j.util.ServletUtils;
 40  
 import freemarker.template.Configuration;
 41  
 import freemarker.template.Template;
 42  
 
 43  
 /**
 44  
  *
 45  
  * This filter allows you to enable performance monitoring. Notification will be
 46  
  * sent when a defined threshold limit is reached.
 47  
  *
 48  
  * <p>
 49  
  * Initialization parameters for this filter are as follows:
 50  
  * </p>
 51  
  * <li>notification.threshold.in.millis - Optional. If set, a notification will
 52  
  * be issued should a page take longer than the specified number of
 53  
  * milliseconds. For this option to work, values must be provided for notifier</li>
 54  
  * <li>notifier -- Optional. Handles admin notification. See documentation for
 55  
  * the Notifier you're using for any additional configuration requirements. For
 56  
  * example, 'net.admin4j.util.notify.EmailNotifier'.</li>
 57  
  *
 58  
  * @author D. Ashmore
 59  
  * @since 1.0
 60  
  */
 61  12
 public class PerformanceMonitoringFilter extends BaseNotificationFilter
 62  
 implements Filter {
 63  
 
 64  12
         private long notificationThresholdInMillis = Long.MAX_VALUE;
 65  12
         private HttpRequestConsolidator consolidator = new DefaultHttpRequestConsolidator();
 66  
 
 67  
         public void destroy() {
 68  0
         }
 69  
 
 70  
         public void doFilter(ServletRequest request, ServletResponse response,
 71  
                         FilterChain filterChain) throws IOException, ServletException {
 72  
 
 73  12
                 TaskTimer perfMonitor = null;
 74  12
                 HttpServletRequest httpRequest = null;
 75  12
                 String serviceName = null;
 76  12
                 long beginTime = System.currentTimeMillis();
 77  
 
 78  
                 try {
 79  
 
 80  
                         /*
 81  
                          * Under no circumstances should an Admin4J error 'mask' the
 82  
                          * underlying error for an application. Hence, all Admin4J work is
 83  
                          * surrounded by a try/catch making sure to throw the underlying
 84  
                          * exception up the chain.
 85  
                          */
 86  
                         try {
 87  12
                                 httpRequest = (HttpServletRequest) request;
 88  12
                                 serviceName = httpRequest.getRequestURI();
 89  12
                                 perfMonitor = TaskTimerFactory.start(serviceName);
 90  0
                         } catch (Throwable fubar) {
 91  0
                                 logger.error("Error starting performance monitor.", fubar);
 92  12
                         }
 93  
 
 94  12
                         filterChain.doFilter(request, response);
 95  
                         try {
 96  12
                                 long durationInMillis = System.currentTimeMillis() - beginTime;
 97  12
                                 double durationInSeconds = durationInMillis / 1000;
 98  
 
 99  12
                                 if (durationInMillis > notificationThresholdInMillis) {
 100  6
                                         Configuration cfg = new Configuration();
 101  6
                                         cfg.setClassForTemplateLoading(
 102  
                                                         ErrorNotificationFilter.class, "");
 103  
 
 104  6
                                         Map<String, Object> variableMap = new HashMap<String, Object>();
 105  6
                                         variableMap.put("request", httpRequest);
 106  6
                                         variableMap.put("GuiUtils", new GuiUtils());
 107  6
                                         variableMap.put("host", HostUtils.getHostName());
 108  6
                                         variableMap.put("timeInSeconds", durationInSeconds);
 109  6
                                         variableMap.put(
 110  
                                                         "sessionAttributeList",
 111  
                                                         ServletUtils.listSessionAttributes(httpRequest.getSession()));
 112  6
                                         variableMap.put("requestAttributeList",
 113  
                                                         ServletUtils.listRequestAttributes(httpRequest));
 114  
 
 115  6
                                         Template temp = null;
 116  6
                                         if (this.notifier.supportsHtml()) {
 117  3
                                                 temp = FreemarkerUtils.createConfiguredTemplate(
 118  
                                                                 this.getClass(),
 119  
                                                                 "slowPerformanceNotificationMessageHtml.ftl");
 120  
                                         }
 121  
                                         else {
 122  3
                                                 temp = FreemarkerUtils.createConfiguredTemplate(
 123  
                                                                 this.getClass(),
 124  
                                                                 "slowPerformanceNotificationMessageText.ftl");
 125  
                                         }
 126  
 
 127  6
                                         StringWriter message = new StringWriter();
 128  
                                         try {
 129  6
                                                 temp.process(variableMap, message);
 130  0
                                         } catch (Exception e) {
 131  0
                                                 throw new Admin4jRuntimeException(e);
 132  6
                                         }
 133  
 
 134  6
                                         String subject = ServletUtils.getApplicationName(httpRequest)
 135  
                                                         + "@"
 136  
                                                         + HostUtils.getHostName()
 137  
                                                         + ": "
 138  
                                                         + httpRequest.getRequestURI()
 139  
                                                         + ": "
 140  
                                                         + "Response time over "
 141  
                                                         + notificationThresholdInMillis + " ms";
 142  6
                                         this.notifier.notify(subject, message.toString());
 143  
                                 }
 144  0
                         } catch (Throwable fubar) {
 145  0
                                 logger.error("Error providing performance notification.", fubar);
 146  12
                         }
 147  
 
 148  0
                 } catch (ServletException se) {
 149  0
                         throw se;
 150  0
                 } catch (Throwable ex) {
 151  0
                         throw new ServletException(ex);
 152  
                 } finally {
 153  12
                         if (perfMonitor != null) {
 154  12
                                 perfMonitor.stop();
 155  
                         }
 156  
                 }
 157  12
         }
 158  
 
 159  
         /*
 160  
          * (non-Javadoc)
 161  
          *
 162  
          * @see
 163  
          * net.admin4j.ui.filters.BaseNotificationFilter#init(javax.servlet.FilterConfig
 164  
          * )
 165  
          */
 166  
         @Override
 167  
         public void init(FilterConfig config) throws ServletException {
 168  9
                 super.init(config);
 169  
 
 170  9
                 String notifyThresholdInMillisStr = config.getInitParameter("notification.threshold.in.millis");
 171  0
                 if (!StringUtils.isEmpty(notifyThresholdInMillisStr)) {
 172  
                         try {
 173  3
                                 this.notificationThresholdInMillis = Long.parseLong(notifyThresholdInMillisStr);
 174  0
                         } catch (NumberFormatException e) {
 175  0
                                 this.notificationThresholdInMillis = Long.MAX_VALUE;
 176  0
                                 throw new Admin4jRuntimeException(
 177  
                                                 "notification.threshold.in.millis secification not numeric",
 178  
                                                 e).addContextValue("notification.threshold.in.millis",
 179  
                                                                 notifyThresholdInMillisStr);
 180  
 
 181  3
                         }
 182  
                 }
 183  6
                 else if (Admin4JConfiguration.getWebTransactionPerformanceNotificationThresholdInMillis() != null) {
 184  0
                         this.notificationThresholdInMillis = Admin4JConfiguration.getWebTransactionPerformanceNotificationThresholdInMillis();
 185  
                 }
 186  
 
 187  9
                 String requestConsolidatorClassStr = config.getInitParameter("uri.consolidator");
 188  0
                 if (!StringUtils.isEmpty(requestConsolidatorClassStr)) {
 189  
                         try {
 190  0
                                 consolidator = (HttpRequestConsolidator) Class.forName(
 191  
                                                 requestConsolidatorClassStr)
 192  
                                                 .newInstance();
 193  0
                         } catch (Exception e) {
 194  0
                                 throw new Admin4jRuntimeException(
 195  
                                                 "uri.consolidator cannot be instantiated", e).addContextValue(
 196  
                                                                 "uri.consolidator", requestConsolidatorClassStr);
 197  0
                         }
 198  
                 }
 199  9
                 else if (Admin4JConfiguration.getPerformanceRestUriConsolidator() != null) {
 200  0
                         consolidator = Admin4JConfiguration.getPerformanceRestUriConsolidator();
 201  
                 }
 202  9
         }
 203  
 
 204  
 }