package org.apache.helix.alerts;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.util.HashMap;
import java.util.Map;
import org.apache.helix.HelixException;
import org.apache.helix.Mocks.MockManager;
import org.apache.helix.controller.stages.HealthDataCache;
import org.testng.AssertJUnit;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class TestEvaluateAlerts {
protected static final String CLUSTER_NAME = "TestCluster";
MockManager _helixManager;
AlertsHolder _alertsHolder;
StatsHolder _statsHolder;
public final String EXP = AlertParser.EXPRESSION_NAME;
public final String CMP = AlertParser.COMPARATOR_NAME;
public final String CON = AlertParser.CONSTANT_NAME;
@BeforeMethod(groups = {
"unitTest"
})
public void setup() {
HealthDataCache cache = new HealthDataCache();
_helixManager = new MockManager(CLUSTER_NAME);
_alertsHolder = new AlertsHolder(_helixManager, cache);
_statsHolder = _alertsHolder._statsHolder;
}
public Map<String, String> getStatFields(String value, String timestamp) {
Map<String, String> statMap = new HashMap<String, String>();
statMap.put(StatsHolder.VALUE_NAME, value);
statMap.put(StatsHolder.TIMESTAMP_NAME, timestamp);
return statMap;
}
public String getSimpleStat() throws HelixException {
String stat = "accumulate()(dbFoo.partition10.latency)";
// _statsHolder.addStat(stat);
return stat;
}
public String addPairOfStats() throws HelixException {
String stat = "accumulate()(dbFoo.partition10.latency, dbFoo.partition11.latency)";
_statsHolder.addStat(stat);
_statsHolder.persistStats();
return stat;
}
public String getWildcardStat() throws HelixException {
String stat = "accumulate()(dbFoo.partition*.latency)";
// _statsHolder.addStat(stat);
return stat;
}
public String addSimpleAlert() throws HelixException {
String alert =
EXP + "(accumulate()(dbFoo.partition10.latency))" + CMP + "(GREATER)" + CON + "(100)";
_alertsHolder.addAlert(alert);
return alert;
}
public String addWildcardAlert() throws HelixException {
String alert =
EXP + "(accumulate()(dbFoo.partition*.latency))" + CMP + "(GREATER)" + CON + "(100)";
_alertsHolder.addAlert(alert);
return alert;
}
public String addTwoWildcardAlert() throws HelixException {
String alert =
EXP + "(accumulate()(dbFoo.partition*.put*))" + CMP + "(GREATER)" + CON + "(100)";
_alertsHolder.addAlert(alert);
return alert;
}
public String addExpandWildcardAlert() throws HelixException {
String alert =
EXP + "(accumulate()(dbFoo.partition*.latency)|EXPAND)" + CMP + "(GREATER)" + CON + "(100)";
_alertsHolder.addAlert(alert);
return alert;
}
public String addExpandSumAlert() throws HelixException {
String alert =
EXP + "(accumulate()(dbFoo.partition10.latency,dbFoo.partition11.latency)|EXPAND|SUM)"
+ CMP + "(GREATER)" + CON + "(100)";
_alertsHolder.addAlert(alert);
return alert;
}
public String addExpandSumWildcardAlert() throws HelixException {
String alert =
EXP + "(accumulate()(dbFoo.partition*.success,dbFoo.partition*.failure)|EXPAND|SUM)" + CMP
+ "(GREATER)" + CON + "(100)";
_alertsHolder.addAlert(alert);
return alert;
}
public String addExpandSumEachWildcardAlert() throws HelixException {
String alert =
EXP + "(accumulate()(dbFoo.partition*.success,dbFoo.partition*.failure)|EXPAND|SUMEACH)"
+ CMP + "(GREATER)" + CON + "(100)";
_alertsHolder.addAlert(alert);
return alert;
}
public String addExpandSumEachSumWildcardAlert() throws HelixException {
String alert =
EXP
+ "(accumulate()(dbFoo.partition*.success,dbFoo.partition*.failure)|EXPAND|SUMEACH|SUM)"
+ CMP + "(GREATER)" + CON + "(100)";
_alertsHolder.addAlert(alert);
return alert;
}
public String addArrivingSimpleStat() throws HelixException {
_statsHolder.refreshStats();
String incomingStatName = "dbFoo.partition10.latency";
Map<String, String> statFields = getStatFields("110", "0");
_statsHolder.applyStat(incomingStatName, statFields);
_statsHolder.persistStats();
return incomingStatName;
}
public String addArrivingPairOfStats() throws HelixException {
_statsHolder.refreshStats();
String incomingStatName1 = "dbFoo.partition10.latency";
String incomingStatName2 = "dbFoo.partition11.latency";
Map<String, String> statFields = getStatFields("50", "0");
_statsHolder.applyStat(incomingStatName1, statFields);
statFields = getStatFields("51", "0");
_statsHolder.applyStat(incomingStatName2, statFields);
_statsHolder.persistStats();
return null;
}
@Test(groups = {
"unitTest"
})
public void testSimpleAlertFires() {
String alert = addSimpleAlert();
String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
_statsHolder.refreshStats(); // need to refresh since not triggered by stats aggregation stage
addArrivingSimpleStat();
Map<String, Map<String, AlertValueAndStatus>> alertResult =
AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
boolean alertFired = alertResult.get(alert).get(AlertProcessor.noWildcardAlertKey).isFired();
AssertJUnit.assertTrue(alertFired);
}
@Test(groups = {
"unitTest"
})
public void testSimpleAlertNoStatArrivesFires() {
String alert = addSimpleAlert();
String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
Map<String, Map<String, AlertValueAndStatus>> alertResult =
AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
AssertJUnit.assertEquals(null, alertResult.get(AlertProcessor.noWildcardAlertKey));
}
@Test(groups = {
"unitTest"
})
public void testWildcardAlertFires() {
String alert = addWildcardAlert();
String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
String incomingStatName = addArrivingSimpleStat();
Map<String, Map<String, AlertValueAndStatus>> alertResult =
AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
String wildcardBinding = incomingStatName;
boolean alertFired = alertResult.get(alert).get(wildcardBinding).isFired();
AssertJUnit.assertTrue(alertFired);
}
@Test(groups = {
"unitTest"
})
public void testExpandOperatorWildcardAlertFires() {
String alert = addExpandWildcardAlert();
String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
String incomingStatName = addArrivingSimpleStat();
Map<String, Map<String, AlertValueAndStatus>> alertResult =
AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
String wildcardBinding = incomingStatName;
boolean alertFired = alertResult.get(alert).get(wildcardBinding).isFired();
AssertJUnit.assertTrue(alertFired);
}
@Test(groups = {
"unitTest"
})
public void testExpandSumOperatorAlertFires() {
String alert = addExpandSumAlert();
String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
addArrivingPairOfStats();
Map<String, Map<String, AlertValueAndStatus>> alertResult =
AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
boolean alertFired = alertResult.get(alert).get(AlertProcessor.noWildcardAlertKey).isFired();
AssertJUnit.assertTrue(alertFired);
}
/**
* We need to re-decide how to support the feature to specify more than one stats in
* an alert.
* Probabaly instead of
* "(dbFoo.partition*.success,dbFoo.partition*.failure)", use the form
* "(dbFoo.partition*.(success, failure))" as it seems that the stat source is always the
* same.
*
//@Test (groups = {"unitTest"})
* public void testExpandSumOperatorWildcardAlert()
* {
* String alert = addExpandSumWildcardAlert();
* String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
* String part10SuccStat = "dbFoo.partition10.success";
* String part10FailStat = "dbFoo.partition10.failure";
* String part11SuccStat = "dbFoo.partition11.success";
* String part11FailStat = "dbFoo.partition11.failure";
* Map<String, String> statFields = getStatFields("50","0");
* _statsHolder.applyStat(part10SuccStat, statFields);
* statFields = getStatFields("51","0");
* _statsHolder.applyStat(part10FailStat, statFields);
* statFields = getStatFields("50","0");
* _statsHolder.applyStat(part11SuccStat, statFields);
* statFields = getStatFields("49","0");
* _statsHolder.applyStat(part11FailStat, statFields);
* Map<String, Map<String, AlertValueAndStatus>> alertResult =
* AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
* boolean alertFired = alertResult.get(alert).get("10").isFired(); //10 should fire
* AssertJUnit.assertTrue(alertFired);
* alertFired = alertResult.get(alert).get("11").isFired(); //11 should not fire
* AssertJUnit.assertFalse(alertFired);
* }
* //@Test (groups = {"unitTest"})
* public void testExpandSumEachSumOperatorWildcardAlert()
* {
* String alert = addExpandSumEachSumWildcardAlert();
* String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
* String part10SuccStat = "dbFoo.partition10.success";
* String part10FailStat = "dbFoo.partition10.failure";
* String part11SuccStat = "dbFoo.partition11.success";
* String part11FailStat = "dbFoo.partition11.failure";
* Map<String, String> statFields = getStatFields("50","0");
* _statsHolder.applyStat(part10SuccStat, statFields);
* statFields = getStatFields("51","0");
* _statsHolder.applyStat(part10FailStat, statFields);
* statFields = getStatFields("50","0");
* _statsHolder.applyStat(part11SuccStat, statFields);
* statFields = getStatFields("49","0");
* _statsHolder.applyStat(part11FailStat, statFields);
* Map<String, Map<String, AlertValueAndStatus>> alertResult =
* AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
* boolean alertFired = alertResult.get(alert).get(_statsHolder.getStatsList().get(0)).isFired();
* //10 should fire
* AssertJUnit.assertTrue(alertFired);
* }
* //@Test (groups = {"unitTest"})
* public void testTwoAlerts()
* {
* //alert 1
* String alert1 = addSimpleAlert();
* String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert1);
* addArrivingSimpleStat();
* //alert 2
* String alert2 = addExpandSumWildcardAlert();
* stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert2);
* String part10SuccStat = "dbFoo.partition10.success";
* String part10FailStat = "dbFoo.partition10.failure";
* String part11SuccStat = "dbFoo.partition11.success";
* String part11FailStat = "dbFoo.partition11.failure";
* Map<String, String> statFields = getStatFields("50","0");
* _statsHolder.applyStat(part10SuccStat, statFields);
* statFields = getStatFields("51","0");
* _statsHolder.applyStat(part10FailStat, statFields);
* statFields = getStatFields("50","0");
* _statsHolder.applyStat(part11SuccStat, statFields);
* statFields = getStatFields("49","0");
* _statsHolder.applyStat(part11FailStat, statFields);
* Map<String, Map<String, AlertValueAndStatus>> alertResult =
* AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
* //alert 1 check
* boolean alertFired = alertResult.get(alert1).get(AlertProcessor.noWildcardAlertKey).isFired();
* AssertJUnit.assertTrue(alertFired);
* //alert 2 check
* alertFired = alertResult.get(alert2).get("10").isFired(); //10 should fire
* AssertJUnit.assertTrue(alertFired);
* alertFired = alertResult.get(alert2).get("11").isFired(); //11 should not fire
* AssertJUnit.assertFalse(alertFired);
* }
*/
@Test(groups = {
"unitTest"
})
public void testAddWildcardInFirstStatToken() throws Exception {
String alert = "EXP(decay(1)(instance*.reportingage))CMP(GREATER)CON(300)";
_alertsHolder.addAlert(alert);
_statsHolder.persistStats();
_statsHolder.refreshStats();
// generate incoming stat
String incomingStatName = "instance10.reportingage";
Map<String, String> statFields = getStatFields("301", "10");
_statsHolder.refreshStats();
_statsHolder.applyStat(incomingStatName, statFields);
_statsHolder.persistStats();
Map<String, Map<String, AlertValueAndStatus>> alertResult =
AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
String wildcardBinding = incomingStatName;
boolean alertFired = alertResult.get(alert).get(wildcardBinding).isFired();
AssertJUnit.assertTrue(alertFired);
}
@Test(groups = {
"unitTest"
})
public void testTwoWildcardAlertFires() {
// error is with * and )
String alert = addTwoWildcardAlert();
String stat = AlertParser.getComponent(AlertParser.EXPRESSION_NAME, alert);
String incomingStatName = "dbFoo.partition10.putCount";
Map<String, String> statFields = getStatFields("110", "0");
_statsHolder.refreshStats();
_statsHolder.applyStat(incomingStatName, statFields);
_statsHolder.persistStats();
Map<String, Map<String, AlertValueAndStatus>> alertResult =
AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
String wildcardBinding = incomingStatName; // XXX: this is not going to work...need "Count" in
// here too.
boolean alertFired = alertResult.get(alert).get(wildcardBinding).isFired();
AssertJUnit.assertTrue(alertFired);
}
/*
* only supporting wildcards at end of components right now
* @Test (groups = {"unitTest"})
* public void testTwoWildcardsNotAtEndFires()
* {
* String alert = EXP + "(accumulate()(dbFoo.partition*.*Count))"
* + CMP + "(GREATER)" + CON + "(100)";
* _alertsHolder.addAlert(alert);
* String incomingStatName = "dbFoo.partition10.putCount";
* Map<String, String> statFields = getStatFields("110","0");
* _statsHolder.applyStat(incomingStatName, statFields);
* Map<String, Map<String, AlertValueAndStatus>> alertResult =
* AlertProcessor.executeAllAlerts(_alertsHolder.getAlertList(), _statsHolder.getStatsList());
* String wildcardBinding = "10,put"; //XXX: this is not going to work...need "Count" in here too.
* boolean alertFired = alertResult.get(alert).get(wildcardBinding).isFired();
* AssertJUnit.assertTrue(alertFired);
* }
*/
// test using sumall
// test using rows where some tuples are null (no stat sent)
// test with window tuples where some windows are different lengths
// anything else, look around at the code
// next: review all older tests
// next: actually write the fired alerts to ZK
}