All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.phoenix.pherf.util.GoogleChartGenerator Maven / Gradle / Ivy

The newest version!
/*
 * 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.phoenix.pherf.util;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.phoenix.pherf.PherfConstants;
import org.apache.phoenix.pherf.PherfConstants.CompareType;
import org.apache.phoenix.pherf.result.file.ResultFileDetails;

/**
 * Compare results based on set threshold and render results as Google Charts
 */
public class GoogleChartGenerator {

	private String[] labels;
	private CompareType compareType;
	private final Map datanodes = new TreeMap();
	private final PherfConstants constants = PherfConstants.create();
	private final String resultDir = constants.getProperty("pherf.default.results.dir");
	private final double threshold = Double.parseDouble(constants.getProperty("pherf.default.comparison.threshold"));

	public GoogleChartGenerator(String labels, CompareType compareType) {
		this.setLabels(labels);
		this.setCompareType(compareType);
	}
	
	String[] getLabels() {
		return labels;
	}

	void setLabels(String[] labels) {
		this.labels = labels;
	}

	void setLabels(String labels) {
		this.labels = labels.split(",");
	}
	
	CompareType getCompareType() {
		return this.compareType;
	}
	
    void setCompareType(CompareType compareType) {
		this.compareType = compareType;
	}
	
	public void readAndRender() {
		try {
			for (String label : labels) {
				read(label);
			}
			renderAsGoogleChartsHTML();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Reads aggregate file and convert it to DataNode 
	 * @param label
	 * @throws Exception
	 */
    private void read(String label) throws Exception {
		String resultFileName = resultDir 
				+ PherfConstants.PATH_SEPARATOR
				+ PherfConstants.RESULT_PREFIX 
				+ label
				+ ResultFileDetails.CSV_AGGREGATE_PERFORMANCE.getExtension();

    	FileReader in = new FileReader(resultFileName);
    	final CSVParser parser = new CSVParser(in, CSVFormat.DEFAULT.withHeader());

        for (CSVRecord record : parser) {
            String group = record.get("QUERY_GROUP");
            String query = record.get("QUERY");
            String explain = record.get("EXPLAIN_PLAN");
            String tenantId = record.get("TENANT_ID");
            long avgTime = Long.parseLong(record.get("AVG_TIME_MS"));
            long minTime = Long.parseLong(record.get("AVG_MIN_TIME_MS"));
            long numRuns = Long.parseLong(record.get("RUN_COUNT"));
            long rowCount = Long.parseLong(record.get("RESULT_ROW_COUNT"));
            Node node = new Node(minTime, avgTime, numRuns, explain, query, tenantId, label, rowCount);
            
            if (datanodes.containsKey(group)) {
            	datanodes.get(group).getDataSet().put(label, node);
            } else {
            	datanodes.put(group, new DataNode(label, node));
            }
        }
        parser.close();
    }

    /**
     * Verifies if the first result is within the set 
     * threshold of pherf.default.comparison.threshold
     * set in pherf.properties files
     * @param threshold
     * @return
     */
    private boolean verifyWithinThreshold(double threshold) {
    	long resetTimeToCompare = -1;
    	long timeToCompare = resetTimeToCompare;
    	for (Map.Entry dn : datanodes.entrySet()) {    	   	
        	for (Map.Entry node : dn.getValue().getDataSet().entrySet()) {
        		if (timeToCompare == -1) {
        			timeToCompare = node.getValue().getTime(getCompareType());
        			if (timeToCompare < 10) { // extremely small query time in ms therefore don't compare
        				return true;
        			}
        		}
				if ((((double) (timeToCompare - node.getValue().getTime(getCompareType()))) / (double) node
						.getValue().getTime(getCompareType())) > threshold) {
					return false;
				}
        	}
        	timeToCompare = resetTimeToCompare;
    	}
    	return true;
    }
    
    /**
     * Render results as Google charts
     * @throws FileNotFoundException
     * @throws UnsupportedEncodingException
     */
    private void renderAsGoogleChartsHTML() throws FileNotFoundException, UnsupportedEncodingException {
    	String lastKeyPrefix = "";
    	StringBuffer sb = new StringBuffer();
    	for (String label : labels) {
    		sb.append("dataTable.addColumn('number', '" + label + "');\n");
    		sb.append("dataTable.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});\n");
    	}
    	sb.append("dataTable.addRows([\n");
    	for (Map.Entry dn : datanodes.entrySet()) {
    		String currentKeyPrefix = dn.getKey().substring(0, dn.getKey().indexOf('|'));
    		if (!lastKeyPrefix.equalsIgnoreCase(currentKeyPrefix) && lastKeyPrefix != "") {
    			sb.append(getBlankRow());
    		}
    		lastKeyPrefix = currentKeyPrefix;
        	sb.append("['" + dn.getKey() + "'");
        	for (Map.Entry nodeSet : dn.getValue().getDataSet().entrySet()) {
        		sb.append (", " + nodeSet.getValue().getTime(getCompareType()));
        		sb.append (",'" + getToolTipAsHTML(dn.getValue().getDataSet()) + "'");
        	}
        	sb.append("],\n");
        }
    	String summaryFile = PherfConstants.create().getProperty("pherf.default.summary.file");
    	String title = labels[0];
    	PrintWriter writer = new PrintWriter(summaryFile, "UTF-8");
    	
    	writer.println(StaticGoogleChartsRenderingData.HEADER.replace("[title]", title));
    	writer.println(sb.substring(0, sb.length() - 2) + "\n]);");
		String thresholdString = Math.round((threshold*100)) + "%"; 
		String footer = StaticGoogleChartsRenderingData.FOOTER
				.replace("[summary]",
						((verifyWithinThreshold(threshold) == true ? "PASSED | Results are within ": 
							"FAILED | Results are outside "))
								+ "set threshold of " + thresholdString + "
" + new SimpleDateFormat("yyyy/MM/dd ha z").format(new Date())); footer = footer.replace("[title]", title); writer.println(footer); writer.close(); } /** * Render a blank Google charts row * @return */ private String getBlankRow() { String ret = "['" + new String(new char[60]).replace("\0", ".") + "'"; for (int i=0; i nodeDataSet) { String ret = ""; for (Map.Entry nodeSet : nodeDataSet.entrySet()) ret += ""; return ret + "
" + getToolText(nodeSet.getValue()) + "
"; } /** * Get tooltip for node * @param node * @return */ private String getToolText(Node node) { return node.getLabelAsHTML() + node.getAvgTimeAsHTML() + node.getMinTimeAsHTML() + node.getNumRunsAsHTML() + node.getRowCountAsHTML() + node.getExplainPlanAsHTML() + node.getQueryAsHTML(); } /** * DataNode to store results to render and compare */ class DataNode { private Map dataSet = new LinkedHashMap(); public DataNode(String label, Node node) { this.getDataSet().put(label, node); } public Map getDataSet() { return dataSet; } public void setDataSet(Map dataSet) { this.dataSet = dataSet; } } class Node { private String explainPlan; private String query; private String tenantId; private long minTime; private long avgTime; private long numRuns; private long rowCount; private String label; private DecimalFormat df = new DecimalFormat("#.#"); public Node(long minTime, long avgTime, long numRuns, String explainPlan, String query, String tenantId, String label, long rowCount) { this.setMinTime(minTime); this.setAvgTime(avgTime); this.setNumRuns(numRuns); this.setExplainPlan(explainPlan); this.setQuery(query); this.setTenantId(tenantId); this.setLabel(label); this.setRowCount(rowCount); } String getExplainPlan() { return explainPlan; } String getExplainPlanAsHTML() { return "
EXPLAIN PLAN " + explainPlan.replace("'", "") + "
"; } void setExplainPlan(String explainPlan) { this.explainPlan = explainPlan; } long getTime(CompareType compareType) { return (compareType == CompareType.AVERAGE ? getAvgTime() : getMinTime()); } long getMinTime() { if (minTime <= 2) return 2; else return minTime; } public String getMinTimeAsHTML() { return "MIN TIME " + minTime + " ms (" + df.format((double) minTime / 1000) + " sec)
"; } void setMinTime(long minTime) { this.minTime = minTime; } long getAvgTime() { return avgTime; } public String getAvgTimeAsHTML() { return "AVERAGE TIME " + avgTime + " ms (" + df.format((double) avgTime / 1000) + " sec)
"; } void setAvgTime(long avgTime) { this.avgTime = avgTime; } public long getNumRuns() { return numRuns; } public String getNumRunsAsHTML() { return "NUMBER OF RUNS " + numRuns + "
"; } public void setNumRuns(long numRuns) { this.numRuns = numRuns; } public String getQuery() { return query; } public String getQueryAsHTML() { return "
QUERY " + query.replace("'", "") + " (TENANT ID: " + getTenantId() + ")
"; } public void setQuery(String query) { this.query = query; } public String getTenantId() { return tenantId; } public void setTenantId(String tenantId) { this.tenantId = tenantId; } public String getLabel() { return label; } public String getLabelAsHTML() { return "" + label + "
"; } public void setLabel(String label) { this.label = label; } public long getRowCount() { return rowCount; } public String getRowCountAsHTML() { return "RESULT ROW COUNT " + rowCount + "
"; } public void setRowCount(long rowCount) { this.rowCount = rowCount; } } static class StaticGoogleChartsRenderingData { public static String HEADER = "[title]" + "" + "PHERFED [title]
[summary]
"; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy