diff --git a/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.html b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.html
new file mode 100644
index 0000000000..76536555f5
--- /dev/null
+++ b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js
new file mode 100644
index 0000000000..c7180a74e0
--- /dev/null
+++ b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js
@@ -0,0 +1,95 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+(function() {
+ 'use strict';
+
+ var APP_STARTED = 'App Started';
+ var PAGE_LOADED = 'Page Loaded';
+ var TIMING_EVENT = 'timing-report';
+ var DEFAULT_CATEGORY = 'UI Latency';
+ var DEFAULT_TYPE = 'timing';
+
+ Polymer({
+ is: 'gr-reporting',
+
+ properties: {
+ _baselines: {
+ type: Array,
+ value: function() { return {}; },
+ }
+ },
+
+ get performanceTiming() {
+ return window.performance.timing;
+ },
+
+ now: function() {
+ return Math.round(10 * window.performance.now()) / 10;
+ },
+
+ reporter: function(type, category, eventName, eventValue) {
+ eventValue = eventValue;
+ var detail = {
+ type: type,
+ category: category,
+ name: eventName,
+ value: eventValue,
+ };
+ document.dispatchEvent(
+ new CustomEvent(TIMING_EVENT, {detail: detail}));
+ console.log(eventName + ': ' + eventValue);
+ },
+
+ /**
+ * User-perceived app start time, should be reported when the app is ready.
+ */
+ appStarted: function() {
+ var startTime =
+ new Date().getTime() - this.performanceTiming.navigationStart;
+ this.reporter(
+ DEFAULT_TYPE, DEFAULT_CATEGORY, APP_STARTED, startTime);
+ },
+
+ /**
+ * Page load time, should be reported at any time after navigation.
+ */
+ pageLoaded: function() {
+ if (this.performanceTiming.loadEventEnd === 0) {
+ console.error('pageLoaded should be called after window.onload');
+ this.async(this.pageLoaded, 100);
+ } else {
+ var loadTime = this.performanceTiming.loadEventEnd -
+ this.performanceTiming.navigationStart;
+ this.reporter(DEFAULT_TYPE, DEFAULT_CATEGORY, PAGE_LOADED, loadTime);
+ }
+ },
+
+ /**
+ * Reset named timer.
+ */
+ time: function(name) {
+ this._baselines[name] = this.now();
+ },
+
+ /**
+ * Finish named timer and report it to server.
+ */
+ timeEnd: function(name) {
+ var baseTime = this._baselines[name] || 0;
+ var time = this.now() - baseTime;
+ this.reporter(DEFAULT_TYPE, DEFAULT_CATEGORY, name, time);
+ delete this._baselines[name];
+ },
+ });
+})();
diff --git a/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting_test.html b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting_test.html
new file mode 100644
index 0000000000..e9226b8865
--- /dev/null
+++ b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting_test.html
@@ -0,0 +1,93 @@
+
+
+
+
+
gr-reporting
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.js b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
index d11d438266..8441372426 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.js
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
@@ -18,8 +18,12 @@
// custom element having the id "app", but it is made explicit here.
var app = document.querySelector('#app');
var restAPI = document.createElement('gr-rest-api-interface');
+ var reporting = document.createElement('gr-reporting');
window.addEventListener('WebComponentsReady', function() {
+ reporting.timeEnd('WebComponentsReady');
+ reporting.pageLoaded();
+
// Middleware
page(function(ctx, next) {
document.body.scrollTop = 0;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html
index ec19a2df45..18c06025f8 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html
@@ -14,10 +14,12 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
+
+