autotest: delete a bunch of graph-related tko gwt code
BUG=None
TEST=./utils/compile_gwt_clients -a succeeds
Change-Id: I376620eb724d3e45922ced2da46efb31de7f8b44
Reviewed-on: https://chromium-review.googlesource.com/505249
Commit-Ready: Aviv Keshet <akeshet@chromium.org>
Tested-by: Aviv Keshet <akeshet@chromium.org>
Reviewed-by: Keith Haddow <haddowk@chromium.org>
Reviewed-by: Simran Basi <sbasi@chromium.org>
Reviewed-by: Dan Shi <dshi@google.com>
diff --git a/frontend/client/src/autotest/public/EmbeddedTkoClientTest.html b/frontend/client/src/autotest/public/EmbeddedTkoClientTest.html
index 0acea9b..1b880c1 100644
--- a/frontend/client/src/autotest/public/EmbeddedTkoClientTest.html
+++ b/frontend/client/src/autotest/public/EmbeddedTkoClientTest.html
@@ -9,35 +9,12 @@
<script type="text/javascript">
function initialize() {
Autotest.initialize("http://autotest");
-
- var plot1 = Autotest.createMetricsPlot(document.getElementById("plot1_canvas"));
- queries = {}
- queries["__main__"] = "SELECT test_name, AVG(IF(kernel LIKE '2.6.11%', iteration_value, NULL)) '2.6.11', STDDEV(IF(kernel LIKE '2.6.11%', iteration_value, NULL)) 'errors-2.6.11', AVG(IF(kernel LIKE '2.6.18%', iteration_value, NULL)) '2.6.18', STDDEV(IF(kernel LIKE '2.6.18%', iteration_value, NULL)) 'errors-2.6.18' FROM tko_perf_view_2 WHERE test_idx < 1000 AND test_name IN ('dbench', 'tbench') AND iteration_key = 'throughput' AND (kernel LIKE '2.6.11%' OR kernel LIKE '2.6.18%') GROUP BY test_name";
- queries["__2.6.11__"] = "SELECT test_idx, iteration_value FROM tko_perf_view_2 WHERE test_idx < 1000 AND test_name IN ('dbench', 'tbench') AND iteration_key = 'throughput' AND kernel LIKE '2.6.11%%' AND test_name = %s ORDER BY iteration_value";
- queries["__2.6.18__"] = "SELECT test_idx, iteration_value FROM tko_perf_view_2 WHERE test_idx < 1000 AND test_name IN ('dbench', 'tbench') AND iteration_key = 'throughput' AND kernel LIKE '2.6.18%%' AND test_name = %s ORDER BY iteration_value";
- plot1.refresh({
- plot : "Bar",
- invert : [],
- queries : queries
- });
-
- var plot2 = Autotest.createMetricsPlot(document.getElementById("plot2_canvas"));
- queries = {}
- queries["__main__"] = "SELECT kernel, AVG(iteration_value) 'throughput', STDDEV(iteration_value) 'errors-throughput' FROM tko_perf_view_2 WHERE test_idx < 1000 AND test_name = 'dbench' AND iteration_key ='throughput' GROUP BY kernel";
- queries["__throughput__"] = "SELECT test_idx, iteration_value FROM tko_perf_view_2 WHERE test_idx < 1000 AND test_name = 'dbench' AND iteration_key ='throughput' AND kernel = %s ORDER BY iteration_value";
- plot2.refresh({
- plot : "Line",
- invert : [],
- queries : queries
- });
}
</script>
</head>
<body onload="initialize()">
Top text
- <div id="plot1_canvas"></div>
Middle text
- <div id="plot2_canvas"></div>
Bottom text
</body>
diff --git a/frontend/client/src/autotest/tko/DynamicGraphingFrontend.java b/frontend/client/src/autotest/tko/DynamicGraphingFrontend.java
deleted file mode 100644
index 64536ba..0000000
--- a/frontend/client/src/autotest/tko/DynamicGraphingFrontend.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package autotest.tko;
-
-import autotest.common.JsonRpcCallback;
-import autotest.common.ui.TabView;
-import autotest.tko.PreconfigSelector.PreconfigHandler;
-import autotest.tko.TableView.TableSwitchListener;
-
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.json.client.JSONObject;
-import com.google.gwt.json.client.JSONValue;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;
-
-import java.util.Map;
-
-public abstract class DynamicGraphingFrontend extends GraphingFrontend
- implements ClickHandler, PreconfigHandler {
- protected PreconfigSelector preconfig;
- protected Button graphButton = new Button("Graph");
- protected Plot plot;
- private TabView parent;
-
- public DynamicGraphingFrontend(final TabView parent, Plot plot, String preconfigType) {
- this.parent = parent;
- this.plot = plot;
- plot.setDrilldownTrigger();
- preconfig = new PreconfigSelector(preconfigType, this);
- graphButton.addClickHandler(this);
- }
-
- @Override
- public void onClick(ClickEvent event) {
- if (event.getSource() != graphButton) {
- super.onClick(event);
- return;
- }
-
- parent.updateHistory();
- plot.setVisible(false);
- embeddingLink.setVisible(false);
- graphButton.setEnabled(false);
-
- JSONObject params = buildParams();
- if (params == null) {
- graphButton.setEnabled(true);
- return;
- }
-
- plot.refresh(params, new JsonRpcCallback() {
- @Override
- public void onSuccess(JSONValue result) {
- plot.setVisible(true);
- embeddingLink.setVisible(true);
- graphButton.setEnabled(true);
- }
-
- @Override
- public void onError(JSONObject errorObject) {
- super.onError(errorObject);
- graphButton.setEnabled(true);
- }
- });
- }
-
- protected abstract JSONObject buildParams();
-
- @Override
- public void refresh() {
- // Nothing to refresh
- }
-
- protected void commonInitialization() {
- table.setWidget(table.getRowCount(), 1, graphButton);
- table.setWidget(table.getRowCount(), 0, plot);
- table.getFlexCellFormatter().setColSpan(table.getRowCount() - 1, 0, 3);
-
- table.setWidget(table.getRowCount(), 2, embeddingLink);
- table.getFlexCellFormatter().setHorizontalAlignment(
- table.getRowCount() - 1, 2, HasHorizontalAlignment.ALIGN_RIGHT);
-
- plot.setVisible(false);
- embeddingLink.setVisible(false);
-
- initWidget(table);
- }
-
- public void handlePreconfig(Map<String, String> preconfigParameters) {
- handleHistoryArguments(preconfigParameters);
- }
-
- @Override
- protected void setListener(TableSwitchListener listener) {
- super.setListener(listener);
- plot.setListener(listener);
- }
-}
diff --git a/frontend/client/src/autotest/tko/EmbeddedTkoClient.java b/frontend/client/src/autotest/tko/EmbeddedTkoClient.java
index 0ed0a0b..08ba372 100644
--- a/frontend/client/src/autotest/tko/EmbeddedTkoClient.java
+++ b/frontend/client/src/autotest/tko/EmbeddedTkoClient.java
@@ -19,30 +19,8 @@
public void onModuleLoad() {
JsonRpcProxy.setDefaultBaseUrl(JsonRpcProxy.TKO_BASE_URL);
testDetailView = new TestDetailView();
- injectNativeMethods();
}
- /**
- * Creates a global object named Autotest with the following methods. This objects acts as the
- * entry point for externally-written native code to create embeddable widgets.
- * * initialize(autoservServerUrl) -- must call this before anything else, passing in the URL
- * to the Autotest server (i.e. "http://myhost").
- * * createMetricsPlot(parent) -- returns a metrics plot object attached to the given parent
- * element.
- */
- private native void injectNativeMethods() /*-{
- var instance = this;
- $wnd.Autotest = {
- initialize: function(autotestServerUrl) {
- instance.@autotest.tko.EmbeddedTkoClient::initialize(Ljava/lang/String;)(autotestServerUrl);
- },
-
- createMetricsPlot: function(parent) {
- return instance.@autotest.tko.EmbeddedTkoClient::createMetricsPlot(Lcom/google/gwt/dom/client/Element;)(parent);
- }
- }
- }-*/;
-
@SuppressWarnings("unused") // called from native
private void initialize(String autotestServerUrl) {
this.autotestServerUrl = autotestServerUrl;
@@ -51,32 +29,6 @@
JsonRpcProxy.setProxy(JsonRpcProxy.TKO_BASE_URL, proxy);
}
- @SuppressWarnings("unused") // called from native
- private JavaScriptObject createMetricsPlot(Element parent) {
- UncaughtExceptionHandler handler = GWT.getUncaughtExceptionHandler();
- if (handler == null) {
- return doCreateMetricsPlot(parent);
- }
-
- try {
- return doCreateMetricsPlot(parent);
- } catch (Throwable throwable) {
- handler.onUncaughtException(throwable);
- return null;
- }
- }
-
- private JavaScriptObject doCreateMetricsPlot(Element parent) {
- if (parent == null) {
- throw new IllegalArgumentException("parent element cannot be null");
- }
- Plot plot = new MetricsPlot();
- plot.setDrilldownTrigger();
- plot.setListener(this);
- parent.appendChild(plot.getElement());
- return plot.getNativeProxy();
- }
-
public HistoryToken getSelectTestHistoryToken(int testId) {
testDetailView.updateObjectId(Integer.toString(testId));
return testDetailView.getHistoryArguments();
diff --git a/frontend/client/src/autotest/tko/ExistingGraphsFrontend.java b/frontend/client/src/autotest/tko/ExistingGraphsFrontend.java
deleted file mode 100644
index 57faee6..0000000
--- a/frontend/client/src/autotest/tko/ExistingGraphsFrontend.java
+++ /dev/null
@@ -1,300 +0,0 @@
-package autotest.tko;
-
-import autotest.common.JsonRpcCallback;
-import autotest.common.SimpleCallback;
-import autotest.common.StaticDataRepository;
-import autotest.common.Utils;
-import autotest.common.ui.TabView;
-
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.logical.shared.SelectionEvent;
-import com.google.gwt.event.logical.shared.SelectionHandler;
-import com.google.gwt.json.client.JSONArray;
-import com.google.gwt.json.client.JSONObject;
-import com.google.gwt.json.client.JSONString;
-import com.google.gwt.json.client.JSONValue;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
-import com.google.gwt.user.client.ui.Panel;
-import com.google.gwt.user.client.ui.SuggestBox;
-import com.google.gwt.user.client.ui.SuggestOracle;
-import com.google.gwt.user.client.ui.TextBox;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-public class ExistingGraphsFrontend extends GraphingFrontend {
-
- private CheckBox normalize = new CheckBox("Normalize Performance (allows multiple benchmarks" +
- " on one graph)");
- private MultiWordSuggestOracle oracle = new MultiWordSuggestOracle();
- private TextBox hostname = new TextBox();
- private SuggestBox hostnameSuggest = new SuggestBox(oracle, hostname);
- private Panel benchmarkWrapper = new HorizontalPanel();
- private TextBox kernel = new TextBox();
- private JSONObject hostsAndTests = null;
- private Button graphButton = new Button("Graph");
-
- private ListBox singleBenchmark = new ListBox(false);
- private ListBox multiBenchmark = new ListBox(true);
-
- public ExistingGraphsFrontend(final TabView parent) {
- normalize.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent event) {
- normalizeClicked();
- }
- });
-
- hostnameSuggest.getTextBox().addBlurHandler(new BlurHandler() {
- public void onBlur(BlurEvent event) {
- refreshTests();
- }
- });
- hostnameSuggest.addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>() {
- public void onSelection(SelectionEvent<SuggestOracle.Suggestion> event) {
- refreshTests();
- }
- });
-
- addBenchmarkItem("(Please select a hostname first)");
-
- graphButton.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent event) {
- parent.updateHistory();
- showGraph();
- }
- });
-
- kernel.setText("all");
-
- table.setWidget(0, 0, normalize);
- table.getFlexCellFormatter().setColSpan(0, 0, 2);
- benchmarkWrapper.add(singleBenchmark);
- benchmarkWrapper.add(multiBenchmark);
- multiBenchmark.setVisible(false);
-
- addControl("Hostname:", hostnameSuggest);
- addControl("Benchmark:", benchmarkWrapper);
- addControl("Kernel:", kernel);
- table.setWidget(table.getRowCount(), 1, graphButton);
-
- table.getColumnFormatter().setWidth(0, "1px");
-
- initWidget(table);
- }
-
- private void addBenchmarkItem(String item) {
- singleBenchmark.addItem(item);
- multiBenchmark.addItem(item);
- }
-
- private void getHostsAndTests(final SimpleCallback onFinished) {
- setEnabled(false);
- rpcProxy.rpcCall("get_hosts_and_tests", new JSONObject(), new JsonRpcCallback() {
- @Override
- public void onSuccess(JSONValue result) {
- hostsAndTests = result.isObject();
- onFinished.doCallback(null);
- setEnabled(true);
- }
- });
- }
-
- @Override
- public void refresh() {
- getHostsAndTests(new SimpleCallback() {
- public void doCallback(Object source) {
- oracle.clear();
- for (String host : hostsAndTests.keySet()) {
- oracle.add(host);
- }
- }
- });
- }
-
- @Override
- public void addToHistory(Map<String, String> args) {
- args.put("normalize", String.valueOf(normalize.getValue()));
- args.put("hostname", hostname.getText());
-
- // Add the selected benchmarks
- StringBuilder benchmarks = new StringBuilder();
- ListBox benchmark = getVisibleBenchmark();
- for (int i = 0; i < benchmark.getItemCount(); i++) {
- if (benchmark.isItemSelected(i)) {
- benchmarks.append(benchmark.getValue(i));
- benchmarks.append(",");
- }
- }
-
- args.put("benchmark", benchmarks.toString());
- args.put("kernel", kernel.getText());
- }
-
- @Override
- public void handleHistoryArguments(final Map<String, String> args) {
- hostname.setText(args.get("hostname"));
- normalize.setValue(Boolean.parseBoolean(args.get("normalize")));
- normalizeClicked();
- kernel.setText(args.get("kernel"));
-
- getHostsAndTests(new SimpleCallback() {
- public void doCallback(Object source) {
- refreshTests();
-
- ListBox benchmark = getVisibleBenchmark();
- Set<String> benchmarks =
- new HashSet<String>(Arrays.asList(args.get("benchmark").split(",")));
- for (int i = 0; i < benchmark.getItemCount(); i++) {
- benchmark.setItemSelected(i, benchmarks.contains(benchmark.getValue(i)));
- }
- }
- });
- }
-
- private ListBox getVisibleBenchmark() {
- boolean multiVisible = normalize.getValue();
- if (multiVisible) {
- assert multiBenchmark.isVisible();
- return multiBenchmark;
- } else {
- assert singleBenchmark.isVisible();
- return singleBenchmark;
- }
- }
-
- @Override
- protected void addAdditionalEmbeddingParams(JSONObject params) {
- // No embedding
- }
-
- // Change the state of the page based on the status of the "normalize" checkbox
- private void normalizeClicked() {
- boolean multiVisible = normalize.getValue();
- ListBox dest;
- ListBox src;
-
- if (multiVisible) {
- dest = multiBenchmark;
- src = singleBenchmark;
- } else {
- dest = singleBenchmark;
- src = multiBenchmark;
- }
-
- dest.setVisible(true);
- src.setVisible(false);
-
- dest.setSelectedIndex(src.getSelectedIndex());
- src.setSelectedIndex(-1);
- }
-
- private void setEnabled(boolean enabled) {
- normalize.setEnabled(enabled);
- hostname.setEnabled(enabled);
- singleBenchmark.setEnabled(enabled);
- multiBenchmark.setEnabled(enabled);
- kernel.setEnabled(enabled);
- graphButton.setEnabled(enabled);
- }
-
- private void refreshTests() {
- JSONValue value = hostsAndTests.get(hostnameSuggest.getText());
- if (value == null) {
- return;
- }
-
- HashSet<String> selectedTests = new HashSet<String>();
- ListBox benchmark = getVisibleBenchmark();
- for (int i = 0; i < benchmark.getItemCount(); i++) {
- if (benchmark.isItemSelected(i)) {
- selectedTests.add(benchmark.getValue(i));
- }
- }
-
- JSONArray tests = value.isObject().get("tests").isArray();
- singleBenchmark.clear();
- multiBenchmark.clear();
- for (int i = 0; i < tests.size(); i++) {
- String test = Utils.jsonToString(tests.get(i));
- addBenchmarkItem(test);
- if (selectedTests.contains(test)) {
- benchmark.setItemSelected(i, true);
- }
- }
- }
-
- private void showGraph() {
- String hostnameStr = hostnameSuggest.getText();
-
- JSONValue value = hostsAndTests.get(hostnameStr);
- if (value == null) {
- return;
- }
-
- String url;
- HashMap<String, String> args = new HashMap<String, String>();
- args.put("kernel", kernel.getText());
-
- if (normalize.getValue()) {
- url = "/tko/machine_aggr.cgi?";
- final JSONArray tests = new JSONArray();
- for (int i = 0; i < multiBenchmark.getItemCount(); i++) {
- if (multiBenchmark.isItemSelected(i)) {
- tests.set(tests.size(), new JSONString(multiBenchmark.getValue(i)));
- }
- }
-
- args.put("machine", hostnameStr);
-
- StringBuilder arg = new StringBuilder();
- for (int i = 0; i < tests.size(); i++) {
- String test = Utils.jsonToString(tests.get(i));
- String key = getKey(test);
- if (i != 0) {
- arg.append(",");
- }
- arg.append(test);
- arg.append(":");
- arg.append(key);
- }
- args.put("benchmark_key", arg.toString());
- } else {
- int benchmarkIndex = singleBenchmark.getSelectedIndex();
- if (benchmarkIndex == -1) {
- return;
- }
-
- url = "/tko/machine_test_attribute_graph.cgi?";
-
- JSONObject hostObject = value.isObject();
- String machine = Utils.jsonToString(hostObject.get("id"));
- String benchmarkStr = singleBenchmark.getValue(benchmarkIndex);
-
- args.put("machine", machine);
- args.put("benchmark", benchmarkStr);
- args.put("key", getKey(benchmarkStr));
- }
- Utils.openUrlInNewWindow(url + Utils.encodeUrlArguments(args));
- }
-
- private String getKey(String benchmark) {
- JSONObject benchmarkKey =
- StaticDataRepository.getRepository().getData("benchmark_key").isObject();
- return Utils.jsonToString(benchmarkKey.get(benchmark.replaceAll("\\..*", "")));
- }
-
- @Override
- public String getFrontendId() {
- return "existing_graphs";
- }
-}
diff --git a/frontend/client/src/autotest/tko/GraphingFrontend.java b/frontend/client/src/autotest/tko/GraphingFrontend.java
deleted file mode 100644
index 7b4dcad..0000000
--- a/frontend/client/src/autotest/tko/GraphingFrontend.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package autotest.tko;
-
-import autotest.common.CustomHistory;
-import autotest.common.JsonRpcCallback;
-import autotest.common.JsonRpcProxy;
-import autotest.common.Utils;
-import autotest.common.CustomHistory.CustomHistoryListener;
-import autotest.common.CustomHistory.HistoryToken;
-import autotest.common.ui.NotifyManager;
-import autotest.common.ui.SimpleDialog;
-import autotest.tko.TableView.TableSwitchListener;
-
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.json.client.JSONNumber;
-import com.google.gwt.json.client.JSONObject;
-import com.google.gwt.json.client.JSONString;
-import com.google.gwt.json.client.JSONValue;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.HasVerticalAlignment;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.Widget;
-
-import java.util.Map;
-
-public abstract class GraphingFrontend extends Composite
- implements CustomHistoryListener, ClickHandler {
- public static final String HISTORY_TOKEN = "embedded_query";
-
- protected FlexTable table = new FlexTable();
- protected JsonRpcProxy rpcProxy = JsonRpcProxy.getProxy();
- protected Anchor embeddingLink = new Anchor("[Link to this graph]");
- protected TableSwitchListener listener;
-
- public abstract void refresh();
- public abstract void addToHistory(Map<String, String> args);
- public abstract void handleHistoryArguments(Map<String, String> args);
-
- /**
- * This function allows subclasses to add parameters to the call to get_embedding_id() RPC,
- * called when a user requests an embeddable link to a graph.
- */
- protected abstract void addAdditionalEmbeddingParams(JSONObject params);
-
- /**
- * @return a short text ID for the frontend
- */
- public abstract String getFrontendId();
-
- protected GraphingFrontend() {
- CustomHistory.addHistoryListener(this);
- embeddingLink.addClickHandler(this);
- }
-
- public void onClick(ClickEvent event) {
- assert event.getSource() == embeddingLink;
- JSONObject params = new JSONObject();
- params.put("url_token", new JSONString(CustomHistory.getLastHistoryToken().toString()));
- addAdditionalEmbeddingParams(params);
-
- rpcProxy.rpcCall("get_embedding_id", params, new JsonRpcCallback() {
- @Override
- public void onSuccess(JSONValue result) {
- String id = Utils.jsonToString(result);
- showEmbeddedGraphHtml(id);
- }
- });
- }
-
- private void showEmbeddedGraphHtml(String embeddedGraphId) {
- StringBuilder link = new StringBuilder();
- link.append("<a href=\"http://");
- link.append(Window.Location.getHost());
- link.append(Window.Location.getPath());
- link.append("#");
- link.append(HISTORY_TOKEN);
- link.append("=");
- link.append(embeddedGraphId);
-
- link.append("\"><img border=\"0\" src=\"http://");
- link.append(Window.Location.getHost());
-
- link.append(JsonRpcProxy.TKO_BASE_URL);
- link.append("plot/?id=");
- link.append(embeddedGraphId);
-
- link.append("&max_age=10");
-
- link.append("\"></a>");
-
- TextBox linkBox = new TextBox();
- linkBox.setText(link.toString());
- linkBox.setWidth("100%");
- linkBox.setSelectionRange(0, link.length());
-
- new SimpleDialog("Paste HTML to embed in website:", linkBox).center();
- }
-
- protected void setListener(TableSwitchListener listener) {
- this.listener = listener;
- }
-
- protected void addControl(String text, Widget control) {
- int row = TkoUtils.addControlRow(table, text, control);
- table.getFlexCellFormatter().setColSpan(row, 1, 2);
- table.getFlexCellFormatter().setWidth(row, 1, "100%");
- table.getFlexCellFormatter().setVerticalAlignment(row, 0, HasVerticalAlignment.ALIGN_TOP);
- }
-
- // TODO(showard): merge this with the code from SavedQueriesControl
- public void onHistoryChanged(Map<String, String> arguments) {
- final String idString = arguments.get(HISTORY_TOKEN);
- if (idString == null) {
- return;
- }
-
- JSONObject args = new JSONObject();
- args.put("id", new JSONNumber(Integer.parseInt(idString)));
- rpcProxy.rpcCall("get_embedded_query_url_token", args, new JsonRpcCallback() {
- @Override
- public void onSuccess(JSONValue result) {
- String tokenString = Utils.jsonToString(result);
- HistoryToken token;
- try {
- token = HistoryToken.fromString(tokenString);
- } catch (IllegalArgumentException exc) {
- NotifyManager.getInstance().showError("Invalid embedded query token " +
- tokenString);
- return;
- }
-
- // since this is happening asynchronously, the history may have changed, so ensure
- // it's set back to what it should be.
- HistoryToken shortToken = new HistoryToken();
- shortToken.put(HISTORY_TOKEN, idString);
- CustomHistory.newItem(shortToken);
-
- CustomHistory.simulateHistoryToken(token);
- }
- });
- }
-}
diff --git a/frontend/client/src/autotest/tko/GraphingView.java b/frontend/client/src/autotest/tko/GraphingView.java
deleted file mode 100644
index 3b0dade..0000000
--- a/frontend/client/src/autotest/tko/GraphingView.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package autotest.tko;
-
-import autotest.common.CustomHistory.HistoryToken;
-import autotest.common.ui.ExtendedListBox;
-import autotest.common.ui.TabView;
-import autotest.tko.TableView.TableSwitchListener;
-
-import com.google.gwt.event.dom.client.ChangeEvent;
-import com.google.gwt.event.dom.client.ChangeHandler;
-import com.google.gwt.user.client.ui.DeckPanel;
-
-import java.util.Map;
-
-public class GraphingView extends TabView {
-
- private ExtendedListBox frontendSelection = new ExtendedListBox();
- private MetricsPlotFrontend metricsPlotFrontend = new MetricsPlotFrontend(this);
- private MachineQualHistogramFrontend machineQualHistogramFrontend =
- new MachineQualHistogramFrontend(this);
- private ExistingGraphsFrontend existingGraphsFrontend = new ExistingGraphsFrontend(this);
- private DeckPanel controlPanel = new DeckPanel();
- private GraphingFrontend frontends[] = {
- metricsPlotFrontend,
- machineQualHistogramFrontend,
- existingGraphsFrontend,
- };
-
- public GraphingView(TableSwitchListener listener) {
- metricsPlotFrontend.setListener(listener);
- machineQualHistogramFrontend.setListener(listener);
- }
-
- @Override
- public void initialize() {
- super.initialize();
- frontendSelection.addItem("Metrics Plot", metricsPlotFrontend.getFrontendId());
- frontendSelection.addItem("Machine Qualification Histogram",
- machineQualHistogramFrontend.getFrontendId());
- frontendSelection.addItem("Existing Graphs", existingGraphsFrontend.getFrontendId());
-
- frontendSelection.addChangeHandler(new ChangeHandler() {
- public void onChange(ChangeEvent event) {
- showSelectedView();
- updateHistory();
- }
- });
-
- controlPanel.add(metricsPlotFrontend);
- controlPanel.add(machineQualHistogramFrontend);
- controlPanel.add(existingGraphsFrontend);
- controlPanel.showWidget(0);
-
- addWidget(frontendSelection, "graphing_type");
- addWidget(controlPanel, "graphing_frontend");
- }
-
- @Override
- public String getElementId() {
- return "graphing_view";
- }
-
- private GraphingFrontend getSelectedFrontend() {
- return frontends[frontendSelection.getSelectedIndex()];
- }
-
- @Override
- public void refresh() {
- super.refresh();
- getSelectedFrontend().refresh();
- }
-
- @Override
- public void display() {
- super.display();
- CommonPanel.getPanel().setConditionVisible(false);
- }
-
- @Override
- public HistoryToken getHistoryArguments() {
- HistoryToken args = super.getHistoryArguments();
- args.put("view", getSelectedFrontend().getFrontendId());
- getSelectedFrontend().addToHistory(args);
- return args;
- }
-
- @Override
- public void handleHistoryArguments(Map<String, String> arguments) {
- super.handleHistoryArguments(arguments);
- String frontendId = arguments.get("view");
- frontendSelection.selectByValue(frontendId);
- for (GraphingFrontend frontend : frontends) {
- if (frontend.getFrontendId().equals(frontendId)) {
- frontend.handleHistoryArguments(arguments);
- break;
- }
- }
- showSelectedView();
- }
-
- private void showSelectedView() {
- int index = frontendSelection.getSelectedIndex();
- controlPanel.showWidget(index);
- frontends[index].refresh();
- }
-}
diff --git a/frontend/client/src/autotest/tko/MachineQualHistogram.java b/frontend/client/src/autotest/tko/MachineQualHistogram.java
deleted file mode 100644
index 757553e..0000000
--- a/frontend/client/src/autotest/tko/MachineQualHistogram.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package autotest.tko;
-
-import autotest.common.Utils;
-import autotest.common.ui.SimpleDialog;
-import autotest.tko.TableView.TableViewConfig;
-
-import com.google.gwt.json.client.JSONObject;
-import com.google.gwt.user.client.ui.HTML;
-
-class MachineQualHistogram extends Plot {
- public MachineQualHistogram() {
- super("create_qual_histogram");
- }
-
- /**
- * drilldownParams contains:
- * * type: "normal", "not_applicable", or "empty"
- * for type "normal":
- * * filterString: SQL filter for selected bucket
- * for type "not_applicable":
- * * hosts: HTML list of hosts in this bucket
- */
- @Override
- protected void showDrilldownImpl(JSONObject drilldownParams) {
- String type = Utils.jsonToString(drilldownParams.get("type"));
- if (type.equals("normal")) {
- String filterString = Utils.jsonToString(drilldownParams.get("filterString"));
- showNormalDrilldown(filterString);
- } else if (type.equals("not_applicable")) {
- String hosts = Utils.jsonToString(drilldownParams.get("hosts"));
- showNADialog(hosts);
- } else if (type.equals("empty")) {
- showEmptyDialog();
- }
- }
-
- private void showNormalDrilldown(final String filterString) {
- CommonPanel.getPanel().setSqlCondition(filterString);
- listener.onSwitchToTable(TableViewConfig.PASS_RATE);
- }
-
- private void showNADialog(String hosts) {
- new SimpleDialog("Did not run any of the selected tests:", new HTML(hosts)).center();
- }
-
- private void showEmptyDialog() {
- new SimpleDialog("No hosts in this pass rate range", new HTML()).center();
- }
-}
diff --git a/frontend/client/src/autotest/tko/MachineQualHistogramFrontend.java b/frontend/client/src/autotest/tko/MachineQualHistogramFrontend.java
deleted file mode 100644
index 5d226cd..0000000
--- a/frontend/client/src/autotest/tko/MachineQualHistogramFrontend.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package autotest.tko;
-
-import autotest.common.ui.NotifyManager;
-import autotest.common.ui.TabView;
-
-import com.google.gwt.json.client.JSONNumber;
-import com.google.gwt.json.client.JSONObject;
-import com.google.gwt.json.client.JSONString;
-import com.google.gwt.user.client.ui.TextBox;
-
-import java.util.Map;
-
-public class MachineQualHistogramFrontend extends DynamicGraphingFrontend {
- private static final String DEFAULT_INTERVAL = "10";
-
- private FilterSelector globalFilters =
- new FilterSelector(DBColumnSelector.TEST_VIEW);
- private FilterSelector testFilters =
- new FilterSelector(DBColumnSelector.TEST_VIEW);
- private TextBox interval = new TextBox();
-
- public MachineQualHistogramFrontend(final TabView parent) {
- super(parent, new MachineQualHistogram(), "qual");
-
- interval.setText(DEFAULT_INTERVAL);
-
- addControl("Preconfigured:", preconfig);
- addControl("Global filters:", globalFilters);
- addControl("Test set filters:", testFilters);
- addControl("Interval:", interval);
-
- commonInitialization();
- }
-
- @Override
- protected void addAdditionalEmbeddingParams(JSONObject params) {
- params.put("graph_type", new JSONString("qual"));
- params.put("params", buildParams());
- }
-
- private JSONString buildQuery() {
- String gFilterString = globalFilters.getFilterString();
- String tFilterString = testFilters.getFilterString();
- boolean hasGFilter = !gFilterString.equals("");
- boolean hasTFilter = !tFilterString.equals("");
-
- StringBuilder sql = new StringBuilder();
-
- sql.append("SELECT hostname, COUNT(DISTINCT ");
- if (hasTFilter) {
- sql.append("IF(");
- sql.append(tFilterString);
- sql.append(", test_idx, NULL)");
- } else {
- sql.append("test_idx");
- }
- sql.append(") 'total', COUNT(DISTINCT IF(");
- if (hasTFilter) {
- sql.append(TkoUtils.wrapWithParens(tFilterString));
- sql.append(" AND ");
- }
-
- sql.append("status = 'GOOD', test_idx, NULL)) 'good' FROM tko_test_view_outer_joins");
- if (hasGFilter) {
- sql.append(" WHERE ");
- sql.append(gFilterString);
- }
- sql.append(" GROUP BY hostname");
- return new JSONString(sql.toString());
- }
-
- private JSONString buildFilterString() {
- StringBuilder filterString = new StringBuilder();
- String gFilterString = globalFilters.getFilterString();
- String tFilterString = testFilters.getFilterString();
- boolean hasGFilter = !gFilterString.equals("");
- boolean hasTFilter = !tFilterString.equals("");
- if (hasGFilter) {
- filterString.append(TkoUtils.wrapWithParens(gFilterString));
- if (hasTFilter) {
- filterString.append(" AND ");
- }
- }
- if (hasTFilter) {
- filterString.append(TkoUtils.wrapWithParens(tFilterString));
- }
- return new JSONString(filterString.toString());
- }
-
- @Override
- protected JSONObject buildParams() {
- if (interval.getText().equals("")) {
- NotifyManager.getInstance().showError("You must enter an interval");
- return null;
- }
-
- int intervalValue;
- try {
- intervalValue = Integer.parseInt(interval.getText());
- } catch (NumberFormatException e) {
- NotifyManager.getInstance().showError("Interval must be an integer");
- return null;
- }
-
- JSONObject params = new JSONObject();
- params.put("query", buildQuery());
- params.put("filter_string", buildFilterString());
- params.put("interval", new JSONNumber(intervalValue));
-
- return params;
- }
-
- @Override
- public String getFrontendId() {
- return "machine_qual_histogram";
- }
-
- @Override
- public void addToHistory(Map<String, String> args) {
- globalFilters.addToHistory(args, "globalFilter");
- testFilters.addToHistory(args, "testFilter");
- args.put("interval", interval.getText());
- }
-
- @Override
- public void handleHistoryArguments(Map<String, String> args) {
- setVisible(false);
- globalFilters.reset();
- testFilters.reset();
- globalFilters.handleHistoryArguments(args, "globalFilter");
- testFilters.handleHistoryArguments(args, "testFilter");
- interval.setText(args.get("interval"));
- setVisible(true);
- }
-}
diff --git a/frontend/client/src/autotest/tko/MetricsPlot.java b/frontend/client/src/autotest/tko/MetricsPlot.java
deleted file mode 100644
index 567dc68..0000000
--- a/frontend/client/src/autotest/tko/MetricsPlot.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package autotest.tko;
-
-import autotest.common.JsonRpcCallback;
-import autotest.common.Utils;
-import autotest.common.ui.SimpleDialog;
-
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.json.client.JSONArray;
-import com.google.gwt.json.client.JSONObject;
-import com.google.gwt.json.client.JSONString;
-import com.google.gwt.json.client.JSONValue;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.FlexTable;
-
-class MetricsPlot extends Plot {
- public MetricsPlot() {
- super("create_metrics_plot");
- }
-
- /**
- * drilldownParams contains:
- * * query - SQL query for the selected series
- * * series - name of the selected series
- * * param - parameter to fill in query for the selected data point
- */
- @Override
- protected void showDrilldownImpl(JSONObject drilldownParams) {
- String query = Utils.jsonToString(drilldownParams.get("query"));
- final String series = Utils.jsonToString(drilldownParams.get("series"));
- final String param = Utils.jsonToString(drilldownParams.get("param"));
-
- JSONObject params = new JSONObject();
- params.put("query", new JSONString(query));
- params.put("param", new JSONString(param));
- rpcProxy.rpcCall("execute_query_with_param", params, new JsonRpcCallback() {
- @Override
- public void onSuccess(JSONValue result) {
- JSONArray data = result.isArray();
-
- String title = series + " for " + param;
- FlexTable contents = new FlexTable();
- final SimpleDialog drill = new SimpleDialog(title, contents);
-
- for (int i = 0; i < data.size(); i++) {
- final JSONArray row = data.get(i).isArray();
- final int testId = (int) row.get(0).isNumber().doubleValue();
- String yValue = Utils.jsonToString(row.get(1));
-
- Anchor link = new Anchor(yValue);
- link.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent event) {
- drill.hide();
- listener.onSelectTest(testId);
- }
- });
- contents.setWidget(i, 0, link);
- }
-
- drill.center();
- }
- });
- }
-}
diff --git a/frontend/client/src/autotest/tko/MetricsPlotFrontend.java b/frontend/client/src/autotest/tko/MetricsPlotFrontend.java
deleted file mode 100644
index cd4cd51..0000000
--- a/frontend/client/src/autotest/tko/MetricsPlotFrontend.java
+++ /dev/null
@@ -1,341 +0,0 @@
-package autotest.tko;
-
-import autotest.common.Utils;
-import autotest.common.ui.ExtendedListBox;
-import autotest.common.ui.NotifyManager;
-import autotest.common.ui.TabView;
-import autotest.tko.SeriesSelector.Series;
-
-import com.google.gwt.event.dom.client.ChangeEvent;
-import com.google.gwt.event.dom.client.ChangeHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.json.client.JSONObject;
-import com.google.gwt.json.client.JSONString;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Panel;
-import com.google.gwt.user.client.ui.RadioButton;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.VerticalPanel;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class MetricsPlotFrontend extends DynamicGraphingFrontend implements ClickHandler {
-
- public static final String NORMALIZE_SINGLE = "single";
- public static final String NORMALIZE_FIRST = "first";
- public static final String NORMALIZE_SERIES_PREFIX = "series__";
- public static final String NORMALIZE_X_PREFIX = "x__";
-
- protected FilterSelector globalFilter = new FilterSelector(DBColumnSelector.PERF_VIEW);
- private ExtendedListBox plotSelector = new ExtendedListBox();
- private ExtendedListBox xAxis = new DBColumnSelector(DBColumnSelector.PERF_VIEW, true);
- private RadioButton noNormalizeMultiple =
- new RadioButton("normalize", "No normalization (multiple subplots)");
- private RadioButton noNormalizeSingle =
- new RadioButton("normalize", "No normalization (single plot)");
- private RadioButton normalizeFirst = new RadioButton("normalize", "First data point");
- private RadioButton normalizeSeries = new RadioButton("normalize", "Specified series:");
- private ExtendedListBox normalizeSeriesSelect = new ExtendedListBox();
- private RadioButton normalizeX = new RadioButton("normalize", "Specified X-axis value:");
- private TextBox normalizeXSelect = new TextBox();
- private SeriesSelector seriesSelector = new SeriesSelector(new ChangeHandler() {
- public void onChange(ChangeEvent event) {
- refreshSeries();
- }
- });
-
- public MetricsPlotFrontend(final TabView parent) {
- super(parent, new MetricsPlot(), "metrics");
-
- noNormalizeSingle.setValue(true);
-
- noNormalizeMultiple.addClickHandler(this);
- noNormalizeSingle.addClickHandler(this);
- normalizeFirst.addClickHandler(this);
- normalizeSeries.addClickHandler(this);
- normalizeX.addClickHandler(this);
-
- normalizeSeriesSelect.setEnabled(false);
- normalizeXSelect.setEnabled(false);
-
- plotSelector.addItem("Line");
- plotSelector.addItem("Bar");
- plotSelector.addChangeHandler(new ChangeHandler() {
- public void onChange(ChangeEvent event) {
- checkNormalizeInput();
- }
- });
-
- Panel normalizePanel = new VerticalPanel();
- normalizePanel.add(noNormalizeMultiple);
- normalizePanel.add(noNormalizeSingle);
- Panel seriesPanel = new HorizontalPanel();
- seriesPanel.add(normalizeSeries);
- seriesPanel.add(normalizeSeriesSelect);
- normalizePanel.add(seriesPanel);
- normalizePanel.add(normalizeFirst);
- Panel baselinePanel = new HorizontalPanel();
- baselinePanel.add(normalizeX);
- baselinePanel.add(normalizeXSelect);
- normalizePanel.add(baselinePanel);
-
- addControl("Preconfigured:", preconfig);
- addControl("Plot:", plotSelector);
- addControl("X-axis values:", xAxis);
- addControl("Global filters:", globalFilter);
- addControl("Series:", seriesSelector);
- addControl("Normalize to:", normalizePanel);
-
- commonInitialization();
- }
-
- @Override
- public void onClick(ClickEvent event) {
- if (event.getSource() != noNormalizeSingle && event.getSource() != noNormalizeMultiple
- && event.getSource() != normalizeSeries && event.getSource() != normalizeX) {
- super.onClick(event);
- return;
- }
-
- normalizeSeriesSelect.setEnabled(false);
- normalizeXSelect.setEnabled(false);
- if (event.getSource() == normalizeSeries) {
- normalizeSeriesSelect.setEnabled(true);
- refreshSeries();
- } else if (event.getSource() == normalizeX) {
- normalizeXSelect.setEnabled(true);
- }
-
- checkInvertible();
- }
-
- private void addNormalizeParameter(String plotType, Map<String, String> parameters) {
- String normalizationType = null;
- if (plotType.equals("Line") && noNormalizeSingle.getValue()) {
- normalizationType = NORMALIZE_SINGLE;
- } else if (normalizeFirst.getValue()) {
- normalizationType = NORMALIZE_FIRST;
- } else if (normalizeSeries.getValue()) {
- String series = normalizeSeriesSelect.getSelectedValue();
- normalizationType = NORMALIZE_SERIES_PREFIX + series;
- } else if (normalizeX.getValue()) {
- String baseline = normalizeXSelect.getText();
- normalizationType = NORMALIZE_X_PREFIX + baseline;
- }
-
- if (normalizationType != null) {
- parameters.put("normalize", normalizationType);
- }
- }
-
- @Override
- public void addToHistory(Map<String, String> args) {
- String plot = plotSelector.getValue(plotSelector.getSelectedIndex());
- args.put("plot", plot);
- args.put("xAxis", xAxis.getSelectedValue());
- globalFilter.addToHistory(args, "globalFilter");
- seriesSelector.addToHistory(args);
- addNormalizeParameter(plot, args);
- }
-
- @Override
- public void handleHistoryArguments(Map<String, String> args) {
- setVisible(false);
- plot.setVisible(false);
- embeddingLink.setVisible(false);
- globalFilter.reset();
- seriesSelector.reset();
- for (int i = 0; i < plotSelector.getItemCount(); i++) {
- if (plotSelector.getValue(i).equals(args.get("plot"))) {
- plotSelector.setSelectedIndex(i);
- break;
- }
- }
-
- xAxis.selectByValue(args.get("xAxis"));
- globalFilter.handleHistoryArguments(args, "globalFilter");
- seriesSelector.handleHistoryArguments(args);
-
- refreshSeries();
- noNormalizeMultiple.setValue(true);
- normalizeSeriesSelect.setEnabled(false);
- normalizeXSelect.setEnabled(false);
- String normalizeString = args.get("normalize");
- if (normalizeString != null) {
- if (normalizeString.equals(NORMALIZE_SINGLE)) {
- noNormalizeSingle.setValue(true);
- } else if (normalizeString.equals(NORMALIZE_FIRST)) {
- normalizeFirst.setValue(true);
- } else if (normalizeString.startsWith(NORMALIZE_SERIES_PREFIX)) {
- normalizeSeries.setValue(true);
- String series = normalizeString.substring(NORMALIZE_SERIES_PREFIX.length());
- for (int i = 0; i < normalizeSeriesSelect.getItemCount(); i++) {
- if (normalizeSeriesSelect.getValue(i).equals(series)) {
- normalizeSeriesSelect.setSelectedIndex(i);
- break;
- }
- }
- normalizeSeriesSelect.setEnabled(true);
- } else if (normalizeString.startsWith(NORMALIZE_X_PREFIX)) {
- normalizeX.setValue(true);
- normalizeXSelect.setText(normalizeString.substring(NORMALIZE_X_PREFIX.length()));
- normalizeXSelect.setEnabled(true);
- }
- }
- checkNormalizeInput();
- checkInvertible();
-
- setVisible(true);
- }
-
- @Override
- protected void addAdditionalEmbeddingParams(JSONObject params) {
- params.put("graph_type", new JSONString("metrics"));
- params.put("params", buildParams());
- }
-
- private void refreshSeries() {
- String selectedValue = normalizeSeriesSelect.getSelectedValue();
- normalizeSeriesSelect.clear();
- for (Series selector : seriesSelector.getAllSeries()) {
- normalizeSeriesSelect.addItem(selector.getName());
- if (selector.getName().equals(selectedValue)) {
- normalizeSeriesSelect.setSelectedIndex(normalizeSeriesSelect.getItemCount() - 1);
- }
- }
- }
-
- // Disable "No Normalization (multiple)" for bar charts
- private void checkNormalizeInput() {
- if (plotSelector.getValue(plotSelector.getSelectedIndex()).equals("Line")) {
- noNormalizeMultiple.setEnabled(true);
- } else {
- noNormalizeMultiple.setEnabled(false);
- if (noNormalizeMultiple.getValue()) {
- noNormalizeSingle.setValue(true);
- }
- }
- }
-
- private JSONObject buildQueries() {
- List<Series> seriesList = seriesSelector.getAllSeries();
- JSONObject queries = new JSONObject();
- StringBuilder sql = new StringBuilder();
-
- sql.append("SELECT ");
- sql.append(xAxis.getSelectedValue());
- for (Series series : seriesList) {
- addSeriesSelects(series, sql);
- }
-
- sql.append(" FROM tko_perf_view_2");
-
- String xFilterString = globalFilter.getFilterString();
- if (xFilterString.equals("")) {
- NotifyManager.getInstance().showError("You must enter a global filter");
- return null;
- }
-
- sql.append(" WHERE ");
- sql.append(xFilterString);
-
- sql.append(" GROUP BY ");
- sql.append(xAxis.getSelectedValue());
- queries.put("__main__", new JSONString(sql.toString()));
-
- for (Series series : seriesList) {
- String drilldownQuery = getSeriesDrilldownQuery(series, xFilterString);
- queries.put("__" + series.getName() + "__", new JSONString(drilldownQuery));
- }
-
- return queries;
- }
-
- private String getSeriesDrilldownQuery(Series series, String xFilterString) {
- StringBuilder sql;
- sql = new StringBuilder();
- ExtendedListBox valueSelector = series.getDBColumnSelector();
-
- sql.append("SELECT test_idx, ");
- sql.append(valueSelector.getSelectedValue());
- sql.append(" FROM tko_perf_view_2 WHERE ");
-
- String seriesFilter = series.getFilterString();
- if (!xFilterString.equals("") || !seriesFilter.equals("")) {
- sql.append(xFilterString.replace("%", "%%"));
- if (!xFilterString.equals("") && !seriesFilter.equals("")) {
- sql.append(" AND ");
- }
- sql.append(seriesFilter.replace("%", "%%"));
- sql.append(" AND ");
- }
-
- sql.append(xAxis.getSelectedValue());
- sql.append(" = %s ORDER BY ");
- sql.append(valueSelector.getSelectedValue());
- return sql.toString();
- }
-
- private void addSeriesSelects(Series series, StringBuilder sql) {
- ExtendedListBox valueSelector = series.getDBColumnSelector();
-
- StringBuilder ifClause = new StringBuilder();
- String seriesFilter = series.getFilterString();
- if (!seriesFilter.equals("")) {
- ifClause.append("IF(");
- ifClause.append(seriesFilter);
- ifClause.append(", ");
- }
- ifClause.append(valueSelector.getSelectedValue());
- if (!seriesFilter.equals("")) {
- ifClause.append(", NULL)");
- }
-
- sql.append(", ");
- sql.append(series.getAggregation());
- sql.append(ifClause.toString());
- sql.append(") '");
- sql.append(series.getName());
- sql.append("'");
- if (series.wantErrorBars()) {
- sql.append(", STDDEV(");
- sql.append(ifClause.toString());
- sql.append(") 'errors-");
- sql.append(series.getName());
- sql.append("'");
- }
- }
-
- // Disable the "Invert y-axis" checkboxes if inversion doesn't make sense
- private void checkInvertible() {
- boolean invertible = noNormalizeMultiple.getValue() || normalizeFirst.getValue()
- || normalizeX.getValue();
- seriesSelector.setInvertible(invertible);
- }
-
- @Override
- protected JSONObject buildParams() {
- JSONObject queries = buildQueries();
- if (queries == null) {
- return null;
- }
-
- Map<String, String> params = new HashMap<String, String>();
- String plot = plotSelector.getSelectedValue();
- params.put("plot", plot);
- addNormalizeParameter(plot, params);
-
- JSONObject jsonParams = Utils.mapToJsonObject(params);
- jsonParams.put("invert", Utils.stringsToJSON(seriesSelector.getInverted()));
- jsonParams.put("queries", queries);
- return jsonParams;
- }
-
- @Override
- public String getFrontendId() {
- return "metrics_plot";
- }
-}
diff --git a/frontend/client/src/autotest/tko/Plot.java b/frontend/client/src/autotest/tko/Plot.java
deleted file mode 100644
index bacf01c..0000000
--- a/frontend/client/src/autotest/tko/Plot.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package autotest.tko;
-
-import autotest.common.JsonRpcCallback;
-import autotest.common.JsonRpcProxy;
-import autotest.common.Utils;
-import autotest.tko.TableView.TableSwitchListener;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
-import com.google.gwt.json.client.JSONObject;
-import com.google.gwt.json.client.JSONString;
-import com.google.gwt.json.client.JSONValue;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTML;
-
-abstract class Plot extends Composite {
- private static final String CALLBACK_PREFIX = "__plot_drilldown";
-
- private static int callbackNameCounter = 0;
- protected final static JsonRpcProxy rpcProxy = JsonRpcProxy.getProxy();
-
- private String rpcName;
- private HTML plotElement = new HTML();
- protected TableSwitchListener listener;
-
- private String callbackName;
-
- private static class DummyRpcCallback extends JsonRpcCallback {
- @Override
- public void onSuccess(JSONValue result) {}
- }
-
- public Plot(String rpcName) {
- this.rpcName = rpcName;
- this.callbackName = getFreshCallbackName();
- initWidget(plotElement);
- }
-
- private static String getFreshCallbackName() {
- callbackNameCounter++;
- return CALLBACK_PREFIX + callbackNameCounter;
- }
-
- /**
- * This function is called at initialization time and allows the plot to put native
- * callbacks in place for drilldown functionality from graphs.
- */
- public native void setDrilldownTrigger() /*-{
- var instance = this;
- var name = this.@autotest.tko.Plot::callbackName;
- $wnd[name] = function(drilldownParams) {
- instance.@autotest.tko.Plot::showDrilldown(Lcom/google/gwt/core/client/JavaScriptObject;)(drilldownParams);
- }
- }-*/;
-
- /**
- * Get a native JS object that acts as a proxy to this object. Currently the only exposed
- * method is refresh(params), where params is a JS object. This is only necessary for allowing
- * externally-written native code to use this object without having to write out the full JSNI
- * method call syntax.
- */
- public native JavaScriptObject getNativeProxy() /*-{
- var instance = this;
- return {
- refresh: function(params) {
- jsonObjectParams = @com.google.gwt.json.client.JSONObject::new(Lcom/google/gwt/core/client/JavaScriptObject;)(params);
- instance.@autotest.tko.Plot::refresh(Lcom/google/gwt/json/client/JSONObject;)(jsonObjectParams);
- }
- };
- }-*/;
-
- @SuppressWarnings("unused") // called from native code (see setDrilldownTrigger)
- private void showDrilldown(JavaScriptObject drilldownParamsJso) {
- UncaughtExceptionHandler handler = GWT.getUncaughtExceptionHandler();
- if (handler == null) {
- showDrilldownImpl(new JSONObject(drilldownParamsJso));
- return;
- }
-
- try {
- showDrilldownImpl(new JSONObject(drilldownParamsJso));
- } catch (Throwable throwable) {
- handler.onUncaughtException(throwable);
- }
- }
-
- protected abstract void showDrilldownImpl(JSONObject drilldownParams);
-
- public void refresh(JSONObject params, final JsonRpcCallback callback) {
- params.put("drilldown_callback", new JSONString(callbackName));
- rpcProxy.rpcCall(rpcName, params, new JsonRpcCallback() {
- @Override
- public void onSuccess(JSONValue result) {
- plotElement.setHTML(Utils.jsonToString(result));
- callback.onSuccess(result);
- }
-
- @Override
- public void onError(JSONObject errorObject) {
- callback.onError(errorObject);
- }
- });
- }
-
- public void refresh(JSONObject params) {
- refresh(params, new DummyRpcCallback());
- }
-
- public void setListener(TableSwitchListener listener) {
- this.listener = listener;
- }
-}
diff --git a/frontend/client/src/autotest/tko/TkoClient.java b/frontend/client/src/autotest/tko/TkoClient.java
index f9fb41c..c738bb6 100644
--- a/frontend/client/src/autotest/tko/TkoClient.java
+++ b/frontend/client/src/autotest/tko/TkoClient.java
@@ -19,7 +19,6 @@
private CommonPanel commonPanel;
private TabView spreadsheetView;
private TableView tableView;
- private GraphingView graphingView;
private TestDetailView detailView;
private CustomTabPanel mainTabPanel = new CustomTabPanel();
@@ -44,13 +43,11 @@
commonPanel = CommonPanel.getPanel();
spreadsheetView = new SpreadsheetView(this);
tableView = new TableView(this);
- graphingView = new GraphingView(this);
detailView = TkoUtils.factory.getTestDetailView();
mainTabPanel.getCommonAreaPanel().add(commonPanel);
mainTabPanel.addTabView(spreadsheetView);
mainTabPanel.addTabView(tableView);
- mainTabPanel.addTabView(graphingView);
mainTabPanel.addTabView(detailView);
savedQueriesControl = new SavedQueriesControl();
diff --git a/frontend/tko/graphing_utils.py b/frontend/tko/graphing_utils.py
deleted file mode 100644
index 9d1a9fb..0000000
--- a/frontend/tko/graphing_utils.py
+++ /dev/null
@@ -1,861 +0,0 @@
-# pylint: disable-msg=C0111
-
-import base64, os, tempfile, pickle, datetime, django.db
-import os.path, getpass
-from math import sqrt
-
-# When you import matplotlib, it tries to write some temp files for better
-# performance, and it does that to the directory in MPLCONFIGDIR, or, if that
-# doesn't exist, the home directory. Problem is, the home directory is not
-# writable when running under Apache, and matplotlib's not smart enough to
-# handle that. It does appear smart enough to handle the files going
-# away after they are written, though.
-
-temp_dir = os.path.join(tempfile.gettempdir(),
- '.matplotlib-%s' % getpass.getuser())
-if not os.path.exists(temp_dir):
- os.mkdir(temp_dir)
-os.environ['MPLCONFIGDIR'] = temp_dir
-
-try:
- import matplotlib
- matplotlib.use('Agg')
- import matplotlib.figure, matplotlib.backends.backend_agg
- import StringIO, colorsys, PIL.Image, PIL.ImageChops
-except ImportError:
- # Do nothing, in case this is part of a unit test, so the unit test
- # can proceed.
- pass
-
-from autotest_lib.frontend.afe import readonly_connection
-from autotest_lib.frontend.afe.model_logic import ValidationError
-from json import encoder
-from autotest_lib.client.common_lib import global_config
-from autotest_lib.frontend.tko import models, tko_rpc_utils
-
-_FIGURE_DPI = 100
-_FIGURE_WIDTH_IN = 10
-_FIGURE_BOTTOM_PADDING_IN = 2 # for x-axis labels
-
-_SINGLE_PLOT_HEIGHT = 6
-_MULTIPLE_PLOT_HEIGHT_PER_PLOT = 4
-
-_MULTIPLE_PLOT_MARKER_TYPE = 'o'
-_MULTIPLE_PLOT_MARKER_SIZE = 4
-_SINGLE_PLOT_STYLE = 'bs-' # blue squares with lines connecting
-_SINGLE_PLOT_ERROR_BAR_COLOR = 'r'
-
-_LEGEND_FONT_SIZE = 'xx-small'
-_LEGEND_HANDLE_LENGTH = 0.03
-_LEGEND_NUM_POINTS = 3
-_LEGEND_MARKER_TYPE = 'o'
-
-_LINE_XTICK_LABELS_SIZE = 'x-small'
-_BAR_XTICK_LABELS_SIZE = 8
-
-_json_encoder = encoder.JSONEncoder()
-
-class NoDataError(Exception):
- """\
- Exception to raise if the graphing query returned an empty resultset.
- """
-
-
-def _colors(n):
- """\
- Generator function for creating n colors. The return value is a tuple
- representing the RGB of the color.
- """
- for i in xrange(n):
- yield colorsys.hsv_to_rgb(float(i) / n, 1.0, 1.0)
-
-
-def _resort(kernel_labels, list_to_sort):
- """\
- Resorts a list, using a list of kernel strings as the keys. Returns the
- resorted list.
- """
-
- labels = [tko_rpc_utils.KernelString(label) for label in kernel_labels]
- resorted_pairs = sorted(zip(labels, list_to_sort))
-
- # We only want the resorted list; we are not interested in the kernel
- # strings.
- return [pair[1] for pair in resorted_pairs]
-
-
-def _quote(string):
- return "%s%s%s" % ("'", string.replace("'", r"\'"), "'")
-
-
-_HTML_TEMPLATE = """\
-<html><head></head><body>
-<img src="data:image/png;base64,%s" usemap="#%s"
- border="0" alt="graph">
-<map name="%s">%s</map>
-</body></html>"""
-
-_AREA_TEMPLATE = """\
-<area shape="rect" coords="%i,%i,%i,%i" title="%s"
-href="#"
-onclick="%s(%s); return false;">"""
-
-
-class MetricsPlot(object):
- def __init__(self, query_dict, plot_type, inverted_series, normalize_to,
- drilldown_callback):
- """
- query_dict: dictionary containing the main query and the drilldown
- queries. The main query returns a row for each x value. The first
- column contains the x-axis label. Subsequent columns contain data
- for each series, named by the column names. A column named
- 'errors-<x>' will be interpreted as errors for the series named <x>.
-
- plot_type: 'Line' or 'Bar', depending on the plot type the user wants
-
- inverted_series: list of series that should be plotted on an inverted
- y-axis
-
- normalize_to:
- None - do not normalize
- 'first' - normalize against the first data point
- 'x__%s' - normalize against the x-axis value %s
- 'series__%s' - normalize against the series %s
-
- drilldown_callback: name of drilldown callback method.
- """
- self.query_dict = query_dict
- if plot_type == 'Line':
- self.is_line = True
- elif plot_type == 'Bar':
- self.is_line = False
- else:
- raise ValidationError({'plot' : 'Plot must be either Line or Bar'})
- self.plot_type = plot_type
- self.inverted_series = inverted_series
- self.normalize_to = normalize_to
- if self.normalize_to is None:
- self.normalize_to = ''
- self.drilldown_callback = drilldown_callback
-
-
-class QualificationHistogram(object):
- def __init__(self, query, filter_string, interval, drilldown_callback):
- """
- query: the main query to retrieve the pass rate information. The first
- column contains the hostnames of all the machines that satisfied the
- global filter. The second column (titled 'total') contains the total
- number of tests that ran on that machine and satisfied the global
- filter. The third column (titled 'good') contains the number of
- those tests that passed on that machine.
-
- filter_string: filter to apply to the common global filter to show the
- Table View drilldown of a histogram bucket
-
- interval: interval for each bucket. E.g., 10 means that buckets should
- be 0-10%, 10%-20%, ...
-
- """
- self.query = query
- self.filter_string = filter_string
- self.interval = interval
- self.drilldown_callback = drilldown_callback
-
-
-def _create_figure(height_inches):
- """\
- Creates an instance of matplotlib.figure.Figure, given the height in inches.
- Returns the figure and the height in pixels.
- """
-
- fig = matplotlib.figure.Figure(
- figsize=(_FIGURE_WIDTH_IN, height_inches + _FIGURE_BOTTOM_PADDING_IN),
- dpi=_FIGURE_DPI, facecolor='white')
- fig.subplots_adjust(bottom=float(_FIGURE_BOTTOM_PADDING_IN) / height_inches)
- return (fig, fig.get_figheight() * _FIGURE_DPI)
-
-
-def _create_line(plots, labels, plot_info):
- """\
- Given all the data for the metrics, create a line plot.
-
- plots: list of dicts containing the plot data. Each dict contains:
- x: list of x-values for the plot
- y: list of corresponding y-values
- errors: errors for each data point, or None if no error information
- available
- label: plot title
- labels: list of x-tick labels
- plot_info: a MetricsPlot
- """
- # when we're doing any kind of normalization, all series get put into a
- # single plot
- single = bool(plot_info.normalize_to)
-
- area_data = []
- lines = []
- if single:
- plot_height = _SINGLE_PLOT_HEIGHT
- else:
- plot_height = _MULTIPLE_PLOT_HEIGHT_PER_PLOT * len(plots)
- figure, height = _create_figure(plot_height)
-
- if single:
- subplot = figure.add_subplot(1, 1, 1)
-
- # Plot all the data
- for plot_index, (plot, color) in enumerate(zip(plots, _colors(len(plots)))):
- needs_invert = (plot['label'] in plot_info.inverted_series)
-
- # Add a new subplot, if user wants multiple subplots
- # Also handle axis inversion for subplots here
- if not single:
- subplot = figure.add_subplot(len(plots), 1, plot_index + 1)
- subplot.set_title(plot['label'])
- if needs_invert:
- # for separate plots, just invert the y-axis
- subplot.set_ylim(1, 0)
- elif needs_invert:
- # for a shared plot (normalized data), need to invert the y values
- # manually, since all plots share a y-axis
- plot['y'] = [-y for y in plot['y']]
-
- # Plot the series
- subplot.set_xticks(range(0, len(labels)))
- subplot.set_xlim(-1, len(labels))
- if single:
- lines += subplot.plot(plot['x'], plot['y'], label=plot['label'],
- marker=_MULTIPLE_PLOT_MARKER_TYPE,
- markersize=_MULTIPLE_PLOT_MARKER_SIZE)
- error_bar_color = lines[-1].get_color()
- else:
- lines += subplot.plot(plot['x'], plot['y'], _SINGLE_PLOT_STYLE,
- label=plot['label'])
- error_bar_color = _SINGLE_PLOT_ERROR_BAR_COLOR
- if plot['errors']:
- subplot.errorbar(plot['x'], plot['y'], linestyle='None',
- yerr=plot['errors'], color=error_bar_color)
- subplot.set_xticklabels([])
-
- # Construct the information for the drilldowns.
- # We need to do this in a separate loop so that all the data is in
- # matplotlib before we start calling transform(); otherwise, it will return
- # incorrect data because it hasn't finished adjusting axis limits.
- for line in lines:
-
- # Get the pixel coordinates of each point on the figure
- x = line.get_xdata()
- y = line.get_ydata()
- label = line.get_label()
- icoords = line.get_transform().transform(zip(x,y))
-
- # Get the appropriate drilldown query
- drill = plot_info.query_dict['__' + label + '__']
-
- # Set the title attributes (hover-over tool-tips)
- x_labels = [labels[x_val] for x_val in x]
- titles = ['%s - %s: %f' % (label, x_label, y_val)
- for x_label, y_val in zip(x_labels, y)]
-
- # Get the appropriate parameters for the drilldown query
- params = [dict(query=drill, series=line.get_label(), param=x_label)
- for x_label in x_labels]
-
- area_data += [dict(left=ix - 5, top=height - iy - 5,
- right=ix + 5, bottom=height - iy + 5,
- title= title,
- callback=plot_info.drilldown_callback,
- callback_arguments=param_dict)
- for (ix, iy), title, param_dict
- in zip(icoords, titles, params)]
-
- subplot.set_xticklabels(labels, rotation=90, size=_LINE_XTICK_LABELS_SIZE)
-
- # Show the legend if there are not multiple subplots
- if single:
- font_properties = matplotlib.font_manager.FontProperties(
- size=_LEGEND_FONT_SIZE)
- legend = figure.legend(lines, [plot['label'] for plot in plots],
- prop=font_properties,
- handlelen=_LEGEND_HANDLE_LENGTH,
- numpoints=_LEGEND_NUM_POINTS)
- # Workaround for matplotlib not keeping all line markers in the legend -
- # it seems if we don't do this, matplotlib won't keep all the line
- # markers in the legend.
- for line in legend.get_lines():
- line.set_marker(_LEGEND_MARKER_TYPE)
-
- return (figure, area_data)
-
-
-def _get_adjusted_bar(x, bar_width, series_index, num_plots):
- """\
- Adjust the list 'x' to take the multiple series into account. Each series
- should be shifted such that the middle series lies at the appropriate x-axis
- tick with the other bars around it. For example, if we had four series
- (i.e. four bars per x value), we want to shift the left edges of the bars as
- such:
- Bar 1: -2 * width
- Bar 2: -width
- Bar 3: none
- Bar 4: width
- """
- adjust = (-0.5 * num_plots - 1 + series_index) * bar_width
- return [x_val + adjust for x_val in x]
-
-
-# TODO(showard): merge much of this function with _create_line by extracting and
-# parameterizing methods
-def _create_bar(plots, labels, plot_info):
- """\
- Given all the data for the metrics, create a line plot.
-
- plots: list of dicts containing the plot data.
- x: list of x-values for the plot
- y: list of corresponding y-values
- errors: errors for each data point, or None if no error information
- available
- label: plot title
- labels: list of x-tick labels
- plot_info: a MetricsPlot
- """
-
- area_data = []
- bars = []
- figure, height = _create_figure(_SINGLE_PLOT_HEIGHT)
-
- # Set up the plot
- subplot = figure.add_subplot(1, 1, 1)
- subplot.set_xticks(range(0, len(labels)))
- subplot.set_xlim(-1, len(labels))
- subplot.set_xticklabels(labels, rotation=90, size=_BAR_XTICK_LABELS_SIZE)
- # draw a bold line at y=0, making it easier to tell if bars are dipping
- # below the axis or not.
- subplot.axhline(linewidth=2, color='black')
-
- # width here is the width for each bar in the plot. Matplotlib default is
- # 0.8.
- width = 0.8 / len(plots)
-
- # Plot the data
- for plot_index, (plot, color) in enumerate(zip(plots, _colors(len(plots)))):
- # Invert the y-axis if needed
- if plot['label'] in plot_info.inverted_series:
- plot['y'] = [-y for y in plot['y']]
-
- adjusted_x = _get_adjusted_bar(plot['x'], width, plot_index + 1,
- len(plots))
- bar_data = subplot.bar(adjusted_x, plot['y'],
- width=width, yerr=plot['errors'],
- facecolor=color,
- label=plot['label'])
- bars.append(bar_data[0])
-
- # Construct the information for the drilldowns.
- # See comment in _create_line for why we need a separate loop to do this.
- for plot_index, plot in enumerate(plots):
- adjusted_x = _get_adjusted_bar(plot['x'], width, plot_index + 1,
- len(plots))
-
- # Let matplotlib plot the data, so that we can get the data-to-image
- # coordinate transforms
- line = subplot.plot(adjusted_x, plot['y'], linestyle='None')[0]
- label = plot['label']
- upper_left_coords = line.get_transform().transform(zip(adjusted_x,
- plot['y']))
- bottom_right_coords = line.get_transform().transform(
- [(x + width, 0) for x in adjusted_x])
-
- # Get the drilldown query
- drill = plot_info.query_dict['__' + label + '__']
-
- # Set the title attributes
- x_labels = [labels[x] for x in plot['x']]
- titles = ['%s - %s: %f' % (plot['label'], label, y)
- for label, y in zip(x_labels, plot['y'])]
- params = [dict(query=drill, series=plot['label'], param=x_label)
- for x_label in x_labels]
- area_data += [dict(left=ulx, top=height - uly,
- right=brx, bottom=height - bry,
- title=title,
- callback=plot_info.drilldown_callback,
- callback_arguments=param_dict)
- for (ulx, uly), (brx, bry), title, param_dict
- in zip(upper_left_coords, bottom_right_coords, titles,
- params)]
-
- figure.legend(bars, [plot['label'] for plot in plots])
- return (figure, area_data)
-
-
-def _normalize(data_values, data_errors, base_values, base_errors):
- """\
- Normalize the data against a baseline.
-
- data_values: y-values for the to-be-normalized data
- data_errors: standard deviations for the to-be-normalized data
- base_values: list of values normalize against
- base_errors: list of standard deviations for those base values
- """
- values = []
- for value, base in zip(data_values, base_values):
- try:
- values.append(100 * (value - base) / base)
- except ZeroDivisionError:
- # Base is 0.0 so just simplify:
- # If value < base: append -100.0;
- # If value == base: append 0.0 (obvious); and
- # If value > base: append 100.0.
- values.append(100 * float(cmp(value, base)))
-
- # Based on error for f(x,y) = 100 * (x - y) / y
- if data_errors:
- if not base_errors:
- base_errors = [0] * len(data_errors)
- errors = []
- for data, error, base_value, base_error in zip(
- data_values, data_errors, base_values, base_errors):
- try:
- errors.append(sqrt(error**2 * (100 / base_value)**2
- + base_error**2 * (100 * data / base_value**2)**2
- + error * base_error * (100 / base_value**2)**2))
- except ZeroDivisionError:
- # Again, base is 0.0 so do the simple thing.
- errors.append(100 * abs(error))
- else:
- errors = None
-
- return (values, errors)
-
-
-def _create_png(figure):
- """\
- Given the matplotlib figure, generate the PNG data for it.
- """
-
- # Draw the image
- canvas = matplotlib.backends.backend_agg.FigureCanvasAgg(figure)
- canvas.draw()
- size = canvas.get_renderer().get_canvas_width_height()
- image_as_string = canvas.tostring_rgb()
- image = PIL.Image.fromstring('RGB', size, image_as_string, 'raw', 'RGB', 0,
- 1)
- image_background = PIL.Image.new(image.mode, image.size,
- figure.get_facecolor())
-
- # Crop the image to remove surrounding whitespace
- non_whitespace = PIL.ImageChops.difference(image, image_background)
- bounding_box = non_whitespace.getbbox()
- image = image.crop(bounding_box)
-
- image_data = StringIO.StringIO()
- image.save(image_data, format='PNG')
-
- return image_data.getvalue(), bounding_box
-
-
-def _create_image_html(figure, area_data, plot_info):
- """\
- Given the figure and drilldown data, construct the HTML that will render the
- graph as a PNG image, and attach the image map to that image.
-
- figure: figure containing the drawn plot(s)
- area_data: list of parameters for each area of the image map. See the
- definition of the template string '_AREA_TEMPLATE'
- plot_info: a MetricsPlot or QualHistogram
- """
-
- png, bbox = _create_png(figure)
-
- # Construct the list of image map areas
- areas = [_AREA_TEMPLATE %
- (data['left'] - bbox[0], data['top'] - bbox[1],
- data['right'] - bbox[0], data['bottom'] - bbox[1],
- data['title'], data['callback'],
- _json_encoder.encode(data['callback_arguments'])
- .replace('"', '"'))
- for data in area_data]
-
- map_name = plot_info.drilldown_callback + '_map'
- return _HTML_TEMPLATE % (base64.b64encode(png), map_name, map_name,
- '\n'.join(areas))
-
-
-def _find_plot_by_label(plots, label):
- for index, plot in enumerate(plots):
- if plot['label'] == label:
- return index
- raise ValueError('no plot labeled "%s" found' % label)
-
-
-def _normalize_to_series(plots, base_series):
- base_series_index = _find_plot_by_label(plots, base_series)
- base_plot = plots[base_series_index]
- base_xs = base_plot['x']
- base_values = base_plot['y']
- base_errors = base_plot['errors']
- del plots[base_series_index]
-
- for plot in plots:
- old_xs, old_values, old_errors = plot['x'], plot['y'], plot['errors']
- new_xs, new_values, new_errors = [], [], []
- new_base_values, new_base_errors = [], []
- # Select only points in the to-be-normalized data that have a
- # corresponding baseline value
- for index, x_value in enumerate(old_xs):
- try:
- base_index = base_xs.index(x_value)
- except ValueError:
- continue
-
- new_xs.append(x_value)
- new_values.append(old_values[index])
- new_base_values.append(base_values[base_index])
- if old_errors:
- new_errors.append(old_errors[index])
- new_base_errors.append(base_errors[base_index])
-
- if not new_xs:
- raise NoDataError('No normalizable data for series ' +
- plot['label'])
- plot['x'] = new_xs
- plot['y'] = new_values
- if old_errors:
- plot['errors'] = new_errors
-
- plot['y'], plot['errors'] = _normalize(plot['y'], plot['errors'],
- new_base_values,
- new_base_errors)
-
-
-def _create_metrics_plot_helper(plot_info, extra_text=None):
- """
- Create a metrics plot of the given plot data.
- plot_info: a MetricsPlot object.
- extra_text: text to show at the uppper-left of the graph
-
- TODO(showard): move some/all of this logic into methods on MetricsPlot
- """
- query = plot_info.query_dict['__main__']
- cursor = readonly_connection.cursor()
- cursor.execute(query)
-
- if not cursor.rowcount:
- raise NoDataError('query did not return any data')
- rows = cursor.fetchall()
- # "transpose" rows, so columns[0] is all the values from the first column,
- # etc.
- columns = zip(*rows)
-
- plots = []
- labels = [str(label) for label in columns[0]]
- needs_resort = (cursor.description[0][0] == 'kernel')
-
- # Collect all the data for the plot
- col = 1
- while col < len(cursor.description):
- y = columns[col]
- label = cursor.description[col][0]
- col += 1
- if (col < len(cursor.description) and
- 'errors-' + label == cursor.description[col][0]):
- errors = columns[col]
- col += 1
- else:
- errors = None
- if needs_resort:
- y = _resort(labels, y)
- if errors:
- errors = _resort(labels, errors)
-
- x = [index for index, value in enumerate(y) if value is not None]
- if not x:
- raise NoDataError('No data for series ' + label)
- y = [y[i] for i in x]
- if errors:
- errors = [errors[i] for i in x]
- plots.append({
- 'label': label,
- 'x': x,
- 'y': y,
- 'errors': errors
- })
-
- if needs_resort:
- labels = _resort(labels, labels)
-
- # Normalize the data if necessary
- normalize_to = plot_info.normalize_to
- if normalize_to == 'first' or normalize_to.startswith('x__'):
- if normalize_to != 'first':
- baseline = normalize_to[3:]
- try:
- baseline_index = labels.index(baseline)
- except ValueError:
- raise ValidationError({
- 'Normalize' : 'Invalid baseline %s' % baseline
- })
- for plot in plots:
- if normalize_to == 'first':
- plot_index = 0
- else:
- try:
- plot_index = plot['x'].index(baseline_index)
- # if the value is not found, then we cannot normalize
- except ValueError:
- raise ValidationError({
- 'Normalize' : ('%s does not have a value for %s'
- % (plot['label'], normalize_to[3:]))
- })
- base_values = [plot['y'][plot_index]] * len(plot['y'])
- if plot['errors']:
- base_errors = [plot['errors'][plot_index]] * len(plot['errors'])
- plot['y'], plot['errors'] = _normalize(plot['y'], plot['errors'],
- base_values,
- None or base_errors)
-
- elif normalize_to.startswith('series__'):
- base_series = normalize_to[8:]
- _normalize_to_series(plots, base_series)
-
- # Call the appropriate function to draw the line or bar plot
- if plot_info.is_line:
- figure, area_data = _create_line(plots, labels, plot_info)
- else:
- figure, area_data = _create_bar(plots, labels, plot_info)
-
- # TODO(showard): extract these magic numbers to named constants
- if extra_text:
- text_y = .95 - .0075 * len(plots)
- figure.text(.1, text_y, extra_text, size='xx-small')
-
- return (figure, area_data)
-
-
-def create_metrics_plot(query_dict, plot_type, inverted_series, normalize_to,
- drilldown_callback, extra_text=None):
- plot_info = MetricsPlot(query_dict, plot_type, inverted_series,
- normalize_to, drilldown_callback)
- figure, area_data = _create_metrics_plot_helper(plot_info, extra_text)
- return _create_image_html(figure, area_data, plot_info)
-
-
-def _get_hostnames_in_bucket(hist_data, bucket):
- """\
- Get all the hostnames that constitute a particular bucket in the histogram.
-
- hist_data: list containing tuples of (hostname, pass_rate)
- bucket: tuple containing the (low, high) values of the target bucket
- """
-
- return [hostname for hostname, pass_rate in hist_data
- if bucket[0] <= pass_rate < bucket[1]]
-
-
-def _create_qual_histogram_helper(plot_info, extra_text=None):
- """\
- Create a machine qualification histogram of the given data.
-
- plot_info: a QualificationHistogram
- extra_text: text to show at the upper-left of the graph
-
- TODO(showard): move much or all of this into methods on
- QualificationHistogram
- """
- cursor = readonly_connection.cursor()
- cursor.execute(plot_info.query)
-
- if not cursor.rowcount:
- raise NoDataError('query did not return any data')
-
- # Lists to store the plot data.
- # hist_data store tuples of (hostname, pass_rate) for machines that have
- # pass rates between 0 and 100%, exclusive.
- # no_tests is a list of machines that have run none of the selected tests
- # no_pass is a list of machines with 0% pass rate
- # perfect is a list of machines with a 100% pass rate
- hist_data = []
- no_tests = []
- no_pass = []
- perfect = []
-
- # Construct the lists of data to plot
- for hostname, total, good in cursor.fetchall():
- if total == 0:
- no_tests.append(hostname)
- continue
-
- if good == 0:
- no_pass.append(hostname)
- elif good == total:
- perfect.append(hostname)
- else:
- percentage = 100.0 * good / total
- hist_data.append((hostname, percentage))
-
- interval = plot_info.interval
- bins = range(0, 100, interval)
- if bins[-1] != 100:
- bins.append(bins[-1] + interval)
-
- figure, height = _create_figure(_SINGLE_PLOT_HEIGHT)
- subplot = figure.add_subplot(1, 1, 1)
-
- # Plot the data and get all the bars plotted
- _,_, bars = subplot.hist([data[1] for data in hist_data],
- bins=bins, align='left')
- bars += subplot.bar([-interval], len(no_pass),
- width=interval, align='center')
- bars += subplot.bar([bins[-1]], len(perfect),
- width=interval, align='center')
- bars += subplot.bar([-3 * interval], len(no_tests),
- width=interval, align='center')
-
- buckets = [(bin, min(bin + interval, 100)) for bin in bins[:-1]]
- # set the x-axis range to cover all the normal bins plus the three "special"
- # ones - N/A (3 intervals left), 0% (1 interval left) ,and 100% (far right)
- subplot.set_xlim(-4 * interval, bins[-1] + interval)
- subplot.set_xticks([-3 * interval, -interval] + bins + [100 + interval])
- subplot.set_xticklabels(['N/A', '0%'] +
- ['%d%% - <%d%%' % bucket for bucket in buckets] +
- ['100%'], rotation=90, size='small')
-
- # Find the coordinates on the image for each bar
- x = []
- y = []
- for bar in bars:
- x.append(bar.get_x())
- y.append(bar.get_height())
- f = subplot.plot(x, y, linestyle='None')[0]
- upper_left_coords = f.get_transform().transform(zip(x, y))
- bottom_right_coords = f.get_transform().transform(
- [(x_val + interval, 0) for x_val in x])
-
- # Set the title attributes
- titles = ['%d%% - <%d%%: %d machines' % (bucket[0], bucket[1], y_val)
- for bucket, y_val in zip(buckets, y)]
- titles.append('0%%: %d machines' % len(no_pass))
- titles.append('100%%: %d machines' % len(perfect))
- titles.append('N/A: %d machines' % len(no_tests))
-
- # Get the hostnames for each bucket in the histogram
- names_list = [_get_hostnames_in_bucket(hist_data, bucket)
- for bucket in buckets]
- names_list += [no_pass, perfect]
-
- if plot_info.filter_string:
- plot_info.filter_string += ' AND '
-
- # Construct the list of drilldown parameters to be passed when the user
- # clicks on the bar.
- params = []
- for names in names_list:
- if names:
- hostnames = ','.join(_quote(hostname) for hostname in names)
- hostname_filter = 'hostname IN (%s)' % hostnames
- full_filter = plot_info.filter_string + hostname_filter
- params.append({'type': 'normal',
- 'filterString': full_filter})
- else:
- params.append({'type': 'empty'})
-
- params.append({'type': 'not_applicable',
- 'hosts': '<br />'.join(no_tests)})
-
- area_data = [dict(left=ulx, top=height - uly,
- right=brx, bottom=height - bry,
- title=title, callback=plot_info.drilldown_callback,
- callback_arguments=param_dict)
- for (ulx, uly), (brx, bry), title, param_dict
- in zip(upper_left_coords, bottom_right_coords, titles, params)]
-
- # TODO(showard): extract these magic numbers to named constants
- if extra_text:
- figure.text(.1, .95, extra_text, size='xx-small')
-
- return (figure, area_data)
-
-
-def create_qual_histogram(query, filter_string, interval, drilldown_callback,
- extra_text=None):
- plot_info = QualificationHistogram(query, filter_string, interval,
- drilldown_callback)
- figure, area_data = _create_qual_histogram_helper(plot_info, extra_text)
- return _create_image_html(figure, area_data, plot_info)
-
-
-def create_embedded_plot(model, update_time):
- """\
- Given an EmbeddedGraphingQuery object, generate the PNG image for it.
-
- model: EmbeddedGraphingQuery object
- update_time: 'Last updated' time
- """
-
- params = pickle.loads(model.params)
- extra_text = 'Last updated: %s' % update_time
-
- if model.graph_type == 'metrics':
- plot_info = MetricsPlot(query_dict=params['queries'],
- plot_type=params['plot'],
- inverted_series=params['invert'],
- normalize_to=None,
- drilldown_callback='')
- figure, areas_unused = _create_metrics_plot_helper(plot_info,
- extra_text)
- elif model.graph_type == 'qual':
- plot_info = QualificationHistogram(
- query=params['query'], filter_string=params['filter_string'],
- interval=params['interval'], drilldown_callback='')
- figure, areas_unused = _create_qual_histogram_helper(plot_info,
- extra_text)
- else:
- raise ValueError('Invalid graph_type %s' % model.graph_type)
-
- image, bounding_box_unused = _create_png(figure)
- return image
-
-
-_cache_timeout = global_config.global_config.get_config_value(
- 'AUTOTEST_WEB', 'graph_cache_creation_timeout_minutes')
-
-
-def handle_plot_request(id, max_age):
- """\
- Given the embedding id of a graph, generate a PNG of the embedded graph
- associated with that id.
-
- id: id of the embedded graph
- max_age: maximum age, in minutes, that a cached version should be held
- """
- model = models.EmbeddedGraphingQuery.objects.get(id=id)
-
- # Check if the cached image needs to be updated
- now = datetime.datetime.now()
- update_time = model.last_updated + datetime.timedelta(minutes=int(max_age))
- if now > update_time:
- cursor = django.db.connection.cursor()
-
- # We want this query to update the refresh_time only once, even if
- # multiple threads are running it at the same time. That is, only the
- # first thread will win the race, and it will be the one to update the
- # cached image; all other threads will show that they updated 0 rows
- query = """
- UPDATE embedded_graphing_queries
- SET refresh_time = NOW()
- WHERE id = %s AND (
- refresh_time IS NULL OR
- refresh_time + INTERVAL %s MINUTE < NOW()
- )
- """
- cursor.execute(query, (id, _cache_timeout))
-
- # Only refresh the cached image if we were successful in updating the
- # refresh time
- if cursor.rowcount:
- model.cached_png = create_embedded_plot(model, now.ctime())
- model.last_updated = now
- model.refresh_time = None
- model.save()
-
- return model.cached_png
diff --git a/frontend/tko/models.py b/frontend/tko/models.py
index 81e2928..de0c3ae 100644
--- a/frontend/tko/models.py
+++ b/frontend/tko/models.py
@@ -309,25 +309,6 @@
db_table = 'tko_saved_queries'
-class EmbeddedGraphingQuery(dbmodels.Model, model_logic.ModelExtensions):
- """Models an embedded graphing query."""
- url_token = dbmodels.TextField(null=False, blank=False)
- graph_type = dbmodels.CharField(max_length=16, null=False, blank=False)
- params = dbmodels.TextField(null=False, blank=False)
- last_updated = dbmodels.DateTimeField(null=False, blank=False,
- editable=False)
- # refresh_time shows the time at which a thread is updating the cached
- # image, or NULL if no one is updating the image. This is used so that only
- # one thread is updating the cached image at a time (see
- # graphing_utils.handle_plot_request).
- refresh_time = dbmodels.DateTimeField(editable=False)
- cached_png = dbmodels.TextField(editable=False)
-
- class Meta:
- """Metadata for class EmbeddedGraphingQuery."""
- db_table = 'tko_embedded_graphing_queries'
-
-
# Views.
class TestViewManager(TempManager):
diff --git a/frontend/tko/views.py b/frontend/tko/views.py
index 2b29c9f..2ea64b7 100644
--- a/frontend/tko/views.py
+++ b/frontend/tko/views.py
@@ -1,7 +1,6 @@
-import django.http
-from autotest_lib.frontend.tko import rpc_interface, graphing_utils
+from autotest_lib.frontend.tko import rpc_interface
from autotest_lib.frontend.tko import csv_encoder
-from autotest_lib.frontend.afe import rpc_handler, rpc_utils
+from autotest_lib.frontend.afe import rpc_handler
rpc_handler_obj = rpc_handler.RpcHandler((rpc_interface,),
document_module=rpc_interface)
@@ -27,7 +26,4 @@
def handle_plot(request):
- id = request.GET['id']
- max_age = request.GET['max_age']
- return django.http.HttpResponse(
- graphing_utils.handle_plot_request(id, max_age), mimetype='image/png')
+ raise DeprecationWarning()