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.Map;
24  
25  import org.apache.helix.HelixException;
26  import org.apache.helix.Mocks.MockManager;
27  import org.apache.helix.alerts.AlertParser;
28  import org.apache.helix.alerts.AlertProcessor;
29  import org.apache.helix.alerts.AlertValueAndStatus;
30  import org.apache.helix.alerts.AlertsHolder;
31  import org.apache.helix.alerts.StatsHolder;
32  import org.apache.helix.controller.stages.HealthDataCache;
33  import org.testng.AssertJUnit;
34  import org.testng.annotations.BeforeMethod;
35  import org.testng.annotations.Test;
36  
37  
38  public class TestEvaluateAlerts {
39    protected static final String CLUSTER_NAME = "TestCluster";
40  
41    MockManager _helixManager;
42    AlertsHolder _alertsHolder;
43    StatsHolder _statsHolder;
44  
45    public final String EXP = AlertParser.EXPRESSION_NAME;
46    public final String CMP = AlertParser.COMPARATOR_NAME;
47    public final String CON = AlertParser.CONSTANT_NAME;
48  
49    @BeforeMethod (groups = {"unitTest"})
50    public void setup()
51    {
52      HealthDataCache cache = new HealthDataCache();
53      _helixManager = new MockManager(CLUSTER_NAME);
54      _alertsHolder = new AlertsHolder(_helixManager, cache);
55      _statsHolder = _alertsHolder._statsHolder;
56    }
57  
58    public Map<String,String> getStatFields(String value, String timestamp)
59    {
60      Map<String, String> statMap = new HashMap<String,String>();
61      statMap.put(StatsHolder.VALUE_NAME, value);
62      statMap.put(StatsHolder.TIMESTAMP_NAME, timestamp);
63      return statMap;
64    }
65  
66    public String getSimpleStat() throws HelixException
67    {
68      String stat = "accumulate()(dbFoo.partition10.latency)";
69      //_statsHolder.addStat(stat);
70      return stat;
71    }
72  
73    public String addPairOfStats() throws HelixException
74    {
75      String stat = "accumulate()(dbFoo.partition10.latency, dbFoo.partition11.latency)";
76      _statsHolder.addStat(stat);
77      _statsHolder.persistStats();
78      return stat;
79    }
80  
81    public String getWildcardStat() throws HelixException
82    {
83      String stat = "accumulate()(dbFoo.partition*.latency)";
84      //_statsHolder.addStat(stat);
85      return stat;
86    }
87  
88    public String addSimpleAlert() throws HelixException
89    {
90      String alert = EXP + "(accumulate()(dbFoo.partition10.latency))"
91          + CMP + "(GREATER)" + CON + "(100)";
92         _alertsHolder.addAlert(alert);
93         return alert;
94    }
95  
96    public String addWildcardAlert() throws HelixException
97    {
98      String alert = EXP + "(accumulate()(dbFoo.partition*.latency))"
99          + CMP + "(GREATER)" + CON + "(100)";
100        _alertsHolder.addAlert(alert);
101        return alert;
102   }
103 
104   public String addTwoWildcardAlert() throws HelixException
105   {
106     String alert = EXP + "(accumulate()(dbFoo.partition*.put*))"
107         + CMP + "(GREATER)" + CON + "(100)";
108        _alertsHolder.addAlert(alert);
109        return alert;
110   }
111 
112 
113   public String addExpandWildcardAlert() throws HelixException
114   {
115     String alert = EXP + "(accumulate()(dbFoo.partition*.latency)|EXPAND)"
116         + CMP + "(GREATER)" + CON + "(100)";
117        _alertsHolder.addAlert(alert);
118        return alert;
119   }
120 
121   public String addExpandSumAlert() throws HelixException
122   {
123     String alert = EXP + "(accumulate()(dbFoo.partition10.latency,dbFoo.partition11.latency)|EXPAND|SUM)"
124         + CMP + "(GREATER)" + CON + "(100)";
125        _alertsHolder.addAlert(alert);
126        return alert;
127   }
128 
129   public String addExpandSumWildcardAlert() throws HelixException
130   {
131     String alert = EXP + "(accumulate()(dbFoo.partition*.success,dbFoo.partition*.failure)|EXPAND|SUM)"
132         + CMP + "(GREATER)" + CON + "(100)";
133        _alertsHolder.addAlert(alert);
134        return alert;
135   }
136 
137   public String addExpandSumEachWildcardAlert() throws HelixException
138   {
139     String alert = EXP + "(accumulate()(dbFoo.partition*.success,dbFoo.partition*.failure)|EXPAND|SUMEACH)"
140         + CMP + "(GREATER)" + CON + "(100)";
141        _alertsHolder.addAlert(alert);
142        return alert;
143   }
144 
145   public String addExpandSumEachSumWildcardAlert() throws HelixException
146   {
147     String alert = EXP + "(accumulate()(dbFoo.partition*.success,dbFoo.partition*.failure)|EXPAND|SUMEACH|SUM)"
148         + CMP + "(GREATER)" + CON + "(100)";
149        _alertsHolder.addAlert(alert);
150        return alert;
151   }
152 
153   public String addArrivingSimpleStat() throws HelixException
154   {
155     _statsHolder.refreshStats();
156     String incomingStatName = "dbFoo.partition10.latency";
157     Map<String, String> statFields = getStatFields("110","0");
158     _statsHolder.applyStat(incomingStatName, statFields);
159     _statsHolder.persistStats();
160     return incomingStatName;
161   }
162 
163   public String addArrivingPairOfStats() throws HelixException
164   {
165     _statsHolder.refreshStats();
166     String incomingStatName1 = "dbFoo.partition10.latency";
167     String incomingStatName2 = "dbFoo.partition11.latency";
168     Map<String, String> statFields = getStatFields("50","0");
169     _statsHolder.applyStat(incomingStatName1, statFields);
170     statFields = getStatFields("51","0");
171     _statsHolder.applyStat(incomingStatName2, statFields);
172     _statsHolder.persistStats();
173     return null;
174   }
175 
176   @Test (groups = {"unitTest"})
177   public void testSimpleAlertFires()
178   {
179     String alert = addSimpleAlert();
180     String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
181     _statsHolder.refreshStats(); //need to refresh since not triggered by stats aggregation stage
182     addArrivingSimpleStat();
183     Map<String, Map<String, AlertValueAndStatus>> alertResult = AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
184     boolean alertFired = alertResult.get(alert).get(AlertProcessor.noWildcardAlertKey).isFired();
185      AssertJUnit.assertTrue(alertFired);
186   }
187 
188   @Test (groups = {"unitTest"})
189   public void testSimpleAlertNoStatArrivesFires()
190   {
191     String alert = addSimpleAlert();
192     String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
193     Map<String, Map<String, AlertValueAndStatus>> alertResult = AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
194     AssertJUnit.assertEquals(null, alertResult.get(AlertProcessor.noWildcardAlertKey));
195   }
196 
197   @Test (groups = {"unitTest"})
198   public void testWildcardAlertFires()
199   {
200     String alert = addWildcardAlert();
201     String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
202     String incomingStatName = addArrivingSimpleStat();
203 
204     Map<String, Map<String, AlertValueAndStatus>> alertResult = AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
205     String wildcardBinding = incomingStatName;
206     boolean alertFired = alertResult.get(alert).get(wildcardBinding).isFired();
207     AssertJUnit.assertTrue(alertFired);
208   }
209 
210   @Test (groups = {"unitTest"})
211   public void testExpandOperatorWildcardAlertFires()
212   {
213     String alert = addExpandWildcardAlert();
214     String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
215     String incomingStatName = addArrivingSimpleStat();
216     Map<String, Map<String, AlertValueAndStatus>> alertResult = AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
217     String wildcardBinding = incomingStatName;
218     boolean alertFired = alertResult.get(alert).get(wildcardBinding).isFired();
219     AssertJUnit.assertTrue(alertFired);
220   }
221 
222   @Test (groups = {"unitTest"})
223   public void testExpandSumOperatorAlertFires()
224   {
225     String alert = addExpandSumAlert();
226     String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
227     addArrivingPairOfStats();
228     Map<String, Map<String, AlertValueAndStatus>> alertResult = AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
229     boolean alertFired = alertResult.get(alert).get(AlertProcessor.noWildcardAlertKey).isFired();
230     AssertJUnit.assertTrue(alertFired);
231   }
232 /**
233  *
234  * We need to re-decide how to support the feature to specify more than one stats in
235  * an alert.
236  *
237  * Probabaly instead of
238  * "(dbFoo.partition*.success,dbFoo.partition*.failure)", use the form
239  * "(dbFoo.partition*.(success, failure))" as it seems that the stat source is always the
240  * same.
241  *
242   //@Test (groups = {"unitTest"})
243   public void testExpandSumOperatorWildcardAlert()
244   {
245     String alert = addExpandSumWildcardAlert();
246     String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
247     String part10SuccStat = "dbFoo.partition10.success";
248     String part10FailStat = "dbFoo.partition10.failure";
249     String part11SuccStat = "dbFoo.partition11.success";
250     String part11FailStat = "dbFoo.partition11.failure";
251 
252 
253     Map<String, String> statFields = getStatFields("50","0");
254     _statsHolder.applyStat(part10SuccStat, statFields);
255     statFields = getStatFields("51","0");
256     _statsHolder.applyStat(part10FailStat, statFields);
257     statFields = getStatFields("50","0");
258     _statsHolder.applyStat(part11SuccStat, statFields);
259     statFields = getStatFields("49","0");
260     _statsHolder.applyStat(part11FailStat, statFields);
261     Map<String, Map<String, AlertValueAndStatus>> alertResult = AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
262     boolean alertFired = alertResult.get(alert).get("10").isFired(); //10 should fire
263     AssertJUnit.assertTrue(alertFired);
264     alertFired = alertResult.get(alert).get("11").isFired(); //11 should not fire
265     AssertJUnit.assertFalse(alertFired);
266   }
267 
268   //@Test (groups = {"unitTest"})
269   public void testExpandSumEachSumOperatorWildcardAlert()
270   {
271     String alert = addExpandSumEachSumWildcardAlert();
272     String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
273     String part10SuccStat = "dbFoo.partition10.success";
274     String part10FailStat = "dbFoo.partition10.failure";
275     String part11SuccStat = "dbFoo.partition11.success";
276     String part11FailStat = "dbFoo.partition11.failure";
277 
278 
279     Map<String, String> statFields = getStatFields("50","0");
280     _statsHolder.applyStat(part10SuccStat, statFields);
281     statFields = getStatFields("51","0");
282     _statsHolder.applyStat(part10FailStat, statFields);
283     statFields = getStatFields("50","0");
284     _statsHolder.applyStat(part11SuccStat, statFields);
285     statFields = getStatFields("49","0");
286     _statsHolder.applyStat(part11FailStat, statFields);
287     Map<String, Map<String, AlertValueAndStatus>> alertResult = AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
288     boolean alertFired = alertResult.get(alert).get(_statsHolder.getStatsList().get(0)).isFired(); //10 should fire
289     AssertJUnit.assertTrue(alertFired);
290   }
291 
292   //@Test (groups = {"unitTest"})
293   public void testTwoAlerts()
294   {
295     //alert 1
296     String alert1 = addSimpleAlert();
297     String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert1);
298     addArrivingSimpleStat();
299 
300     //alert 2
301     String alert2 = addExpandSumWildcardAlert();
302     stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert2);
303     String part10SuccStat = "dbFoo.partition10.success";
304     String part10FailStat = "dbFoo.partition10.failure";
305     String part11SuccStat = "dbFoo.partition11.success";
306     String part11FailStat = "dbFoo.partition11.failure";
307 
308 
309     Map<String, String> statFields = getStatFields("50","0");
310     _statsHolder.applyStat(part10SuccStat, statFields);
311     statFields = getStatFields("51","0");
312     _statsHolder.applyStat(part10FailStat, statFields);
313     statFields = getStatFields("50","0");
314     _statsHolder.applyStat(part11SuccStat, statFields);
315     statFields = getStatFields("49","0");
316     _statsHolder.applyStat(part11FailStat, statFields);
317     Map<String, Map<String, AlertValueAndStatus>> alertResult = AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
318 
319     //alert 1 check
320     boolean alertFired = alertResult.get(alert1).get(AlertProcessor.noWildcardAlertKey).isFired();
321     AssertJUnit.assertTrue(alertFired);
322 
323     //alert 2 check
324     alertFired = alertResult.get(alert2).get("10").isFired(); //10 should fire
325     AssertJUnit.assertTrue(alertFired);
326     alertFired = alertResult.get(alert2).get("11").isFired(); //11 should not fire
327     AssertJUnit.assertFalse(alertFired);
328 
329   }
330 */
331   @Test (groups = {"unitTest"})
332     public void testAddWildcardInFirstStatToken() throws Exception
333     {
334     String alert = "EXP(decay(1)(instance*.reportingage))CMP(GREATER)CON(300)";
335      _alertsHolder.addAlert(alert);
336      _statsHolder.persistStats();
337      
338      _statsHolder.refreshStats();
339      //generate incoming stat
340      String incomingStatName = "instance10.reportingage";
341      Map<String, String> statFields = getStatFields("301","10");
342      _statsHolder.refreshStats();
343      
344      _statsHolder.applyStat(incomingStatName, statFields);
345      _statsHolder.persistStats();
346 
347      Map<String, Map<String, AlertValueAndStatus>> alertResult = AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
348      String wildcardBinding = incomingStatName;
349      boolean alertFired = alertResult.get(alert).get(wildcardBinding).isFired();
350      AssertJUnit.assertTrue(alertFired);
351     }
352 
353   @Test (groups = {"unitTest"})
354   public void testTwoWildcardAlertFires()
355   {
356     //error is with * and )
357     String alert = addTwoWildcardAlert();
358     String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
359     String incomingStatName = "dbFoo.partition10.putCount";
360     Map<String, String> statFields = getStatFields("110","0");
361     _statsHolder.refreshStats();
362     _statsHolder.applyStat(incomingStatName, statFields);
363     _statsHolder.persistStats();
364     Map<String, Map<String, AlertValueAndStatus>> alertResult = AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
365     String wildcardBinding = incomingStatName; //XXX: this is not going to work...need "Count" in here too.
366     boolean alertFired = alertResult.get(alert).get(wildcardBinding).isFired();
367     AssertJUnit.assertTrue(alertFired);
368   }
369 
370   /* only supporting wildcards at end of components right now
371   @Test (groups = {"unitTest"})
372   public void testTwoWildcardsNotAtEndFires()
373   {
374     String alert = EXP + "(accumulate()(dbFoo.partition*.*Count))"
375         + CMP + "(GREATER)" + CON + "(100)";
376     _alertsHolder.addAlert(alert);
377     String incomingStatName = "dbFoo.partition10.putCount";
378     Map<String, String> statFields = getStatFields("110","0");
379     _statsHolder.applyStat(incomingStatName, statFields);
380     Map<String, Map<String, AlertValueAndStatus>> alertResult = AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
381     String wildcardBinding = "10,put"; //XXX: this is not going to work...need "Count" in here too.
382     boolean alertFired = alertResult.get(alert).get(wildcardBinding).isFired();
383     AssertJUnit.assertTrue(alertFired);
384   }
385   */
386 
387   //test using sumall
388   //test using rows where some tuples are null (no stat sent)
389   //test with window tuples where some windows are different lengths
390   //anything else, look around at the code
391 
392   //next: review all older tests
393   //next: actually write the fired alerts to ZK
394 
395 }