/** * 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. */ package org.apache.hadoop.vaidya; import java.lang.Runnable; import org.apache.hadoop.vaidya.statistics.job.*; import org.apache.hadoop.vaidya.util.*; import org.w3c.dom.Node; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.w3c.dom.Element; /* * This is an abstract base class to be extended by each diagnostic test * class. It implements Runnable interface so that if required multiple tests * can be run in parallel. */ public abstract class DiagnosticTest implements Runnable { private static final double HIGHVAL = 0.99; private static final double MEDIUMVAL = 0.66; private static final double LOWVAL = 0.33; /* * Job statistics are passed to this class against which this diagnostic * test is evaluated. */ private JobStatistics _jobExecutionStats; private Element _testConfigElement; private double _impactLevel; private boolean _evaluated; private boolean _testPassed; /* * Checks if test is already evaluated against job execution statistics * @return - true if test is already evaluated once. */ public boolean isEvaluated() { return _evaluated; } /* * If impact level (returned by evaluate method) is less than success threshold * then test is passed (NEGATIVE) else failed (POSITIVE) which inturn indicates the * problem with job performance */ public boolean istestPassed() { return this._testPassed; } /* * Initialize the globals */ public void initGlobals (JobStatistics jobExecutionStats, Element testConfigElement) { this._jobExecutionStats = jobExecutionStats; this._testConfigElement = testConfigElement; } /* * Returns a prescription/advice (formated text) based on the evaluation of * diagnostic test condition (evaluate method). Individual test should override * and implement it. If the value returned is null then the prescription advice * is printed as provided in the test config file. */ public abstract String getPrescription(); /* * This method prints any reference details to support the test result. Individual * test needs to override and implement it and information printed is specific * to individual test. */ public abstract String getReferenceDetails (); /* * Evaluates diagnostic condition and returns impact level (value [0..1]) * Typically this method calculates the impact of a diagnosed condition on the job performance * (Note: for boolean conditions it is either 0 or 1). */ public abstract double evaluate (JobStatistics jobExecutionStats); /* * Get the Title information for this test as set in the test config file */ public String getTitle() throws Exception { return XMLUtils.getElementValue("Title", this._testConfigElement); } /* * Get the Description information as set in the test config file. */ public String getDescription() throws Exception { return XMLUtils.getElementValue("Description", this._testConfigElement); } /* * Get the Importance value as set in the test config file. */ public double getImportance() throws Exception { if (XMLUtils.getElementValue("Importance", this._testConfigElement).equalsIgnoreCase("high")) { return HIGHVAL; } else if (XMLUtils.getElementValue("Importance", this._testConfigElement).equalsIgnoreCase("medium")) { return MEDIUMVAL; } else { return LOWVAL; } } /* * Returns the impact level of this test condition. This value is calculated and * returned by evaluate method. */ public double getImpactLevel() throws Exception { if (!this.isEvaluated()) { throw new Exception("Test has not been evaluated"); } return truncate(this._impactLevel); } /* * Get the severity level as specified in the test config file. */ public double getSeverityLevel() throws Exception { return truncate ((double)(getImportance()*getImpactLevel())); } /* * Get Success Threshold as specified in the test config file. */ public double getSuccessThreshold() throws Exception { double x = Double.parseDouble(XMLUtils.getElementValue("SuccessThreshold", this._testConfigElement)); return truncate (x); } /* * Creates and returns the report element for this test based on the * test evaluation results. */ public Element getReportElement(Document doc, Node parent) throws Exception { /* * If test is not evaluated yet then throw exception */ if (!this.isEvaluated()) { throw new Exception("Test has not been evaluated"); } /* * Construct and return the report element */ // Insert Child ReportElement Node reportElement = doc.createElement("TestReportElement"); parent.appendChild(reportElement); // Insert title Node item = doc.createElement("TestTitle"); reportElement.appendChild(item); Node value = doc.createTextNode(this.getTitle()); item.appendChild(value); // Insert description item = doc.createElement("TestDescription"); reportElement.appendChild(item); value = doc.createTextNode(this.getDescription()); item.appendChild(value); // Insert Importance item = doc.createElement("TestImportance"); reportElement.appendChild(item); String imp; if (this.getImportance() == HIGHVAL) { imp = "HIGH"; } else if (this.getImportance() == MEDIUMVAL) { imp = "MEDIUM"; } else { imp = "LOW"; } value = doc.createTextNode(imp); item.appendChild(value); // Insert Importance item = doc.createElement("TestResult"); reportElement.appendChild(item); if (this._testPassed) { value = doc.createTextNode("NEGATIVE(PASSED)"); } else { value = doc.createTextNode("POSITIVE(FAILED)"); } item.appendChild(value); // TODO : if (!this._testPassed) { // Insert Severity item = doc.createElement("TestSeverity"); reportElement.appendChild(item); value = doc.createTextNode(""+this.getSeverityLevel()); item.appendChild(value); // Insert Reference Details item = doc.createElement("ReferenceDetails"); reportElement.appendChild(item); value = doc.createTextNode(""+this.getReferenceDetails()); item.appendChild(value); // Insert Prescription Advice item = doc.createElement("TestPrescription"); String val = this.getPrescription(); if (val == null) { val = XMLUtils.getElementValue("Prescription", this._testConfigElement); } reportElement.appendChild(item); value = doc.createTextNode(""+val); item.appendChild(value); // } return (Element)reportElement; } /* * (non-Javadoc) * @see java.lang.Runnable#run() */ public void run() { /* * Evaluate the test */ this._impactLevel = this.evaluate(this._jobExecutionStats); this._evaluated = true; try { if (this._impactLevel >= this.getSuccessThreshold()) { this._testPassed = false; } else { this._testPassed = true; } } catch (Exception e) { e.printStackTrace(); } } /* * Returns value of element of type long part of InputElement of diagnostic * rule */ protected long getInputElementLongValue (String elementName, long defaultValue) { Element inputElement = (Element)(this._testConfigElement.getElementsByTagName("InputElement").item(0)); Element prs = null; long value; prs = (Element)inputElement.getElementsByTagName(elementName).item(0); if (prs != null) { value = Long.parseLong(prs.getFirstChild().getNodeValue().trim()); } else { value = defaultValue; } return value; } /* * Returns value of element of type double part of InputElement of diagnostic rule */ protected double getInputElementDoubleValue(String elementName, double defaultValue) { Element inputElement = (Element)(this._testConfigElement.getElementsByTagName("InputElement").item(0)); Element prs = null; double value; prs = (Element)inputElement.getElementsByTagName(elementName).item(0); if (prs != null) { value = Double.parseDouble(prs.getFirstChild().getNodeValue().trim()); } else { value = defaultValue; } return value; } /* * Returns value of element of type String part of InputElement of diagnostic rule */ protected String getInputElementStringValue(String elementName, String defaultValue) { Element inputElement = (Element)(this._testConfigElement.getElementsByTagName("InputElement").item(0)); Element prs = null; String value; prs = (Element)inputElement.getElementsByTagName(elementName).item(0); if (prs != null) { value = prs.getFirstChild().getNodeValue().trim(); } else { value = defaultValue; } return value; } /* * truncate doubles to 2 digit. */ public static double truncate(double x) { long y=(long)(x*100); return (double)y/100; } }