<html>
  <head>
  <title>Skia Buildbot Self-Analysis</title>
  <link rel="icon" href="favicon.ico">
  <script type="text/javascript" src="https://www.google.com/jsapi"></script>
  <script type="text/javascript" src="skia_tools.js"></script>
  <script language="JavaScript">
  "use strict";

  var selectedMaster = null;

  // Build result codes.
  var SUCCESS = 0;

  // Number of builds which should be loaded.
  var DEFAULT_BUILDS_TO_LOAD = 50;

  // Object to manage Git revision history.
  var gitHistory = new skiaTools.GitHistory();

  // Configuration options for the charts
  var LINE_CHART_OPTIONS = {
      "title": "Build Times",
      "width": "100%",
      "height": "100%",
      "chartArea": {left: "9%", top: "9%", width: "86%",
                    height: "70%"},
      "interpolateNulls": true,
      "hAxis": {"title": "Revision"},
      "vAxis": {"title": "Build Time (s)"},
      "legend": {"textStyle": {"fontSize": 12},
                 "position": "bottom"},
  };

  var LINE_CHART_RANGE_FILTER_OPTIONS = {
      "filterColumnIndex": 0,
      "ui": {
          "chartType": "AreaChart",
          "minRangeSize": 1,
          "chartOptions": {
              "chartArea": {"width": "86%",
                            "height": "75%",
                            "left": "9%",
                            "right": "6%"},
              "width": "100%",
              "height": "100%",
              "colors": ["grey"],
              "hAxis": {"baselineColor": "none"},
              "vAxis": {"baselineColor": "none"},
              "interpolateNulls": true,
          },
      },
  };

  var BAR_CHART_OPTIONS = {
      "width": "100%",
      "height": "100%",
      "chartArea": {left: "17%", top: "9%", width: "65%", height: "70%"},
      "hAxis": {"title": "Time (s)"},
      "vAxis": {"title": "Build Step"},
      "tooltip": {"isHtml": true},
      "legend": {"position": "none"},
  };

  // High-level information about each builder.
  var builderData = null;

  var loadStart = null;

  // Load the Visualization API
  google.load("visualization", "1.0", {"packages":["corechart", "controls"]});

  // Set a callback to run when the Google Visualization API is loaded.
  google.setOnLoadCallback(init);

  /**
   * Display text or HTML in the logging div.
   * @param {string} msg The HTML or text to display.
   */
  function setMessage(msg) {
    console.log(msg);
    document.getElementById("logging_div").innerHTML = msg;
  }

  /**
   * Set the HTML content in the pane on the right side of the page.
   * @param {string} content HTML to display.
   */
  function setRightContent(content) {
    document.getElementById("right_content_div").innerHTML = content;
  }

  /**
   * Clear the divs containing charts. Useful when charts need to be updated.
   */
  function clearCharts() {
    document.getElementById("line_chart_div").innerHTML = "";
    document.getElementById("line_chart_range_filter_div").innerHTML = "";
    document.getElementById("bar_chart_div").innerHTML = "";
  }

  /**
   * Convert a duration in seconds to an easily-readable string.
   * @param {number} seconds The duration to convert.
   * @return {string} The duration in HH:MM:SS format.
   */
  function formatTime(secondsParam) {
    var seconds = Math.round(secondsParam);
    var minutes = Math.floor(seconds / 60);
    seconds -= seconds * 60;
    var hours = Math.floor(minutes / 60);
    minutes -= hours * 60;
    var totalTime = "";
    if (seconds > 9) {
      totalTime = seconds;
    } else {
      totalTime = "0" + seconds;
    }
    if (minutes > 9) {
      totalTime = minutes + ":" + totalTime;
    } else {
      totalTime = "0" + minutes + ":" + totalTime;
    }
    if (hours > 9) {
      totalTime = hours + ":" + totalTime;
    } else {
      totalTime = "0" + hours + ":" + totalTime;
    }
    return totalTime;
  }

  /**
   * Draw a line chart illustrating build times for a number of revisions for
   * a set of builders.
   * @param {Array.<string>} displayBuilders List of builders which should be
   *     included in the chart.
   * @param {object} data Dictionary containing builds for various builders,
   *     indexed by commit hash.
   */
  function drawLineChart(displayBuilders, data) {
    var message = "";
    if (loadStart) {
      var elapsedSeconds = (new Date().getTime() - loadStart) / 1000;
      message = "Loaded data in " + elapsedSeconds + " seconds.";
    }
    setMessage(message);
    var table = new google.visualization.DataTable();
    table.addColumn("string", "Revision");
    for (var i = 0; i < displayBuilders.length; i++) {
      table.addColumn("number", displayBuilders[i]);
      table.addColumn({"type": "string", "role": "annotation"});
    }
    var lineChartColsPerBuilder = 2;
    var longestBuildTime = -1;
    var rows = [];
    var allRevs = gitHistory.getRevList();
    for (var revIdx = 0; revIdx < allRevs.length; revIdx++) {
      var rev = allRevs[revIdx];
      var row = [rev];
      var rowHasData = false;
      for (var builderIdx = 0; builderIdx < displayBuilders.length;
           builderIdx++) {
        var builder = displayBuilders[builderIdx];
        if (data[rev] != undefined && data[rev][builder] != undefined) {
          rowHasData = true;
          var time = data[rev][builder].getElapsedTime();
          if (time > longestBuildTime) {
            longestBuildTime = time;
          }
          row.push(time);
          if (data[rev][builder].getResult() != SUCCESS) {
            row.push("failed");
          } else {
            row.push(null);
          }
        } else {
          row.push(null);
          row.push(null);
        }
      }
      // Skip revisions which have no builds.
      if (rowHasData) {
        rows.push(row);
      }
    }
    table.addRows(rows);

    var lineChart = new google.visualization.LineChart(document.getElementById(
        "line_chart_div"));
    google.visualization.events.addListener(lineChart, 'select',
                                            function() {
      var selected = lineChart.getSelection()[0];
      if (selected &&
          selected.column != undefined &&
          selected.row != undefined) {
        var builder = null;
        var builderIdx = Math.floor(
            (selected.column - 1) / lineChartColsPerBuilder);
        builder = displayBuilders[builderIdx];
        var rev = rows[selected.row][0]
        var buildNum = data[rev][builder].getNumber();
        console.log("Selected: " + builder + " @ " + rev);
        var url = "http://" + selectedMaster.getHost() + ":" +
            selectedMaster.getPort() + "/buildstatus?builder=" + builder +
            "&number=" + buildNum;
        var rightContent = "<iframe style=\"width:100%; height:100%; "
                         + "padding:0px; margin=0px; overflow:scroll;\" src=\""
                         + url + "\"></iframe>";
        setRightContent(rightContent);
        drawBarChart(builder, rev, longestBuildTime, data);
      }
    });
    lineChart.draw(table, LINE_CHART_OPTIONS);
    setRightContent("");
  }

  /**
   * Draw a bar chart illustrating the running times of each step in a given
   * build for a given builder.
   * @param {string} builder The builder whose build should be displayed.
   * @param {string} revision The revision of the build to display.
   * @param {number} viewWindowMax The width of the viewing window. This is
   *     provided instead of being determined from the data so that each bar
   *     graph can be displayed with the same scale.
   * @param {object} data Dictionary containing builds for various builders,
   *     indexed by commit hash.
   */
  function drawBarChart(builder, revision, viewWindowMax, data) {
    var table = new google.visualization.DataTable();
    table.addColumn("string", "Step");
    table.addColumn("number", "Time");
    table.addColumn({"type": "string", "role": "tooltip", "p": {"html": true}});
    var buildData = data[revision][builder];
    for (var stepIdx = 0; stepIdx < buildData.getSteps().length; stepIdx++) {
      var step = buildData.getSteps()[stepIdx];
      var stepName = step.getName();
      var time = step.getElapsedTime();
      var stdio = step.getStdio();
      var result = step.getResult();
      var percent = time / buildData.getElapsedTime() * 100.0;
      table.addRow();
      table.setValue(stepIdx, 0, stepName);
      table.setValue(stepIdx, 1, time);
      var tooltip = "<div style=\"font-family:Arial;font-size:14px;"
                  + "padding:10px;\">" + stepName;
      if (result != 0) {
        tooltip += " <span style=\"background-color:red;\">Failed</span>";
      }
      tooltip += "<br/>" + formatTime(time) + " (" + percent.toFixed(2)
              + "%)<br/>Log: <a href=\"" + stdio
              + "\" target=\"_blank\">stdout</a></div>";
      table.setFormattedValue(stepIdx, 2, tooltip);
    }

    // Instantiate and draw our chart, passing in some options.
    var barChart = new google.visualization.BarChart(
        document.getElementById("bar_chart_div"));
    var options = BAR_CHART_OPTIONS;
    options["title"] = builder + ": Build #" + buildData.getNumber() + " (" +
        buildData.getRevision() + ")";
    options["hAxis"]["viewWindow"] = {"max": viewWindowMax};
    barChart.draw(table, BAR_CHART_OPTIONS);
  }

  /**
   * Callback function to use when the selected items of the listbox have
   * changed. This causes data to be loaded for the selected builders and charts
   * to be created for that data.
   */
  function selectBuilders() {
    if (!selectedMaster) {
      console.warn("selectBuilders: No master selected!");
      return;
    }
    loadStart = new Date().getTime();
    var displayBuilders = [];
    var msg = "<p style=\"font-size:0.8em;\">Loading builds for builders:<ul>";
    var menu = document.getElementById("builder_menu");
    for (var i = 0; i < menu.options.length; i++) {
      if (menu.options[i].selected) {
        var builder = menu.options[i].text;
        if (displayBuilders.indexOf(builder) == -1) {
          displayBuilders.push(builder);
          msg += "<li style=\"font-size:0.8em;\">" + builder;
        }
      }
    }
    msg += "</ul></p>";
    clearCharts();
    setMessage(msg);
    var data = {};

    var revsToLoad = [];
    var buildsToLoad = document.getElementById("builds_to_load").value;
    var buildersToLoad = Array.prototype.slice.call(displayBuilders);
    for (var i = 0; i < displayBuilders.length; i++) {
      var builder = displayBuilders[i];
      var builderObj = builderData[builder];
      builderObj.loadBuilds(buildsToLoad, function(builder, dataForBuilder) {
        for (var buildNum in dataForBuilder) {
          var rev = dataForBuilder[buildNum].getRevision();
          if (revsToLoad.indexOf(rev) == -1) {
            revsToLoad.push(rev);
          }
          if (!data[rev]) {
            data[rev] = {};
          }
          data[rev][builder] = dataForBuilder[buildNum];
        }
        console.log("Got builds for " + builder);
        buildersToLoad.splice(buildersToLoad.indexOf(builder), 1);
        if (buildersToLoad.length == 0) {
          // Ensure that all revision data has been loaded, draw the chart.
          gitHistory.ensureLoaded(revsToLoad, function() {
            drawLineChart(displayBuilders, data);
          });
        }
      });
    }
  }

  /**
   * Callback function called when the selected build master has changed. Loads
   * the builders for the master in the master_menu dropdown.
   */
  function selectMaster() {
    selectedMaster = new skiaTools.Master(
        document.getElementById("master_menu").value);
    setMessage("Loading builders for " + selectedMaster.getName() +
               " master...");
    selectedMaster.loadBuilders(function(builders) {
      builderData = {};
      for (var builderNum = 0; builderNum < builders.length; builderNum++) {
        var builder = builders[builderNum];
        builderData[builder.getName()] = builder;
      }
      skiaTools.populateMenu("builder_menu", Object.keys(builderData));
      setMessage("Loaded builders.");
      setMessage("Select one or more builders.");
    });
  }

  /**
   * Callback function to use on page load. This causes the high-level builder
   * data to be loaded and the builder menu populated.
   */
  function init() {
    setMessage("Loading masters...");
    document.getElementById("builds_to_load").value = DEFAULT_BUILDS_TO_LOAD;
    skiaTools.loadMasterList(function(masters) {
      skiaTools.populateMenu("master_menu", masters);
      document.getElementById("master_menu").selectedIndex = -1;
      setMessage("Loaded masters.");
      setMessage("Please select a build master.");
    });
  }
  </script>
  </head>
  <body>
    <div id="heading" style="font-size:2.5em; text-align:center; height:7%;">
      Skia Buildbots Self-Analysis
    </div>
    <div id="main_content_area" style="width:100%; height:90%; padding:0px; margin:0px;">
      <div id="builder_menu_div" style="float:left; width:18%; height:100%; padding:0px; margin:0px;">
        <div style="width:100%;">
          <div style="float:left; width:50%;">
            Master:<br/>
            <select id="master_menu" onChange="selectMaster();">
              <option value="" noselect></option>
            </select>
          </div>
          <div>
            <nobr>Builds to load:</nobr><br/>
            <input type="text" id="builds_to_load" value="" />
          </div>
        </div>
        <div>
          Builders:<br/>
          <select id="builder_menu" multiple="multiple"
              style="width:100%; height:90%; margin:0px; padding:0px;">
              </select>
          <br/>
          <input type="button" onClick="selectBuilders()"
              value="Update Selection"/>
        </div>
      </div>
      <div id="charts_div" style="float:left; width:67%; padding:0px; margin:0px">
        <div id="logging_div" style="width:100%; padding:0px; margin:0px"></div>
        <div id="line_chart_div" style="width:100%; height: 40%; padding:0px; margin:0px"></div>
        <div id="line_chart_range_filter_div" style="width:100%; height: 10%; padding:0px; margin:0px"></div>
        <div id="bar_chart_div" style="width:100%; height: 50%; padding:0px; margin:0px"></div>
      </div>
      <div id="right_content_div" style="float:right; width:15%; height:100%"></div>
    </div>
  </body>
</html>
