View Javadoc

1   package org.apache.helix.alerts;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.HashMap;
23  import java.util.HashSet;
24  import java.util.LinkedList;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.helix.HelixDataAccessor;
29  import org.apache.helix.HelixException;
30  import org.apache.helix.HelixManager;
31  import org.apache.helix.HelixProperty;
32  import org.apache.helix.PropertyKey;
33  import org.apache.helix.PropertyType;
34  import org.apache.helix.ZNRecord;
35  import org.apache.helix.PropertyKey.Builder;
36  import org.apache.helix.controller.stages.HealthDataCache;
37  import org.apache.helix.model.AlertStatus;
38  import org.apache.helix.model.Alerts;
39  import org.apache.log4j.Logger;
40  
41  
42  public class AlertsHolder {
43  
44  	private static final Logger logger = Logger
45  		    .getLogger(AlertsHolder.class.getName());
46  
47  	HelixDataAccessor _accessor;
48  	HealthDataCache _cache;
49  	Map<String, Map<String,String>> _alertsMap; //not sure if map or set yet
50  	Map<String, Map<String,String>> _alertStatusMap;
51  	//Alerts _alerts;
52  	HashSet<String> alerts;
53  	StatsHolder _statsHolder;
54  
55    private final HelixManager _manager;
56  
57    private Builder _keyBuilder;
58  
59  	public AlertsHolder(HelixManager manager, HealthDataCache cache)
60  	{
61  	  this(manager, cache, new StatsHolder(manager, cache));
62  	}
63  	
64  	public AlertsHolder(HelixManager manager, HealthDataCache cache, StatsHolder statHolder)
65    {
66      _manager = manager;
67      _accessor = manager.getHelixDataAccessor();
68      _cache = cache;
69      _statsHolder = statHolder;
70      _keyBuilder = new PropertyKey.Builder(_manager.getClusterName());
71      updateCache(_cache);
72    }
73  
74  	public void refreshAlerts()
75  	{
76  	  _cache.refresh(_accessor);
77  		updateCache(_cache);
78  
79  
80  		/*
81  		_alertsMap = _cache.getAlerts();
82  		//TODO: confirm this a good place to init the _statMap when null
83  		if (_alertsMap == null) {
84  			_alertsMap = new HashMap<String, Map<String,String>>();
85  		}\*/
86  	}
87  
88  	public void refreshAlertStatus()
89  	{
90  		AlertStatus alertStatusRecord = _cache.getAlertStatus();
91  		if (alertStatusRecord != null) {
92  		_alertStatusMap = alertStatusRecord.getMapFields();
93  		}
94  		else {
95  			_alertStatusMap = new HashMap<String, Map<String,String>>();
96  		}
97  	}
98  
99  	public void persistAlerts()
100 	{
101 		//XXX: Am I using _accessor too directly here?
102 	  
103 		Alerts alerts = _accessor.getProperty(_keyBuilder.alerts());
104     if (alerts == null) {
105       alerts = new Alerts(Alerts.nodeName); //TODO: fix naming of this record, if it matters
106 		}
107 		alerts.getRecord().setMapFields(_alertsMap);
108 		 boolean retVal = _accessor.setProperty(_keyBuilder.alerts(), alerts);
109 		 logger.debug("persistAlerts retVal: "+retVal);
110 	}
111 
112 	public void persistAlertStatus()
113 	{
114 		//XXX: Am I using _accessor too directly here?
115 	  AlertStatus alertStatus = _accessor.getProperty(_keyBuilder.alertStatus());
116 		if (alertStatus == null) {
117 		  alertStatus = new AlertStatus(AlertStatus.nodeName); //TODO: fix naming of this record, if it matters
118 		}
119 		alertStatus.getRecord().setMapFields(_alertStatusMap);
120 		boolean retVal = _accessor.setProperty(_keyBuilder.alertStatus(), alertStatus);
121 		logger.debug("persistAlerts retVal: "+retVal);
122 	}
123 
124 	//read alerts from cm state
125 	private void readExistingAlerts()
126 	{
127 
128 	}
129 
130 	public void addAlert(String alert) throws HelixException
131 	{
132 		alert = alert.replaceAll("\\s+", ""); //remove white space
133 		AlertParser.validateAlert(alert);
134 		refreshAlerts();
135 		//stick the 3 alert fields in map
136 		Map<String, String> alertFields = new HashMap<String,String>();
137 		alertFields.put(AlertParser.EXPRESSION_NAME,
138 				AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert));
139 		alertFields.put(AlertParser.COMPARATOR_NAME,
140 				AlertParser.getComponent(AlertParser.COMPARATOR_NAME, alert));
141 		alertFields.put(AlertParser.CONSTANT_NAME,
142 				AlertParser.getComponent(AlertParser.CONSTANT_NAME, alert));
143 		try
144 		{
145 		  alertFields.put(AlertParser.ACTION_NAME,
146 	        AlertParser.getComponent(AlertParser.ACTION_NAME, alert));
147 		}
148 		catch(Exception e)
149 		{
150 		  logger.info("No action specified in " + alert);
151 		}
152 		//store the expression as stat
153 		_statsHolder.addStat(alertFields.get(AlertParser.EXPRESSION_NAME));
154         _statsHolder.persistStats();
155 
156 		//naming the alert with the full name
157 		_alertsMap.put(alert, alertFields);
158 		persistAlerts();
159 	}
160 
161 	/*
162 	 * Add a set of alert statuses to ZK
163 	 */
164 	public void addAlertStatusSet(Map<String, Map<String, AlertValueAndStatus>> statusSet) throws HelixException
165 	{
166 	  if (_alertStatusMap == null) {
167 	    _alertStatusMap = new HashMap<String, Map<String,String>>();
168 	  }
169 	  _alertStatusMap.clear(); //clear map.  all alerts overwrite old alerts
170 	  for (String alert : statusSet.keySet()) {
171 	    Map<String,AlertValueAndStatus> currStatus = statusSet.get(alert);
172 	    if (currStatus != null) {
173 	      addAlertStatus(alert, currStatus);
174 	    }
175 	  }
176 
177 	  AlertStatus alertStatus = _accessor.getProperty(_keyBuilder.alertStatus());
178 	  int alertStatusSize = 0;
179 	  if (alertStatus != null) {
180 	    alertStatusSize = alertStatus.getMapFields().size();
181 	  }
182 	  //no need to persist alerts if there are none to persist and none are currently persisted
183 	 if (_alertStatusMap.size() > 0  || alertStatusSize > 0) {
184 	  persistAlertStatus(); //save statuses in zk
185 	 }
186 	}
187 
188 	private void addAlertStatus(String parentAlertKey, Map<String,AlertValueAndStatus> alertStatus) throws HelixException
189 	{
190 		//_alertStatusMap = new HashMap<String,Map<String,String>>();
191 		for (String alertName : alertStatus.keySet()) {
192 			String mapAlertKey;
193 			mapAlertKey = parentAlertKey;
194 			if (!alertName.equals(ExpressionParser.wildcardChar)) {
195 				mapAlertKey = mapAlertKey+" : ("+alertName+")";
196 			}
197 			AlertValueAndStatus vs = alertStatus.get(alertName);
198 			Map<String,String> alertFields = new HashMap<String,String>();
199 			alertFields.put(AlertValueAndStatus.VALUE_NAME, vs.getValue().toString());
200 			alertFields.put(AlertValueAndStatus.FIRED_NAME, String.valueOf(vs.isFired()));
201 			_alertStatusMap.put(mapAlertKey, alertFields);
202 		}
203 	}
204 
205 	public AlertValueAndStatus getAlertValueAndStatus(String alertName)
206 	{
207 		Map<String,String> alertFields = _alertStatusMap.get(alertName);
208 		String val = alertFields.get(AlertValueAndStatus.VALUE_NAME);
209 		Tuple<String> valTup = new Tuple<String>();
210 		valTup.add(val);
211 		boolean fired = Boolean.valueOf(alertFields.get(AlertValueAndStatus.FIRED_NAME));
212 		AlertValueAndStatus vs = new AlertValueAndStatus(valTup, fired);
213 		return vs;
214 	}
215 
216 	public static void parseAlert(String alert, StringBuilder statsName,
217 			Map<String,String> alertFields) throws HelixException
218 	{
219 		alert = alert.replaceAll("\\s+", ""); //remove white space
220 		AlertParser.validateAlert(alert);
221 		//alertFields = new HashMap<String,String>();
222 		alertFields.put(AlertParser.EXPRESSION_NAME,
223 				AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert));
224 		alertFields.put(AlertParser.COMPARATOR_NAME,
225 				AlertParser.getComponent(AlertParser.COMPARATOR_NAME, alert));
226 		alertFields.put(AlertParser.CONSTANT_NAME,
227 				AlertParser.getComponent(AlertParser.CONSTANT_NAME, alert));
228 		try
229         {
230           alertFields.put(AlertParser.ACTION_NAME,
231           AlertParser.getComponent(AlertParser.ACTION_NAME, alert));
232         }
233         catch(Exception e)
234         {
235            logger.info("No action specified in " + alert);
236         }
237 		statsName.append(alertFields.get(AlertParser.EXPRESSION_NAME));
238 	}
239 
240 
241 	/*
242 	public void evaluateAllAlerts()
243 	{
244 		for (String alert : _alertsMap.keySet()) {
245 			Map<String,String> alertFields = _alertsMap.get(alert);
246 			String exp = alertFields.get(AlertParser.EXPRESSION_NAME);
247 			String comp = alertFields.get(AlertParser.COMPARATOR_NAME);
248 			String con = alertFields.get(AlertParser.CONSTANT_NAME);
249 			//TODO: test the fields for null and fail if needed
250 
251 			AlertProcessor.execute(exp,  comp, con, sh);
252 		}
253 	}
254 	*/
255 
256 	public List<Alert> getAlertList()
257 	{
258 		List<Alert> alerts = new LinkedList<Alert>();
259 		for (String alert : _alertsMap.keySet()) {
260 			Map<String,String> alertFields = _alertsMap.get(alert);
261 			String exp = alertFields.get(AlertParser.EXPRESSION_NAME);
262 			String comp = alertFields.get(AlertParser.COMPARATOR_NAME);
263 			Tuple<String> con = Tuple.fromString(alertFields.get(AlertParser.CONSTANT_NAME));
264 			//TODO: test the fields for null and fail if needed
265 
266 			Alert a = new Alert(alert, exp, comp, con);
267 			alerts.add(a);
268 		}
269 		return alerts;
270 	}
271 
272   public void updateCache(HealthDataCache cache)
273   {
274     _cache = cache;
275     Alerts alertsRecord = _cache.getAlerts();
276     if (alertsRecord != null) 
277     {
278       _alertsMap = alertsRecord.getMapFields();
279     }
280     else 
281     {
282       _alertsMap = new HashMap<String, Map<String,String>>();
283     }
284   }
285   
286   public Map<String, Map<String,String>> getAlertsMap()
287   {
288     return _alertsMap;
289   }
290 }