Add v3 UI to perf dashboard
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 Dec 2015 05:19:08 +0000 (05:19 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 Dec 2015 05:19:08 +0000 (05:19 +0000)
commit40f76476cb1fda3e795ffd27c952aaf481c4b23f
tree6a339d5a1aa81c4aeb51de97a3666a654e82ff3e
parenta82e779ad65bd524e4912a837fac731f5aaedaeb
Add v3 UI to perf dashboard
https://bugs.webkit.org/show_bug.cgi?id=152311

Reviewed by Chris Dumez.

Add the third iteration of the perf dashboard UI. UI for viewing and modifying analysis tasks is coming soon.
The v3 UI is focused on speed, and removes all third-party script dependencies including jQuery, d3, and Ember.
Both the DOM-based UI and graphing are implemented manually.

The entire app is structured using new component library implemented in components/base.js. Each component is
an instance of a subclass of ComponentBase which owns a single DOM element. Each subclass may supply static
methods named htmlTemplate and cssTemplate as the template for a component instance. ComponentBase automatically
clones the templates inside the associated element (or its shadow root on the supported browsers). Each subclass
must supply a method called "render()" which constructs and updates the DOM as needed.

There is a special component called Page, which represents an entire page. Each Page is opened by PageRouter's
"route()" function. Each subclass of Page supplies "open()" for initialization and "updateFromSerializedState()"
for a hash URL transition.

The key feature of the v3 UI is the split of time series into chunks called clusters (see r194120). On an internal
instance of the dashboard, the v2 UI downloads 27MB of data whereas the same page loads only 3MB of data in the v3.
The key logic for fetching time series in chunks is implemented by MeasurementSet in /v3/models/measurement-set.js.
We first fetch the cached primary cluster (the cluster that contains the newest data) at:
/data/measurement-set-<platform-id>-<metric-id>.json

If that's outdated according to lastModified in manifest.json, then we immediately re-fetch the primary cluster at:
/api/measurement-set/?platform=<platform-id>&metric=<metric-id>

Once the up-to-date primary cluster is fetched, we fetch all "secondary" clusters. For each cluster being fetched,
including the primary, we invoke registered callbacks.

In addition, the v3 UI reduces the initial page load time by loading a single bundled JS file generated by
tools/bundle-v3-scripts.py. index.html has a fallback to load all 44 JS files individually during development.

* public/api/analysis-tasks.php:
(fetch_and_push_bugs_to_tasks): Added the code to fetch start and end run times. This is necessary in V3 UI
because no longer fetch the entire time series. See r194120 for the new measurement set JSON API.
(format_task): Compute the category of an analysis task based on "result" value. This will be re-vamped once
I add the UI for the analysis task page in v3.

* public/include/json-header.php:
(require_format): CamelCase the name.
(require_match_one_of_values): Ditto.
(validate_arguments): Renamed from require_existence_of and used in measurement-set.php landed in r194120.

* public/v3: Added.
* public/v3/components: Added.

* public/v3/components/base.js: Added.
(ComponentBase): The base component class.
(ComponentBase.prototype.element): Returns the DOM element associated with the DOM element.
(ComponentBase.prototype.content): Returns the shadow root if one exists and the associated element otherwise.
(ComponentBase.prototype.render): To be implemented by a subclass.
(ComponentBase.prototype.renderReplace): A helper function to "render" DOM contents.
(ComponentBase.prototype._constructShadowTree): Called inside the constructor to instantiate the templates.
(ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Instantiates components referred by
its element name inside the instantiated content.
(ComponentBase.isElementInViewport): A helper function. Returns true if the element is in the viewport and it has
non-zero width and height.
(ComponentBase.defineElement): Defines a custom element that can be automatically instantiated from htmlTemplate.
(ComponentBase.createElement): A helper function to create DOM tree to be used in "render()" method.
(ComponentBase._addContentToElement): A helper for "createElement".
(ComponentBase.createLink): A helper function to create a hyperlink or another clickable element (via callback).
(ComponentBase.createActionHandler): A helper function to create an event listener that prevents the default action
and stops the event propagation.

* public/v3/components/button-base.js: Added.

* public/v3/components/chart-status-view.js: Added.
(ChartStatusView): A component that reports the current status of time-series-chart. It's subclasses by
ChartPaneStatusView to provide additional information in the charts page's panes.

* public/v3/components/close-button.js: Added.
(CloseButton):
* public/v3/components/commit-log-viewer.js: Added.
(CommitLogViewer): A component that lists commit revisions along with commit messages for a range of data points.

* public/v3/components/interactive-time-series-chart.js: Added.
(InteractiveTimeSeriesChart): A subclass of InteractiveTimeSeriesChart with interactivity (selection & indicator).
Selection and indicator are mutually exclusive.

* public/v3/components/pane-selector.js: Added.
(PaneSelector): A component for selecting (platform, metric) pair to add in the charts page.

* public/v3/components/spinner-icon.js: Added.

* public/v3/components/time-series-chart.js: Added.
(TimeSeriesChart): A canvas-based chart component without interactivity. It takes a source list and options as
the constructor arguments. A source list is a list of measurement sets (measurement-set.js) with drawing options.
This component fetches data via MeasurementSet.fetchBetween inside TimeSeriesChart.prototype.setDomain and
progressively updates the charts as more data arrives. The canvas is updated on animation frame via rAF and all
layout and rendering metrics are lazily computed in _layout. In addition, this component samples data before
rendering the chart when there are more data points per pixel in _ensureSampledTimeSeries.

* public/v3/index.html: Added. Loads bundled-scripts.js if it exists, or individual script files otherwise.

* public/v3/instrumentation.js: Added. This class is used to gather runtime statistics of v3 UI. (It measures
the performance of the perf dashboard UI).

* public/v3/main.js: Added. Bootstraps the app.
(main):
(fetchManifest):

* public/v3/models: Added.
* public/v3/models/analysis-task.js: Added.
* public/v3/models/bug-tracker.js: Added.
* public/v3/models/bug.js: Added.
* public/v3/models/builder.js: Added.
* public/v3/models/commit-log.js: Added.
* public/v3/models/data-model.js: Added.
(DataModelObject): The base class for various data objects that correspond to database tables. It supplies static
hash map to find entries by id as well as other keys.
(LabeledObject): A subclass of DataModelObject with the capability to find an object via its name.

* public/v3/models/measurement-cluster.js: Added.
(MeasurementCluster): Represents a single cluster or a chunk of data in a measurement set.

* public/v3/models/measurement-set.js: Added.
(MeasurementSet): Represents a measurement set.
(MeasurementSet.findSet): Returns the singleton set given (metric, platform). We use singleton to avoid issuing
multiple HTTP requests for the same JSON when there are multiple TimeSeriesChart that show the same graph (e.g. on
charts page with overview and main charts).
(MeasurementSet.prototype.findClusters): Finds the list of clusters to fetch in a given time range.
(MeasurementSet.prototype.fetchBetween): Fetch clusters for a given time range and calls callback whenever new data
arrives. The number of callbacks depends on the how many clusters need to be newly fetched.
(MeasurementSet.prototype._fetchSecondaryClusters): Fetches non-primary (non-latest) clusters.
(MeasurementSet.prototype._fetch): Issues a HTTP request to fetch a cluster.
(MeasurementSet.prototype._didFetchJSON): Called when a cluster is fetched.
(MeasurementSet.prototype._failedToFetchJSON): Called when the fetching of a cluster has failed.
(MeasurementSet.prototype._invokeCallbacks): Invokes callbacks upon an approval of a new cluster.
(MeasurementSet.prototype._addFetchedCluster): Adds the newly fetched cluster in the order.
(MeasurementSet.prototype.fetchedTimeSeries): Returns a time series that contains data from all clusters that have
been fetched.
(TimeSeries.prototype.findById): Additions to TimeSeries defined in /v2/data.js.
(TimeSeries.prototype.dataBetweenPoints): Ditto.
(TimeSeries.prototype.firstPoint): Ditto.

* public/v3/models/metric.js: Added.
* public/v3/models/platform.js: Added.
* public/v3/models/repository.js: Added.
* public/v3/models/test.js: Added.

* public/v3/pages: Added.
* public/v3/pages/analysis-category-page.js: Added. The "Analysis" page that lists the analysis tasks.
* public/v3/pages/analysis-category-toolbar.js: Added. The toolbar to filter analysis tasks based on its category
(unconfirmed, bisecting, identified, closed) and a keyword.

* public/v3/pages/analysis-task-page.js: Added. Not implemented yet. It just has the hyperlink to the v2  UI.

* public/v3/pages/chart-pane-status-view.js: Added.
(ChartPaneStatusView): A subclass of ChartStatusView used in the charts page. In addition to the current value,
comparison to baseline/target, it shows the list of repository revisions (e.g. WebKit revision, OS version).

* public/v3/pages/chart-pane.js: Added.
(ChartPane): A component a pane in the charts page. Each pane has the overview chart and the main chart. The zooming
is synced across all panes in the charts page.

* public/v3/pages/charts-page.js: Added. Charts page.
* public/v3/pages/charts-toolbar.js: Added. The toolbar to set the number of days to show. This affects the overview
chart's domain in each pane.

* public/v3/pages/create-analysis-task-page.js: Added.
(CreateAnalysisTaskPage): A page that gets shown momentarily while creating a new analysis task.

* public/v3/pages/dashboard-page.js: Added. A dashboard page.
* public/v3/pages/dashboard-toolbar.js: Added. Its toolbar with buttons to select the number of days to show.
* public/v3/pages/domain-control-toolbar.js: Added. An abstract superclass of charts and dashboard toolbars.

* public/v3/pages/heading.js: Added. A component for displaying the header and toolbar, if exists, on each page.
* public/v3/pages/page-router.js: Added. This class is responsible for updating the URL hashes as well as opening
and updating each page when the hash changes (via back/forward navigation).
* public/v3/pages/page-with-charts.js: Added. An abstract subclass of page used by dashboards and charts page.
Supplies helper functions for creating TimeSeriesChart options.
* public/v3/pages/page-with-heading.js: Added. An abstract subclass of page that uses the heading component.
* public/v3/pages/page.js: Added. The Page component.
* public/v3/pages/toolbar.js: Added. An abstract toolbar component.

* public/v3/remote.js: Added.
(getJSON): Fetches JSON from the remote server.
(getJSONWithStatus): Ditto. Rejects the response if the status is not "OK".
(PrivilegedAPI.sendRequest): Posts a HTTP request to a privileged API in /privileged-api/.
(PrivilegedAPI.requestCSRFToken): Creates a new CSRF token to request a privileged API post.

* tools/bundle-v3-scripts.py: Added.
(main): Bundles js files together and minifies them by jsmin.py for the v3 UI. Without this script, we're forced to
download 44 JS files or making each JS file contain multiple classes.

* tools/jsmin.py: Copied from WebInspector / JavaScriptCore code.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@194130 268f45cc-cd09-0410-ab3c-d52691b4dbfc
47 files changed:
Websites/perf.webkit.org/ChangeLog
Websites/perf.webkit.org/public/api/analysis-tasks.php
Websites/perf.webkit.org/public/include/json-header.php
Websites/perf.webkit.org/public/v3/components/base.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/components/button-base.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/components/chart-status-view.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/components/close-button.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/components/commit-log-viewer.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/components/interactive-time-series-chart.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/components/pane-selector.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/components/spinner-icon.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/components/time-series-chart.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/index.html [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/instrumentation.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/main.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/models/analysis-task.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/models/bug-tracker.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/models/bug.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/models/builder.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/models/commit-log.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/models/data-model.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/models/measurement-cluster.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/models/measurement-set.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/models/metric.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/models/platform.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/models/repository.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/models/test.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/analysis-category-page.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/analysis-category-toolbar.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/analysis-task-page.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/chart-pane-status-view.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/chart-pane.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/charts-page.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/charts-toolbar.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/create-analysis-task-page.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/dashboard-page.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/dashboard-toolbar.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/domain-control-toolbar.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/heading.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/page-router.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/page-with-charts.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/page-with-heading.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/page.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/pages/toolbar.js [new file with mode: 0644]
Websites/perf.webkit.org/public/v3/remote.js [new file with mode: 0644]
Websites/perf.webkit.org/tools/bundle-v3-scripts.py [new file with mode: 0644]
Websites/perf.webkit.org/tools/jsmin.py [new file with mode: 0644]