Merge lp:~huwshimi/launchpad/ajax-time into lp:launchpad

Proposed by Huw Wilkins
Status: Merged
Approved by: Robert Collins
Approved revision: no longer in the source branch.
Merged at revision: 12699
Proposed branch: lp:~huwshimi/launchpad/ajax-time
Merge into: lp:launchpad
Diff against target: 183 lines (+132/-4)
4 files modified
lib/canonical/launchpad/icing/style-3-0.css (+38/-2)
lib/canonical/launchpad/templates/launchpad-loginstatus.pt (+7/-1)
lib/lp/app/javascript/ajax_log.js (+85/-0)
lib/lp/app/templates/base-layout.pt (+2/-1)
To merge this branch: bzr merge lp:~huwshimi/launchpad/ajax-time
Reviewer Review Type Date Requested Status
Robert Collins (community) Approve
William Grant code* Approve
Review via email: mp+55257@code.launchpad.net

Commit message

[r=lifeless,wgrant][no-qa] Added a visible log of all AJAX events.

Description of the change

We want to expose the time AJAX events take. This branch adds a visible log of all AJAX events to the user logout area. It exposes time taken, the internal AJAX event id, HTTP status and OOPS ID (if applicable).

The log also highlights if the AJAX event takes more than 1 second.

A screencast can be found here: http://people.canonical.com/~huwshimi/ajax_time_log.ogv

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) wrote :

Looks really nice, but a few comments:

 - That JS should be somewhere other than the template. Probably in a new file in lib/lp/app/javascript.
 - The spacing around the new link is also a little off... it might be best to just remove the • from the render time.
 - You construct HTML in JS with string concatenation. While the values that you're including should always be safe, I'd prefer if you constructed a node from a literal string and injected the text using YUI/DOM methods.
 - Could the click handler use toggleClass instead of add/removeClass?

review: Needs Fixing (code*)
Revision history for this message
Huw Wilkins (huwshimi) wrote :

> - That JS should be somewhere other than the template. Probably in a new file
> in lib/lp/app/javascript.

Done.

> - The spacing around the new link is also a little off... it might be best to
> just remove the • from the render time.

Fixed. Not great, but better.

> - You construct HTML in JS with string concatenation. While the values that
> you're including should always be safe, I'd prefer if you constructed a node
> from a literal string and injected the text using YUI/DOM methods.

Done.

> - Could the click handler use toggleClass instead of add/removeClass?

Absolutely. Thanks for educating me.

Revision history for this message
William Grant (wgrant) wrote :

Looks much better, thanks. A couple of remaining niggles:

 - Can you merge the two visible_render_time sections in base-layout.pt?
 - I think your JS XHTML construction could be a little cleaner still. I've pushed up some suggestions to lp:~wgrant/launchpad/ajax-time.

review: Approve (code*)
Revision history for this message
Huw Wilkins (huwshimi) wrote :

> - Can you merge the two visible_render_time sections in base-layout.pt?
> - I think your JS XHTML construction could be a little cleaner still. I've
> pushed up some suggestions to lp:~wgrant/launchpad/ajax-time.

Done and done.

Revision history for this message
Robert Collins (lifeless) wrote :

