1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
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) {
205 if (rememberValues) {
206 ret = report.getMoreIsBetter() ? dataVal < lastObservedValue : dataVal > lastObservedValue;
207 }
208 }
209
210 lastObservedValue = dataVal;
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