View Javadoc

1   /*
2    * The contents of this file are subject to the terms 
3    * of the Common Development and Distribution License 
4    * (the "License").  You may not use this file except 
5    * in compliance with the License.
6    * 
7    * You can obtain a copy of the license at 
8    * http://www.sun.com/cddl/cddl.html. 
9    * See the License for the specific language governing 
10   * permissions and limitations under the License.
11   * 
12   * When distributing Covered Code, include this CDDL 
13   * HEADER in each file and include the License file at 
14   * license.txt.  If applicable, add the following below 
15   * this CDDL HEADER, with the fields enclosed by brackets 
16   * "[]" replaced with your own identifying information: 
17   * Portions Copyright [yyyy] [name of copyright owner]
18   * 
19   * Portions Copyright 2004 eBay, Inc.
20   */
21  package com.ebay.carad.os.vitalsigns.listeners;
22  
23  import java.net.InetAddress;
24  import java.text.Format;
25  import java.text.MessageFormat;
26  import java.util.Date;
27  
28  import com.ebay.carad.os.vitalsigns.IDashboardAgent;
29  import com.ebay.carad.os.vitalsigns.IDashboardReport;
30  import com.ebay.carad.os.vitalsigns.IReportingListenerContainer;
31  import com.ebay.carad.os.vitalsigns.ReportingException;
32  import com.ebay.carad.os.vitalsigns.util.ExceptionUtil;
33  import com.ebay.carad.os.vitalsigns.util.MailUtil;
34  
35  /***
36   * <p>Report listener that can send email alerts for ReportingExceptions and for data
37   * that is recorded that is out of the expected range.</p>
38   * 
39   * @author Jeremy Thomerson
40   * @version $Id$
41   */
42  public class EmailAlertListener extends AbstractReportingListener {
43  
44      //private static final Logger LOGGER = Logger.getLogger(EmailAlertListener.class);
45      private float mDataLevel = 0;
46      private String mErrorType = "ERROR";
47      
48      private Format mExceptionMessageFormat = new MessageFormat(
49              ""
50              ); 
51      
52      private Format mLevelMessageFormat = new MessageFormat(
53              "{2}\n\nReport ID {4} ({3}) recorded data of {1} which is above the error threshold ({5})\n\n{6}\n\nFrom machine: {7}"
54              ); 
55      
56  
57      private String mMailServer;
58      private String[] mToAddresses;
59      private String mFromAddress;
60      private String mMessageSubject;
61      
62      private boolean rememberValues = false;
63      
64      private float lastObservedValue = 0;
65      
66      /***
67       * If true, the listener will only send an email if the currently observed value is outside the threshold, AND
68       * is "worse" than the last observed value. This is usually desired in situations where observed values are long-lived.
69       * For example, if your report observes number of order exceptions in last 24 hours, but you want an email to be sent
70       * when any errors are detected, you probably do not want to receive an email every time the report is run for 24 hours
71       * after the first error is detected. Instead, you want to get an alert if any more errors are received than the last time
72       * you looked. If enabled, the listener will compare the currently observed value to the last observed value, and send
73       * an email only if the current value is outside of the threshold and worse than the last one. This option is OFF by default.
74       * 
75       * @param rememberValues if true, emails will only be sent when values got "worse" than last observation
76       */
77      public void setRememberValues(boolean rememberValues) {
78  		this.rememberValues = rememberValues;
79  	}
80  
81  	/***
82       * Sets the address of the SMTP relay to use.
83       * 
84       * @param server IP address or hostname of SMTP relay
85       */
86      public void setMailServer(String server) {
87          mMailServer = server;
88      }
89      
90      /***
91       * Sets the address that mail alerts will appear to come from.
92       * 
93       * @param address the address to send from
94       */
95      public void setFromAddress(String address) {
96          mFromAddress = address;
97      }
98      
99      /***
100      * Sets the addresses that mail alerts will be sent to.
101      * 
102      * @param inToAddresses the "to" e-mail addresses
103      */
104     public void setToAddresses(String[] inToAddresses) {
105         mToAddresses = inToAddresses;
106     }
107     
108     /***
109      * Sets the subject line for alerts sent by this handler.
110      * 
111      * @param inSubject subject line for alerts
112      */
113     public void setSubject(String inSubject) {
114         mMessageSubject = inSubject;
115     }
116     
117     public void alert(String msg) {
118         try {
119             MailUtil.sendMessage(new String[] { mFromAddress }, mToAddresses, mMessageSubject, msg, mMailServer);
120         } catch (Exception ex) {
121             ex.printStackTrace();
122         }
123     }
124 
125     /***
126      * Receives parameters:
127      * <pre> 
128      * {
129      *  0 : report.getPreviousData(), 
130      *  1 : report.getThisRunData(), 
131      *  2 : report.getTitle(),
132      *  3 : report.getID(),
133      *  4 : exception.getMessage(),
134      *  5 : full exception details, including stack trace, as string
135      *  6 : new Date().toString()
136      * }
137      * </pre>
138      */
139     public void reportingException(ReportingException exception, IReportingListenerContainer agent, IDashboardReport report) {
140         Object[] params = new Object[] {
141                 report.getPreviousData(),
142                 report.getThisRunData(),
143                 report.getTitle(),
144                 new Integer(report.getID()),
145                 exception.getMessage(),
146                 getExceptionString(exception),
147                 getLocalMachineName()
148         };
149         String msg = mExceptionMessageFormat.format(params);
150         alert(msg);
151     }
152 
153     /***
154      * Receives parameters:
155      * <pre> 
156      * {
157      *  0 : report.getPreviousData(), 
158      *  1 : report.getThisRunData(), 
159      *  2 : this.errorType (i.e. WARNING / ERROR),
160      *  3 : report.getTitle(),
161      *  4 : report.getID(),
162      *  5 : this.dataLevel
163      *  6 : new Date().toString()
164      * }
165      * </pre>
166      */
167     public void reportRan(IDashboardAgent agent, IDashboardReport report) {
168         if (!isAlertNeeded(report)) { 
169             return;
170         }
171         Object[] params = new Object[] { 
172                 report.getPreviousData(),
173                 report.getThisRunData(),
174                 mErrorType,
175                 report.getTitle(),
176                 new Integer(report.getID()),
177                 new Float(mDataLevel),
178                 new Date().toString(),
179                 getLocalMachineName()
180         };
181         String msg = mLevelMessageFormat.format(params);
182         alert(msg);
183     }
184     
185     private String getLocalMachineName() {
186     	String ret = "unknown";
187     	try {
188     	    ret = InetAddress.getLocalHost().getHostName();
189     	} catch(Exception ex) {
190     	}
191     	return ret;
192     }
193 
194     private boolean isAlertNeeded(IDashboardReport report) {
195         Float data = report.getThisRunData();
196         if (data == null) {
197             return false;
198         }
199         
200         float dataVal = data.floatValue();
201         boolean outOfThreshold = report.getMoreIsBetter() ? dataVal < mDataLevel : dataVal > mDataLevel;
202         boolean ret = outOfThreshold;
203 
204         if (outOfThreshold) { // check if memory is turned on
205         	if (rememberValues) { // only return true if this value got worse since our last observation.
206         		ret = report.getMoreIsBetter() ? dataVal < lastObservedValue : dataVal > lastObservedValue;
207         	}
208         }
209         
210         lastObservedValue = dataVal; // remember for next time
211 
212         return ret;
213     }
214 
215     private String getExceptionString(ReportingException exception) {
216         return ExceptionUtil.fullDetailsMessage(exception);
217     }
218 
219     public void setErrorType(String errorType) {
220         mErrorType = errorType;
221     }
222     public void setThreshold(float dataLevel) {
223         mDataLevel = dataLevel;
224     }
225 }
226