/* Maximum amount of time we want AJAX requests to take, in seconds.

-> perhaps 'requests slower than this are marked as 'slow''. Also suggest s/MAX/OK/ or similar - its not a cap on the duration the request takes, but a threshold for reporting.

This is kindof trivial, but likely to confuse, I think.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/icing/style-3-0.css'
2--- lib/canonical/launchpad/icing/style-3-0.css 2011-03-29 07:24:43 +0000
3+++ lib/canonical/launchpad/icing/style-3-0.css 2011-03-30 06:26:31 +0000
4@@ -1102,7 +1102,7 @@
5 font-size: 12px;
6 text-decoration: underline;
7 }
8-.unseen {
9+.unseen, .hidden {
10 display: none;
11 }
12 .invisible-link {
13@@ -1169,10 +1169,46 @@
14 }
15 #rendertime {
16 float: left;
17- margin: 0.2em 1.2em 0 0;
18+ margin: 0.1em 1.2em 0 0;
19 color: #666;
20 font-size: 10px;
21 }
22+#ajax-time {
23+ float: left;
24+ margin: 0 1.2em 0 0.2em;
25+ position: relative;
26+ }
27+#ajax-time-list {
28+ position: absolute;
29+ z-index: 10;
30+ top: 20px;
31+ right: 0;
32+ width: 200px;
33+ background-color: #f2f2f2;
34+ border: 2px solid #fff;
35+ -moz-box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
36+ -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
37+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
38+ -webkit-border-radius: 4px;
39+ -moz-border-radius: 4px;
40+ border-radius: 4px;
41+ }
42+#ajax-time-list li {
43+ border-bottom: 1px solid #e0e0e0;
44+ padding: 3px 5px;
45+ }
46+#ajax-time-list li:last-child {
47+ border-bottom: none;
48+ }
49+#ajax-time-list li span {
50+ color: #999;
51+ font-size: 11px;
52+ display: block;
53+ }
54+#ajax-time-list strong.warning {
55+ color: #f00;
56+ background-color: transparent;
57+ }
58 div.watermark-apps-portlet {
59 clear: both;
60 margin-bottom: .5em;
61
62=== modified file 'lib/canonical/launchpad/templates/launchpad-loginstatus.pt'
63--- lib/canonical/launchpad/templates/launchpad-loginstatus.pt 2011-02-07 07:39:36 +0000
64+++ lib/canonical/launchpad/templates/launchpad-loginstatus.pt 2011-03-30 06:26:31 +0000
65@@ -9,7 +9,13 @@
66 <div id="logincontrol" tal:condition="view/logged_in">
67 <form action="+logout" method="post">
68 <input type="hidden" name="loggingout" value="1" />
69- <div id="rendertime" tal:condition="request/features/visible_render_time">Loading... &bull;</div>
70+ <div id="rendertime" tal:condition="request/features/visible_render_time">Loading...</div>
71+ <div id="ajax-time" tal:condition="request/features/visible_render_time">
72+ <a href="" class="js-action">AJAX Log &darr;</a>
73+ <ul id="ajax-time-list" class="hidden">
74+ <li class="no-events">No AJAX events detected</li>
75+ </ul>
76+ </div>
77 <a tal:replace="structure request/lp:person/fmt:name_link" /> &bull;
78 <input type="submit" name="logout" value="Log Out" />
79 </form>
80
81=== added file 'lib/lp/app/javascript/ajax_log.js'
82--- lib/lp/app/javascript/ajax_log.js 1970-01-01 00:00:00 +0000
83+++ lib/lp/app/javascript/ajax_log.js 2011-03-30 06:26:31 +0000
84@@ -0,0 +1,85 @@
85+/* Log time taken for AJAX requests.
86+*/
87+function start_ajax_logging() {
88+ /* Requests slower than this are marked as slow. Value in seconds.
89+ */
90+ var AJAX_OK_TIME = 1;
91+
92+ LPS.use('node', 'lazr.anim', function(Y) {
93+ Y.on('contentready', function() {
94+ var node = Y.one('#ajax-time-list');
95+ var ajax_request_times = {};
96+ var ajax_menu_animating = false;
97+ var flash_menu = Y.lazr.anim.green_flash({node:'#ajax-time'});
98+ flash_menu.on('end', function() {
99+ ajax_menu_animating = false;
100+ });
101+ /* When an AJAX event starts, record the time.
102+ */
103+ Y.on('io:start', function(transactionid) {
104+ var now = new Date();
105+ ajax_request_times[transactionid] = now;
106+ });
107+ /* When an AJAX event finishes add it to the log.
108+ */
109+ Y.on('io:complete', function(transactionid, arguments) {
110+ /* The AJAX event has finished so record the time.
111+ */
112+ var finish_time = new Date();
113+ /* Remove the initial message in the log.
114+ */
115+ Y.all('#ajax-time-list li.no-events').remove();
116+ if (ajax_request_times[transactionid]) {
117+ var start_time = ajax_request_times[transactionid];
118+ /* The time take for the AJAX event, in seconds.
119+ */
120+ var time_taken = (finish_time - start_time)/1000;
121+ var log_node = Y.Node.create(
122+ '<li>Time: <strong></strong><span></span></li>');
123+ log_node.addClass('transaction-' + transactionid);
124+ log_node.one('strong').set(
125+ 'text', time_taken.toFixed(2) + ' seconds');
126+ /* If the AJAX event takes longer than AJAX_OK_TIME
127+ then add a warning.
128+ */
129+ if (time_taken > AJAX_OK_TIME) {
130+ log_node.one('strong').addClass('warning');
131+ }
132+ log_node.one('span').set(
133+ 'text',
134+ 'ID: ' + transactionid +
135+ ', status: ' + arguments.status +
136+ ' (' + arguments.statusText + ')');
137+ var oops = arguments.getResponseHeader('X-Lazr-OopsId');
138+ if (oops) {
139+ var oops_node = Y.Node.create('<a/>');
140+ oops_node.setAttribute(
141+ 'href', 'http://pad.lv/' + oops);
142+ oops_node.set('text', oops);
143+ log_node.one('span').append(', OOPS ID:&nbsp;');
144+ log_node.one('span').append(oops_node);
145+ }
146+ node.prepend(log_node);
147+ /* Highlight the new entry in the log.
148+ */
149+ Y.lazr.anim.green_flash({
150+ node: '#ajax-time-list li.transaction-'+transactionid
151+ }).run();
152+ /* Signify a new entry has been added to the log.
153+ */
154+ if (ajax_menu_animating == false) {
155+ flash_menu.run();
156+ ajax_menu_animating = true;
157+ }
158+ }
159+ });
160+
161+ /* Open/close the log.
162+ */
163+ Y.on('click', function(e) {
164+ e.halt();
165+ Y.one('#ajax-time-list').toggleClass('hidden');
166+ }, '#ajax-time a');
167+ }, '#ajax-time');
168+ });
169+}
170
171=== modified file 'lib/lp/app/templates/base-layout.pt'
172--- lib/lp/app/templates/base-layout.pt 2011-02-28 06:28:16 +0000
173+++ lib/lp/app/templates/base-layout.pt 2011-03-30 06:26:31 +0000
174@@ -191,7 +191,8 @@
175 tal:condition="request/features/visible_render_time"
176 define="render_time modules/canonical.launchpad.webapp.adapter/summarize_requests;"
177 replace='structure string:&lt;script type="text/javascript"&gt;
178- var render_time = "${render_time} &amp;bull;";
179+ start_ajax_logging();
180+ var render_time = "${render_time}";
181 LPS.use("node", function(Y) {
182 Y.on("domready", function() {
183 var node = Y.one("#rendertime");