PageRenderTime 56ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/dashboard/src/main/java/com/ning/arecibo/dashboard/alert/AlertStatusManager.java

https://github.com/ning/Arecibo
Java | 409 lines | 301 code | 88 blank | 20 comment | 80 complexity | 9c9d4361a315137d2c57935f6716231f MD5 | raw file
  1. /*
  2. * Copyright 2010-2012 Ning, Inc.
  3. *
  4. * Ning licenses this file to you under the Apache License, version 2.0
  5. * (the "License"); you may not use this file except in compliance with the
  6. * License. You may obtain a copy of the License at:
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations
  14. * under the License.
  15. */
  16. package com.ning.arecibo.dashboard.alert;
  17. import java.util.ArrayList;
  18. import java.util.Collection;
  19. import java.util.List;
  20. import java.util.Set;
  21. import java.util.concurrent.ConcurrentHashMap;
  22. import java.util.concurrent.ScheduledThreadPoolExecutor;
  23. import java.util.concurrent.TimeUnit;
  24. import java.util.concurrent.atomic.AtomicLong;
  25. import com.google.inject.Inject;
  26. import com.ning.arecibo.dashboard.guice.DashboardConfig;
  27. import com.ning.arecibo.util.Logger;
  28. public class AlertStatusManager implements Runnable
  29. {
  30. private final static Logger log = Logger.getLogger(AlertStatusManager.class);
  31. public final static String UNDEFINED_HOST_NAME = "undefined";
  32. public final static String UNDEFINED_TYPE_NAME = "undefined";
  33. public final static String UNDEFINED_PATH_NAME = "undefined";
  34. public final static String HOST_ATTR = "hostName";
  35. public final static String TYPE_ATTR = "deployedType";
  36. public final static String PATH_ATTR = "deployedConfigSubPath";
  37. private final static String KEY_DELIM = "$";
  38. //TODO: Inject this
  39. // poll every 10 seconds (will want to inject this later, or change to happen on demand, with minimum refresh interval)
  40. private final static long CONFIG_UPDATE_INTERVAL = 1000L * 10L;
  41. private AtomicLong generationCount = new AtomicLong(Long.MIN_VALUE);
  42. private ScheduledThreadPoolExecutor executor;
  43. private final ClusterAwareAlertClient alertClient;
  44. private final DashboardConfig dashboardConfig;
  45. private final ConcurrentHashMap<String, DashboardAlertStatus> alertsByHost = new ConcurrentHashMap<String, DashboardAlertStatus>();
  46. private final ConcurrentHashMap<String, DashboardAlertStatus> alertsByType = new ConcurrentHashMap<String, DashboardAlertStatus>();
  47. private final ConcurrentHashMap<String, DashboardAlertStatus> alertsByPathWithType = new ConcurrentHashMap<String, DashboardAlertStatus>();
  48. private final ConcurrentHashMap<String, DashboardAlertStatus> alertsOverall = new ConcurrentHashMap<String, DashboardAlertStatus>();
  49. private final ConcurrentHashMap<String,Long> alertMatchMap = new ConcurrentHashMap<String,Long>();
  50. private volatile Boolean alertStatusAvailable = false;
  51. @Inject
  52. public AlertStatusManager(DashboardConfig dashboardConfig,
  53. ClusterAwareAlertClient alertClient) {
  54. this.dashboardConfig = dashboardConfig;
  55. this.alertClient = alertClient;
  56. }
  57. public synchronized void start()
  58. {
  59. if (!dashboardConfig.isAlertManagerEnabled()) {
  60. log.info("Disabling the alertManager");
  61. return;
  62. }
  63. // one thread should be fine
  64. this.executor = new ScheduledThreadPoolExecutor(1);
  65. // start the config updater
  66. this.executor.scheduleAtFixedRate(this,0,CONFIG_UPDATE_INTERVAL,TimeUnit.MILLISECONDS);
  67. }
  68. public synchronized void stop()
  69. {
  70. if (this.executor != null) {
  71. this.executor.shutdown();
  72. this.executor = null;
  73. }
  74. }
  75. // this doesn't need to be synchronized, it's ok if it's caught in between
  76. public boolean isAlertStatusAvailable() {
  77. return this.alertStatusAvailable;
  78. }
  79. public boolean isHostMetricInAlert(String eventType,String attributeType,String hostName) {
  80. String key = getHostKey(eventType,attributeType,hostName);
  81. if(alertMatchMap.containsKey(key)) {
  82. return true;
  83. }
  84. else {
  85. return false;
  86. }
  87. }
  88. public boolean isTypeMetricInAlert(String eventType,String attributeType,String typeName) {
  89. String key = getTypeKey(eventType,attributeType,typeName);
  90. if(alertMatchMap.containsKey(key))
  91. return true;
  92. else
  93. return false;
  94. }
  95. public boolean isPathWithTypeMetricInAlert(String eventType,String attributeType,String path,String typeName) {
  96. String key = getPathWithTypeKey(eventType,attributeType,path,typeName);
  97. if(alertMatchMap.containsKey(key))
  98. return true;
  99. else
  100. return false;
  101. }
  102. public boolean isOverallMetricInAlert(String eventType,String attributeType) {
  103. String key = getOverallKey(eventType,attributeType);
  104. if(alertMatchMap.containsKey(key))
  105. return true;
  106. else
  107. return false;
  108. }
  109. public boolean isMetricInAlert(String eventType,String attributeType,String typeName,String path,String hostName) {
  110. if(hostName != null && !hostName.equals(UNDEFINED_HOST_NAME)) {
  111. return isHostMetricInAlert(eventType,attributeType,hostName);
  112. }
  113. else if(typeName != null && !typeName.equals(UNDEFINED_TYPE_NAME)) {
  114. if(path != null && !path.equals(UNDEFINED_PATH_NAME)) {
  115. return isPathWithTypeMetricInAlert(eventType,attributeType,path,typeName);
  116. }
  117. else {
  118. return isTypeMetricInAlert(eventType,attributeType,typeName);
  119. }
  120. }
  121. else {
  122. return isOverallMetricInAlert(eventType,attributeType);
  123. }
  124. }
  125. public List<DashboardAlertStatus> getMetricsInAlert() {
  126. ArrayList<DashboardAlertStatus> retList = new ArrayList<DashboardAlertStatus>();
  127. Collection<DashboardAlertStatus> alertStatii = alertsOverall.values();
  128. for(DashboardAlertStatus alertStatus:alertStatii) {
  129. retList.add(alertStatus);
  130. }
  131. return retList;
  132. }
  133. public int getNumMetricsInAlert() {
  134. return alertsOverall.size();
  135. }
  136. public List<DashboardAlertStatus> getMetricsInAlert(String eventType,String attributeType,String typeName,String path,String hostName) {
  137. ArrayList<DashboardAlertStatus> retList = new ArrayList<DashboardAlertStatus>();
  138. String eventAttributeSubKey = getEventAttributeSubKey(eventType,attributeType);
  139. if(hostName != null && !hostName.equals(UNDEFINED_HOST_NAME)) {
  140. String hostSubKey = getHostSubKey(hostName);
  141. Set<String> keys = alertsByHost.keySet();
  142. for(String key:keys) {
  143. if(key.contains(eventAttributeSubKey) && key.contains(hostSubKey)) {
  144. DashboardAlertStatus alertStatus = alertsByHost.get(key);
  145. if(alertStatus != null)
  146. retList.add(alertStatus);
  147. }
  148. }
  149. }
  150. else if(typeName != null && !typeName.equals(UNDEFINED_TYPE_NAME)) {
  151. if(path != null && !path.equals(UNDEFINED_PATH_NAME)) {
  152. String pathWithTypeSubKey = getPathWithTypeSubKey(path,typeName);
  153. Set<String> keys = alertsByPathWithType.keySet();
  154. for(String key:keys) {
  155. if(key.contains(eventAttributeSubKey) && key.contains(pathWithTypeSubKey)) {
  156. DashboardAlertStatus alertStatus = alertsByPathWithType.get(key);
  157. if(alertStatus != null)
  158. retList.add(alertStatus);
  159. }
  160. }
  161. }
  162. else {
  163. String typeSubKey = getTypeSubKey(typeName);
  164. Set<String> keys = alertsByType.keySet();
  165. for(String key:keys) {
  166. if(key.contains(eventAttributeSubKey) && key.contains(typeSubKey)) {
  167. DashboardAlertStatus alertStatus = alertsByType.get(key);
  168. if(alertStatus != null)
  169. retList.add(alertStatus);
  170. }
  171. }
  172. }
  173. }
  174. else {
  175. Set<String> keys = alertsOverall.keySet();
  176. for(String key:keys) {
  177. if(key.contains(eventAttributeSubKey)) {
  178. DashboardAlertStatus alertStatus = alertsOverall.get(key);
  179. if(alertStatus != null)
  180. retList.add(alertStatus);
  181. }
  182. }
  183. }
  184. if(retList.size() == 0)
  185. return null;
  186. return retList;
  187. }
  188. public synchronized void run() {
  189. try {
  190. List<DashboardAlertStatus> alertStatusList = alertClient.getAlertStatus(generationCount.get());
  191. if(alertStatusList != null && alertStatusList.size() > 0) {
  192. for(DashboardAlertStatus alertStatus:alertStatusList) {
  193. addToHostMapIfApplicable(alertStatus);
  194. addToTypeMapIfApplicable(alertStatus);
  195. addToPathWithTypeMapIfApplicable(alertStatus);
  196. addToOverallMap(alertStatus);
  197. }
  198. }
  199. purgePreviousGenerations(generationCount.getAndIncrement());
  200. alertStatusAvailable = true;
  201. }
  202. catch(RuntimeException ruEx) {
  203. log.warn(ruEx,"Got RuntimeException retrieving alert status data");
  204. try {
  205. alertStatusAvailable = false;
  206. purgePreviousGenerations(generationCount.getAndIncrement());
  207. }
  208. catch(RuntimeException ruEx2) {
  209. log.warn(ruEx2);
  210. }
  211. }
  212. }
  213. private String getHostKey(String eventType,String attributeType,String hostName) {
  214. return KEY_DELIM + eventType + KEY_DELIM + attributeType + KEY_DELIM + hostName + KEY_DELIM;
  215. }
  216. private String getTypeKey(String eventType,String attributeType,String typeName) {
  217. return KEY_DELIM + eventType + KEY_DELIM + attributeType + KEY_DELIM + typeName + KEY_DELIM;
  218. }
  219. private String getPathWithTypeKey(String eventType,String attributeType,String path,String typeName) {
  220. return KEY_DELIM + eventType + KEY_DELIM + attributeType + KEY_DELIM + path + KEY_DELIM + typeName + KEY_DELIM;
  221. }
  222. private String getOverallKey(String eventType,String attributeType) {
  223. return getEventAttributeSubKey(eventType,attributeType);
  224. }
  225. private String getHostSubKey(String hostName) {
  226. return KEY_DELIM + hostName + KEY_DELIM;
  227. }
  228. private String getPathWithTypeSubKey(String path,String typeName) {
  229. return KEY_DELIM + path + KEY_DELIM + typeName + KEY_DELIM;
  230. }
  231. private String getTypeSubKey(String typeName) {
  232. return KEY_DELIM + typeName + KEY_DELIM;
  233. }
  234. private String getEventAttributeSubKey(String eventType,String attributeType) {
  235. return KEY_DELIM + eventType + KEY_DELIM + attributeType + KEY_DELIM;
  236. }
  237. private synchronized boolean addToHostMapIfApplicable(DashboardAlertStatus alertStatus) {
  238. String hostName;
  239. if((hostName = alertStatus.getAttribute(HOST_ATTR)) != null) {
  240. String eventType = alertStatus.getEventType();
  241. String attributeType = alertStatus.getAttributeType();
  242. String key = getHostKey(eventType,attributeType,hostName);
  243. String fullKey = key + KEY_DELIM + alertStatus.getAlertId();
  244. alertsByHost.put(fullKey,alertStatus);
  245. alertMatchMap.put(key, alertStatus.getGenerationCount());
  246. return true;
  247. }
  248. return false;
  249. }
  250. private synchronized boolean addToTypeMapIfApplicable(DashboardAlertStatus alertStatus) {
  251. String typeName;
  252. if((typeName = alertStatus.getAttribute(TYPE_ATTR)) != null) {
  253. String eventType = alertStatus.getEventType();
  254. String attributeType = alertStatus.getAttributeType();
  255. String key = getTypeKey(eventType,attributeType,typeName);
  256. String fullKey = key + KEY_DELIM + alertStatus.getAlertId();
  257. alertsByType.put(fullKey,alertStatus);
  258. alertMatchMap.put(key, alertStatus.getGenerationCount());
  259. return true;
  260. }
  261. return false;
  262. }
  263. private synchronized boolean addToPathWithTypeMapIfApplicable(DashboardAlertStatus alertStatus) {
  264. String typeName;
  265. String path;
  266. if((path = alertStatus.getAttribute(PATH_ATTR)) != null &&
  267. (typeName = alertStatus.getAttribute(TYPE_ATTR)) != null) {
  268. String eventType = alertStatus.getEventType();
  269. String attributeType = alertStatus.getAttributeType();
  270. String key = getPathWithTypeKey(eventType,attributeType,path,typeName);
  271. String fullKey = key + KEY_DELIM + alertStatus.getAlertId();
  272. alertsByPathWithType.put(fullKey,alertStatus);
  273. alertMatchMap.put(key, alertStatus.getGenerationCount());
  274. return true;
  275. }
  276. return false;
  277. }
  278. private synchronized boolean addToOverallMap(DashboardAlertStatus alertStatus) {
  279. String eventType = alertStatus.getEventType();
  280. String attributeType = alertStatus.getAttributeType();
  281. String key = getOverallKey(eventType,attributeType);
  282. String fullKey = key + KEY_DELIM + alertStatus.getAlertId();
  283. alertsOverall.put(fullKey,alertStatus);
  284. alertMatchMap.put(key, alertStatus.getGenerationCount());
  285. return true;
  286. }
  287. private synchronized void purgePreviousGenerations(long genCount) {
  288. Set<String> keys = alertMatchMap.keySet();
  289. for(String key:keys) {
  290. Long matchGenCount = alertMatchMap.get(key);
  291. if(matchGenCount != genCount) {
  292. alertMatchMap.remove(key);
  293. }
  294. }
  295. keys = alertsByHost.keySet();
  296. for(String key:keys) {
  297. DashboardAlertStatus alertStatus = alertsByHost.get(key);
  298. if(alertStatus.getGenerationCount() != genCount) {
  299. alertsByHost.remove(key);
  300. }
  301. }
  302. keys = alertsByType.keySet();
  303. for(String key:keys) {
  304. DashboardAlertStatus alertStatus = alertsByType.get(key);
  305. if(alertStatus.getGenerationCount() != genCount)
  306. alertsByType.remove(key);
  307. }
  308. keys = alertsByPathWithType.keySet();
  309. for(String key:keys) {
  310. DashboardAlertStatus alertStatus = alertsByPathWithType.get(key);
  311. if(alertStatus.getGenerationCount() != genCount)
  312. alertsByPathWithType.remove(key);
  313. }
  314. keys = alertsOverall.keySet();
  315. for(String key:keys) {
  316. DashboardAlertStatus alertStatus = alertsOverall.get(key);
  317. if(alertStatus.getGenerationCount() != genCount)
  318. alertsOverall.remove(key);
  319. }
  320. }
  321. }