package at.ac.tuwien.iter.services.impl.assertions;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.slf4j.Logger;
import at.ac.tuwien.iter.data.TestReport;
import at.ac.tuwien.iter.data.TestResult;
import at.ac.tuwien.iter.services.AssertionService;
import at.ac.tuwien.iter.services.impl.datacollector.DatabaseManagerService;
public class DoodleWebServiceAvgResponseTimeAssertion implements
AssertionService {
private Logger logger;
private DatabaseManagerService dbService;
private final String assertionName = "avg-response-time";
private double[] thresholds;
/**
*
* TODO: This is just an example, very basic, not clear code ;)
*
*
*
*
* CREATE TABLE `monitoring_dsg_customers_ale_services_ale` ( `time`
* timestamp, `date` datetime `kpi_CREATE_POLL_AvgRT` double DEFAULT NULL,
* `kpi_CREATE_POLL_AvgTX` double DEFAULT NULL, `kpi_CREATE_POLL_QL` double
* DEFAULT NULL, `kpi_CREATE_POLL_RC` double DEFAULT NULL,
* `kpi_CREATE_POLL_RD` double DEFAULT NULL, `kpi_DELETE_POLL_AvgRT` double
* DEFAULT NULL, `kpi_DELETE_POLL_AvgTX` double DEFAULT NULL,
* `kpi_DELETE_POLL_QL` double DEFAULT NULL, `kpi_DELETE_POLL_RC` double
* DEFAULT NULL, `kpi_DELETE_POLL_RD` double DEFAULT NULL,
* `kpi_GET_POLLS_AvgRT` double DEFAULT NULL, `kpi_GET_POLLS_AvgTX` double
* DEFAULT NULL, `kpi_GET_POLLS_QL` double DEFAULT NULL, `kpi_GET_POLLS_RC`
* double DEFAULT NULL, `kpi_GET_POLLS_RD` double DEFAULT NULL,
* `kpi_GET_POLL_AvgRT` double DEFAULT NULL, `kpi_GET_POLL_AvgTX` double
* DEFAULT NULL, `kpi_GET_POLL_QL` double DEFAULT NULL, `kpi_GET_POLL_RC`
* double DEFAULT NULL, `kpi_GET_POLL_RD` double DEFAULT NULL,
* `kpi_VOTE_AvgRT` double DEFAULT NULL, `kpi_VOTE_AvgTX` double DEFAULT
* NULL, `kpi_VOTE_QL` double DEFAULT NULL, `kpi_VOTE_RC` double DEFAULT
* NULL, `kpi_VOTE_RD` double DEFAULT NULL)
*
* @param logger
* @param dbService
* @param threshold
*
* TODO This can be made parametric, just add a conf file with
* inside something like a message.catalog with keys:
* KPI_NAME_LIST and MAX_VALUE or even CONDITION on KPI
*/
public DoodleWebServiceAvgResponseTimeAssertion(Logger logger,
DatabaseManagerService dbService, double... thresholds) {
this.logger = logger;
this.dbService = dbService;
this.thresholds = thresholds;
}
private String getTableName(Connection conn) throws SQLException {
// Finding the name of the table
DatabaseMetaData dbm = conn.getMetaData();
ResultSet rs = dbm.getTables(null, null, null, null);
String tableName = null;
while (rs.next()) {
String candidate = rs.getString(3);
if (candidate.toLowerCase().startsWith("monitoring_")) {
tableName = candidate;
break;
}
}
if (tableName == null) {
throw new RuntimeException("Cannot find the name of the table !");
}
return tableName;
}
// Better testability
protected TestReport check(String dbname) {
TestReport testReport = new TestReport();
testReport.setTestedProperty(assertionName);
Connection conn = null;
try {
Class.forName("org.hsqldb.jdbcDriver");
conn = DriverManager.getConnection(dbname, "sa", "");
// Get table name
String tableName = getTableName(conn);
// Select the values that are bigger than the thresholds
StringBuffer query = new StringBuffer();
// query.append("SELECT COUNT(*)");
query.append("SELECT time, kpi_CREATE_POLL_AvgRT, kpi_DELETE_POLL_AvgRT, kpi_GET_POLLS_AvgRT, kpi_GET_POLL_AvgRT, kpi_VOTE_AvgRT ");
query.append("FROM ").append(tableName).append(" ");
query.append("WHERE ");
query.append("kpi_CREATE_POLL_AvgRT > ").append(thresholds[0])
.append(" OR ").append("kpi_DELETE_POLL_AvgRT > ")
.append(thresholds[1]).append(" OR ")
.append("kpi_GET_POLLS_AvgRT > ").append(thresholds[2])
.append(" OR ").append("kpi_GET_POLL_AvgRT > ")
.append(thresholds[3]).append(" OR ")
.append("kpi_VOTE_AvgRT > ").append(thresholds[4]);
// Execute the Query
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery(query.toString());
int n = 0;
while (rs.next()) {
n = n + 1;
logger.debug("DoodleWebServiceAvgResponseTimeAssertion.check() Failing entry: ");
logger.debug("\t" + rs.getString("time"));
if (rs.getDouble("kpi_CREATE_POLL_AvgRT") > thresholds[0]) {
logger.debug(String.format("%s was (%f>%f)",
"kpi_CREATE_POLL_AvgRT",
rs.getDouble("kpi_CREATE_POLL_AvgRT"),
thresholds[0]));
}
if (rs.getDouble("kpi_DELETE_POLL_AvgRT") > thresholds[1]) {
logger.debug("DoodleWebServiceAvgResponseTimeAssertion.check()");
logger.debug(String.format("\t%s was (%f>%f)",
"kpi_DELETE_POLL_AvgRT",
rs.getDouble("kpi_DELETE_POLL_AvgRT"),
thresholds[1]));
}
if (rs.getDouble("kpi_GET_POLLS_AvgRT") > thresholds[2]) {
logger.debug("DoodleWebServiceAvgResponseTimeAssertion.check()");
logger.debug(String.format("\t%s was (%f>%f)",
"kpi_GET_POLLS_AvgRT",
rs.getDouble("kpi_GET_POLLS_AvgRT"), thresholds[2]));
}
if (rs.getDouble("kpi_GET_POLL_AvgRT") > thresholds[3]) {
logger.debug("DoodleWebServiceAvgResponseTimeAssertion.check()");
logger.debug(String.format("\t%s was (%f>%f)",
"kpi_GET_POLL_AvgRT",
rs.getDouble("kpi_GET_POLL_AvgRT"), thresholds[3]));
}
if (rs.getDouble("kpi_VOTE_AvgRT") > thresholds[4]) {
logger.debug("DoodleWebServiceAvgResponseTimeAssertion.check()");
logger.debug(String.format("\t%s was (%f>%f)",
"kpi_VOTE_AvgRT", rs.getDouble("kpi_VOTE_AvgRT"),
thresholds[4]));
}
}
logger.info(assertionName + " Elements over the threshold :" + n);
if (n == 0) {
logger.info(assertionName + " PASSED");
testReport.setTestOutcome("PASSED");
} else {
logger.info(assertionName + " FAILED");
testReport.setTestOutcome("FAILED");
testReport
.setReason(String
.format("The number of failed requests %d is greater than 0",
n));
}
} catch (ClassNotFoundException e) {
logger.warn(assertionName + " ERROR");
testReport.setTestOutcome("ERROR");
testReport.setReason(e.getMessage());
} catch (SQLException e) {
logger.warn(assertionName + " ERROR");
testReport.setTestOutcome("ERROR");
testReport.setReason(e.getMessage());
} catch (Throwable e) {
logger.warn(assertionName + " ERROR");
testReport.setTestOutcome("ERROR");
testReport.setReason(e.getMessage());
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return testReport;
}
public void check(TestResult testResult) {
try {
String serviceMonitoringDB = null;
if (testResult.getServiceDB() != null) {
serviceMonitoringDB = testResult.getServiceDB();
} else {
serviceMonitoringDB = dbService
.getServiceDBnameForTest(testResult);
}
testResult.addTestReport(check(serviceMonitoringDB));
} catch (Exception e) {
logger.error(
"Got exception. Catch it to avoid breaking the chain !", e);
TestReport testReport = new TestReport();
testReport.setTestedProperty(assertionName);
testReport.setTestOutcome("ERROR");
testReport.setReason(e.getMessage());
testResult.addTestReport(testReport);
}
}
}