1 package org.apache.helix.monitoring.mbeans;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.StringWriter;
23 import java.lang.management.ManagementFactory;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Date;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Map;
30 import java.util.Set;
31 import java.util.concurrent.ConcurrentHashMap;
32
33 import javax.management.MBeanServer;
34 import javax.management.ObjectName;
35
36 import org.apache.helix.PropertyType;
37 import org.apache.helix.ZNRecord;
38 import org.apache.helix.alerts.AlertParser;
39 import org.apache.helix.alerts.AlertValueAndStatus;
40 import org.apache.helix.alerts.Tuple;
41 import org.apache.log4j.Logger;
42 import org.codehaus.jackson.map.ObjectMapper;
43 import org.codehaus.jackson.map.SerializationConfig;
44
45
46 public class ClusterAlertMBeanCollection
47 {
48 public static String DOMAIN_ALERT = "HelixAlerts";
49 public static String ALERT_SUMMARY = "AlertSummary";
50
51 private static final Logger _logger = Logger.getLogger(ClusterAlertMBeanCollection.class);
52 ConcurrentHashMap<String, ClusterAlertItem> _alertBeans
53 = new ConcurrentHashMap<String, ClusterAlertItem>();
54
55 Map<String, String> _recentAlertDelta;
56 ClusterAlertSummary _clusterAlertSummary;
57 ZNRecord _alertHistory = new ZNRecord(PropertyType.ALERT_HISTORY.toString());
58 Set<String> _previousFiredAlerts = new HashSet<String>();
59
60 public static final long ALERT_NOCHANGE_THRESHOLD = 5 * 60 * 1000;
61
62 final MBeanServer _beanServer;
63
64 public interface ClusterAlertSummaryMBean extends ClusterAlertItemMBean
65 {
66 public String getAlertFiredHistory();
67 }
68
69 class ClusterAlertSummary extends ClusterAlertItem implements ClusterAlertSummaryMBean
70 {
71 public ClusterAlertSummary(String name, AlertValueAndStatus valueAndStatus)
72 {
73 super(name, valueAndStatus);
74 }
75
76
77
78 @Override
79 public String getAlertFiredHistory()
80 {
81 try
82 {
83 ObjectMapper mapper = new ObjectMapper();
84 SerializationConfig serializationConfig = mapper.getSerializationConfig();
85 serializationConfig.set(SerializationConfig.Feature.INDENT_OUTPUT, true);
86 StringWriter sw = new StringWriter();
87 mapper.writeValue(sw, _alertHistory);
88 return sw.toString();
89 }
90 catch(Exception e)
91 {
92 _logger.warn("", e);
93 return "";
94 }
95 }
96 }
97
98
99 public ClusterAlertMBeanCollection()
100 {
101 _beanServer = ManagementFactory.getPlatformMBeanServer();
102 }
103
104 public Collection<ClusterAlertItemMBean> getCurrentAlertMBeans()
105 {
106 ArrayList<ClusterAlertItemMBean> beans = new ArrayList<ClusterAlertItemMBean>();
107 for(ClusterAlertItem item : _alertBeans.values())
108 {
109 beans.add(item);
110 }
111 return beans;
112 }
113
114 void onNewAlertMbeanAdded(ClusterAlertItemMBean bean)
115 {
116 try
117 {
118 _logger.info("alert bean " + bean.getSensorName()+" exposed to jmx");
119 System.out.println("alert bean " + bean.getSensorName()+" exposed to jmx");
120 ObjectName objectName = new ObjectName(DOMAIN_ALERT+":alert="+bean.getSensorName());
121 register(bean, objectName);
122 }
123 catch (Exception e)
124 {
125 _logger.error("", e);
126 e.printStackTrace();
127 }
128 }
129
130 public void setAlerts(String originAlert, Map<String, AlertValueAndStatus> alertResultMap, String clusterName)
131 {
132 if(alertResultMap == null)
133 {
134 _logger.warn("null alertResultMap");
135 return;
136 }
137 for(String alertName : alertResultMap.keySet())
138 {
139 String beanName = "";
140 if(alertName.length() > 1)
141 {
142 String comparator = AlertParser.getComponent(AlertParser.COMPARATOR_NAME, originAlert);
143 String constant = AlertParser.getComponent(AlertParser.CONSTANT_NAME, originAlert);
144 beanName = "("+ alertName+")" + comparator + "("+constant+")";
145 }
146 else
147 {
148 beanName = originAlert + "--(" + alertName + ")";
149 }
150
151 beanName = beanName.replace('*', '%').replace('=', '#').replace(',', ';');
152 if(!_alertBeans.containsKey(beanName))
153 {
154 ClusterAlertItem item = new ClusterAlertItem(beanName, alertResultMap.get(alertName));
155 onNewAlertMbeanAdded(item);
156 _alertBeans.put(beanName, item);
157 }
158 else
159 {
160 _alertBeans.get(beanName).setValueMap(alertResultMap.get(alertName));
161 }
162 }
163 refreshSummayAlert(clusterName);
164 }
165
166 public void setAlertHistory(ZNRecord alertHistory)
167 {
168 _alertHistory = alertHistory;
169 }
170
171
172
173
174 void refreshSummayAlert(String clusterName)
175 {
176 boolean fired = false;
177 String alertsFired = "";
178 String summaryKey = ALERT_SUMMARY + "_" + clusterName;
179 for(String key : _alertBeans.keySet())
180 {
181 if(!key.equals(summaryKey))
182 {
183 ClusterAlertItem item = _alertBeans.get(key);
184 fired = (item.getAlertFired() == 1) | fired;
185 if(item.getAlertFired() == 1)
186 {
187 alertsFired += item._alertItemName;
188 alertsFired += ";";
189 }
190 }
191 }
192 Tuple<String> t = new Tuple<String>();
193 t.add("0");
194 AlertValueAndStatus summaryStatus = new AlertValueAndStatus(t, fired);
195 if(!_alertBeans.containsKey(summaryKey))
196 {
197 ClusterAlertSummary item = new ClusterAlertSummary(summaryKey, summaryStatus);
198 onNewAlertMbeanAdded(item);
199 item.setAdditionalInfo(alertsFired);
200 _alertBeans.put(summaryKey, item);
201 _clusterAlertSummary = item;
202 }
203 else
204 {
205 _alertBeans.get(summaryKey).setValueMap(summaryStatus);
206 _alertBeans.get(summaryKey).setAdditionalInfo(alertsFired);
207 }
208 }
209
210 void register(Object bean, ObjectName name)
211 {
212 try
213 {
214 _beanServer.unregisterMBean(name);
215 }
216 catch (Exception e)
217 {
218 }
219 try
220 {
221 _beanServer.registerMBean(bean, name);
222 }
223 catch (Exception e)
224 {
225 _logger.error("Could not register MBean", e);
226 }
227 }
228
229 public void reset()
230 {
231 for(String beanName : _alertBeans.keySet())
232 {
233 ClusterAlertItem item = _alertBeans.get(beanName);
234 item.reset();
235 try
236 {
237 ObjectName objectName = new ObjectName(DOMAIN_ALERT+":alert="+item.getSensorName());
238 _beanServer.unregisterMBean(objectName);
239 }
240 catch (Exception e)
241 {
242 _logger.warn("", e);
243 }
244 }
245 _alertBeans.clear();
246 }
247
248 public void refreshAlertDelta(String clusterName)
249 {
250
251 String summaryKey = ALERT_SUMMARY + "_" + clusterName;
252 Set<String> currentFiredAlerts = new HashSet<String>();
253 for(String key : _alertBeans.keySet())
254 {
255 if(!key.equals(summaryKey))
256 {
257 ClusterAlertItem item = _alertBeans.get(key);
258 if(item.getAlertFired() == 1)
259 {
260 currentFiredAlerts.add(item._alertItemName);
261 }
262 }
263 }
264
265 Map<String, String> onOffAlertsMap = new HashMap<String, String>();
266 for(String alertName : currentFiredAlerts)
267 {
268 if(!_previousFiredAlerts.contains(alertName))
269 {
270 onOffAlertsMap.put(alertName, "ON");
271 _logger.info(alertName + " ON");
272 _previousFiredAlerts.add(alertName);
273 }
274 }
275 for(String cachedAlert : _previousFiredAlerts)
276 {
277 if(!currentFiredAlerts.contains(cachedAlert))
278 {
279 onOffAlertsMap.put(cachedAlert, "OFF");
280 _logger.info(cachedAlert + " OFF");
281 }
282 }
283 for(String key : onOffAlertsMap.keySet())
284 {
285 if(onOffAlertsMap.get(key).equals("OFF"))
286 {
287 _previousFiredAlerts.remove(key);
288 }
289 }
290 if(onOffAlertsMap.size() == 0)
291 {
292 _logger.info("No MBean change");
293 }
294 _recentAlertDelta = onOffAlertsMap;
295
296 checkMBeanFreshness(ALERT_NOCHANGE_THRESHOLD);
297 }
298
299 public Map<String, String> getRecentAlertDelta()
300 {
301 return _recentAlertDelta;
302 }
303
304
305
306
307 void checkMBeanFreshness(long thresholdInMs)
308 {
309 long now = new Date().getTime();
310 Set<String> oldBeanNames = new HashSet<String>();
311
312 for(String beanName : _alertBeans.keySet())
313 {
314 ClusterAlertItem item = _alertBeans.get(beanName);
315 if(now - item.getLastUpdateTime() > thresholdInMs)
316 {
317 oldBeanNames.add(beanName);
318 _logger.info("bean " + beanName+" has not been updated for "+ thresholdInMs +" MS");
319 }
320 }
321 for(String beanName : oldBeanNames)
322 {
323 ClusterAlertItem item = _alertBeans.get(beanName);
324 _alertBeans.remove(beanName);
325 try
326 {
327 item.reset();
328 ObjectName objectName = new ObjectName(DOMAIN_ALERT+":alert="+item.getSensorName());
329 _beanServer.unregisterMBean(objectName);
330 }
331 catch (Exception e)
332 {
333 _logger.warn("", e);
334 }
335 }
336 }
337 }