PluginProbe
Code Profiler – WordPress Performance Profiling and Debugging Made Easy / 1.4.1
Code Profiler – WordPress Performance Profiling and Debugging Made Easy v1.4.1
1.9.5 1.9.4 1.9.3 trunk 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.6 1.6.1 1.6.10 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 All 40 releases
code-profiler / static / code-profiler.js

code-profiler.js in Code Profiler – WordPress Performance Profiling and Debugging Made Easy 1.4.1, at static/code-profiler.js

671 lines 16.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /*
2 +=====================================================================+
3 | ____ _ ____ __ _ _ |
4 | / ___|___ __| | ___ | _ \ _ __ ___ / _(_) | ___ _ __ |
5 | | | / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__| |
6 | | |__| (_) | (_| | __/ | __/| | | (_) | _| | | __/ | |
7 | \____\___/ \__,_|\___| |_| |_| \___/|_| |_|_|\___|_| |
8 | |
9 | (c) Jerome Bruandet ~ https://code-profiler.com/ |
10 +=====================================================================+
11 */
12
13 // =====================================================================
14 // Generic stuff
15
16 // TipTip tooltip
17 jQuery( document ).ready(function( $ ) {
18 'use strict';
19 $( '.code-profiler-tip' ).tipTip( {
20 'attribute': 'data-tip',
21 'fadeIn': 50,
22 'fadeOut': 50,
23 'delay': 100,
24 'maxWidth' : '350px'
25 });
26
27 // We remove the '&action=delete_profiles...' query string because
28 // if the user reloaded the page that would throw an error:
29 var url = window.location.href;
30 window.history.replaceState({},
31 document.title,
32 url.replace( /&action=delete_profiles&.+/, '' )
33 );
34
35 });
36
37 // Append/clear the search query to/from the query string
38 function cpjs_search_query() {
39
40 'use strict';
41 var query;
42 if ( jQuery('#search_id-search-input').val().length > 0 ) {
43 query = '&s=' + jQuery('#search_id-search-input').val();
44 // Case sensitivity
45 if ( jQuery('#case-search-input').is(':checked') === true ) {
46 query += '&c=1';
47 }
48 jQuery("#profile-form").attr('action', jQuery("#profile-form").attr('action')+ query );
49
50 } else {
51 jQuery("#profile-form").attr('action','' );
52 var url = window.location.href;
53 window.history.replaceState({},
54 document.title,
55 url.replace( /&s=[^&$]+/, '' )
56 );
57 var url = window.location.href;
58 window.history.replaceState({},
59 document.title,
60 url.replace( /&c=1/, '' )
61 );
62 }
63 }
64
65 // =====================================================================
66 // Summary page
67
68 function cpjs_front_or_backend( item ) {
69 'use strict';
70 // Enable/disable frontend/backend select box
71 // depending on user's choice
72 if ( item == 1 ) {
73 jQuery('#p-frontend').show();
74 jQuery('#p-backend').hide();
75 jQuery('#p-custom').hide();
76 jQuery('#id-frontend').prop('disabled', false);
77 jQuery('#id-frontend').focus();
78 jQuery('#id-backend').prop('disabled', true);
79 jQuery('#id-custom').prop('disabled', true);
80 jQuery('#user-unauthenticated').prop('disabled', false);
81 } else if ( item == 2 ) {
82 jQuery('#p-backend').show();
83 jQuery('#p-frontend').hide();
84 jQuery('#p-custom').hide();
85 jQuery('#id-backend').prop('disabled', false);
86 jQuery('#id-backend').focus();
87 jQuery('#id-frontend').prop('disabled', true);
88 jQuery('#id-custom').prop('disabled', true);
89 jQuery('#user-unauthenticated').prop('disabled', true);
90 jQuery('#user-authenticated').prop('checked', true)
91 } else {
92 jQuery('#p-custom').show();
93 jQuery('#p-frontend').hide();
94 jQuery('#p-backend').hide();
95 jQuery('#id-custom').prop('disabled', false);
96 jQuery('#id-custom').focus();
97 jQuery('#id-backend').prop('disabled', true);
98 jQuery('#id-frontend').prop('disabled', true);
99 jQuery('#user-unauthenticated').prop('disabled', false);
100 }
101 }
102
103 function cpjs_show_adv_settings() {
104 jQuery("#cp-advanced-settings").slideDown();
105 jQuery("#button-adv-settings").prop('disabled', true);
106 }
107
108 function cpjs_get_post( id ) {
109 if ( id == 1 ) {
110 jQuery("#post-value").prop('disabled', false);
111 jQuery("#post-value").focus();
112 } else {
113 jQuery("#post-value").prop('disabled', true);
114 }
115 }
116
117 // =====================================================================
118 // Log page: filter and delete the log.
119
120 function cpjs_filter_log() {
121 'use strict';
122 // Create bitmask
123 var bitmask = 0;
124 if ( document.cplogform.info.checked == true ) { bitmask += 1; }
125 if ( document.cplogform.warn.checked == true ) { bitmask += 2; }
126 if ( document.cplogform.error.checked == true ) { bitmask += 4; }
127
128 // Clear the textarea
129 document.cplogform.cptxtlog.value = '';
130
131 // Browser through our array and return only selected verbosity
132 var cp_count = 0;
133 var i = 0;
134 for ( i = 0; i < cplog_array.length; ++i ) {
135 var line = decodeURIComponent( cplog_array[i] );
136 var line_array = line.split( '~~', 2 );
137 if ( line_array[0] & bitmask ) {
138 document.cplogform.cptxtlog.value += line_array[1];
139 ++cp_count;
140 }
141 }
142 if ( cp_count == 0 ) {
143 document.cplogform.cptxtlog.value = '\n > ' + cpi18n.empty_log;
144 }
145 }
146
147 function cpjs_delete_log() {
148 'use strict';
149 if ( confirm( cpi18n.delete_log ) ) {
150 return true;
151 }
152 return false;
153 }
154 // =====================================================================
155 // AJAX call to start the profiler.
156
157 function cpjs_start_profiler() {
158 'use strict';
159 // Get the nonce
160 var cp_nonce = jQuery('#cp_nonce').val();
161 if ( cp_nonce == '' ) {
162 alert( cpi18n.missing_nonce );
163 return;
164 }
165
166 // Get the scan type (frontend/backend)
167 var post;
168 var where = jQuery('input[name="where"]:checked').val();
169 if ( where == 'frontend' ) {
170 post = jQuery('#id-frontend').val();
171
172 } else if ( where == 'backend' ) {
173 post = jQuery('#id-backend').val();
174
175 } else if ( where == 'custom' ) {
176 post = jQuery('#id-custom').val().trim(); // Trim user input
177
178 } else {
179 alert( cpi18n.missing_frontbackend );
180 return;
181 }
182 if ( post == '' ) {
183 alert( cpi18n.missing_post );
184 return;
185 }
186
187 // Get the profile's name
188 var profile = jQuery('input[name="profile"]').val();
189 if ( profile == '' ) {
190 alert( cpi18n.missing_profilename );
191 jQuery('input[name="profile"]').focus();
192 return;
193 }
194
195 var user = jQuery('input[name="user"]:checked').val();
196 if ( user == '' ) {
197 alert( cpi18n.missing_userauth );
198 return;
199 }
200
201 var ua = jQuery('#ua-id').val();
202 if ( ua == 'undefined' ) {
203 ua = 'FireFox';
204 }
205
206 // GET or POST
207 var method = jQuery('input[name="method"]:checked').val();
208 var payload = '';
209 if ( method == 'post' ) {
210 // Payload
211 payload = jQuery('#post-value').val();
212 } else {
213 method = 'get';
214 }
215
216 var cookies = jQuery('#cp-cookies').val();
217
218 // Change buttons status and add animated image with status message
219 jQuery('#start-profile').prop('disabled', true);
220 jQuery('#cp-progress-div').slideDown();
221 jQuery('#progress-gif').slideDown();
222 jQuery('#progress-text').slideDown();
223 jQuery('#code-profiler-error').slideUp();
224 jQuery('#cp-span-progress').css('width', '30%');
225
226 var data = {
227 'action': 'codeprofiler_start_profiler',
228 'cp_nonce': cp_nonce,
229 'where': where,
230 'post': post,
231 'profile': profile,
232 'user': user,
233 'cookies': cookies,
234 'method': method,
235 'payload': payload,
236 'ua': ua
237 };
238 // Send the request via AJAX
239 jQuery.ajax( {
240 type: "POST",
241 url: ajaxurl,
242 data: data,
243 dataType: 'json',
244 success: function( response ) {
245
246 if (typeof response === 'undefined') {
247 cpjs_start_error( '<p>'+ cpi18n.unknown_error +'</p>' );
248 return;
249 }
250
251 if ( response.status != 'success' ) {
252 cpjs_start_error( '<p>'+ response.message +'</p>' );
253 return;
254 }
255
256 // ------------------------------------------------------------
257 // Inform the user we're moving to step 2
258 jQuery('#cp-span-progress').css('width', '70%');
259 jQuery('#progress-text').html( cpi18n.preparing_report );
260
261 data['action'] = 'codeprofiler_prepare_report';
262 data['microtime'] = response.microtime;
263 jQuery.ajax( {
264 type: "POST",
265 url: ajaxurl,
266 data: data,
267 dataType: 'json',
268 success: function( response ) {
269
270 if (typeof response === 'undefined') {
271 cpjs_start_error( '<p>'+ cpi18n.unknown_error +'</p>' );
272 return;
273 }
274
275 if ( response.status != 'success' ) {
276 cpjs_start_error( '<p>'+ response.message +'</p>' );
277 return;
278 }
279 var cp_uri;
280 if (response.cp_profile !== 'undefined' && response.cp_profile != '' ) {
281 cp_uri = '&cptab=profiles_list&action=view_profile&id=' + response.cp_profile + '&section=1';
282 } else {
283 cp_uri = '&cptab=profiles_list';
284 }
285
286 // All good, redirect to the Profiles List tab
287 jQuery('#cp-span-progress').css('width', '100%');
288 window.location.href = window.location.href + cp_uri;
289 return;
290
291 },
292
293 // Display non-200 HTTP response
294 error: function( xhr, status, err ) {
295 if ( err != '' ) {
296
297 if ( xhr.status != 0 ) {
298 cpjs_start_error( '<p>'+ cpi18n.http_error +' '+ xhr.status +' '+ err +'.</p>' );
299 return;
300
301 } else {
302 cpjs_start_error( '<p>'+ cpi18n.unknown_error +' '+ err +'.</p>' );
303 return;
304 }
305 }
306 return;
307 }
308 });
309 // ------------------------------------------------------------
310 },
311
312 // Display non-200 HTTP response
313 error: function( xhr, status, err ) {
314 if ( err != '' ) {
315
316 if ( xhr.status != 0 ) {
317 cpjs_start_error( '<p>'+ cpi18n.http_error +' '+ xhr.status +' '+ err +'.</p>' );
318 return;
319
320 } else {
321 cpjs_start_error( '<p>'+ cpi18n.unknown_error +' '+ err +'.</p>' );
322 return;
323 }
324 }
325 return;
326 }
327 });
328 }
329
330 // Display error
331 function cpjs_start_error( error ) {
332 'use strict';
333 jQuery('#start-profile').prop('disabled', false);
334 jQuery('#progress-gif').slideUp();
335 jQuery('#progress-text').slideUp();
336 jQuery('#cp-span-progress').css('width', '0%');
337 jQuery('#code-profiler-error').html( error );
338 jQuery('#code-profiler-error').slideDown();
339 jQuery('#cp-progress-div').slideUp();
340
341 }
342
343 // =====================================================================
344 // Profiles List page.
345
346 function cpjs_delete_profile() {
347 'use strict';
348 if ( confirm( cpi18n.delete_profile ) ) {
349 return true;
350 }
351 return false;
352 }
353
354 // =====================================================================
355 // Plugins/Theme chart.
356
357 function cpjs_plugins_chart( caxis, clabel, cdata, ctotal_time ) {
358 'use strict';
359 // Switch between vertical and horizontal bars
360 var _indexAxis = caxis;
361 document.getElementById('htov').onclick = function() {
362 if ( _indexAxis == 'x' ) {
363 _indexAxis = 'y';
364 } else {
365 _indexAxis = 'x';
366 }
367 myChart.destroy();
368 myChart = new Chart(ctx, {
369 type: 'bar',
370 options: {
371 animation: {
372 duration: 1000,
373 onComplete: function() {
374 document.getElementById('download-png-img').href = myChart.toBase64Image();
375 }
376 },
377 indexAxis: _indexAxis,
378 plugins: chartPlugins
379 },
380 plugins:[ plugin],
381 data: chartData
382 });
383 };
384
385 var ctx = document.getElementById('myChart').getContext('2d');
386
387 var chartData = {
388 labels: clabel,
389 datasets: [{
390 label: cpi18n.exec_sec_plugins,
391 backgroundColor: 'rgba(204, 0, 0, .5)',
392 borderColor: '#c00',
393 borderWidth: 2,
394 hoverBackgroundColor: '#B45252',
395 data: cdata
396 }]
397 };
398
399 const total_time = ctotal_time;
400 const footer = (tooltipItems) => {
401 var sum;
402 tooltipItems.forEach(function(tooltipItem) {
403 if ( _indexAxis == 'x' ) {
404 sum = Math.round( ( tooltipItem.parsed.y / total_time ) * 100 );
405 } else {
406 sum = Math.round( ( tooltipItem.parsed.x / total_time ) * 100 );
407 }
408 });
409 return '('+ sum + cpi18n.pc_plugins +')';
410 };
411
412 var chartPlugins = {
413 title: {
414 display: true,
415 text: cpi18n.exec_tot_plugins_1 +' (' + cpi18n.chart_total +' '+ ctotal_time +')'
416 },
417 legend: {
418 display: false
419 },
420 tooltip: {
421 borderWidth: 1,
422 borderColor: '#666',
423 displayColors: false,
424 backgroundColor: '#F5F5B5',
425 titleColor:'#666',
426 padding: 8,
427 footerColor: '#666',
428 callbacks: {
429 footer: footer,
430 labelTextColor: function(context) {
431 return '#543453';
432 }
433 }
434 }
435 }
436
437 // We want a background colour for the downloaded PNG file
438 const plugin = {
439 id: 'custom_canvas_background_color',
440 beforeDraw: (chart) => {
441 const ctx = chart.canvas.getContext('2d');
442 ctx.save();
443 ctx.globalCompositeOperation = 'destination-over';
444 ctx.fillStyle = '#f0f0f1',
445 ctx.fillRect(0, 0, chart.width, chart.height);
446 ctx.restore();
447 }
448 }
449
450 var myChart = new Chart(ctx, {
451 type: 'bar',
452 data: chartData,
453 options: {
454 animation: {
455 duration: 700,
456 onComplete: function() {
457 jQuery('#cp-footer-buttons').slideDown(200);
458 document.getElementById('download-png-img').href = myChart.toBase64Image();
459 }
460 },
461 indexAxis: _indexAxis,
462 plugins: chartPlugins
463 },
464 plugins:[plugin]
465 });
466 }
467
468 // =====================================================================
469 // File I/O chart.
470
471 function cpjs_iostats_chart( caxis, clabel, cdata, ctotal_calls ) {
472 'use strict';
473 // Switch between vertical and horizontal bars
474 var _indexAxis = caxis;
475 document.getElementById('htov').onclick = function() {
476 if ( _indexAxis == 'x' ) {
477 _indexAxis = 'y';
478 } else {
479 _indexAxis = 'x';
480 }
481 myChart.destroy();
482 myChart = new Chart(ctx, {
483 type: 'line',
484 options: {
485 animation: {
486 duration: 1000,
487 onComplete: function() {
488 document.getElementById('download-png-img').href = myChart.toBase64Image();
489 }
490 },
491 indexAxis: _indexAxis,
492 plugins: chartPlugins
493 },
494 plugins:[ plugin],
495 data: chartData
496 });
497 };
498
499 var ctx = document.getElementById('myChart').getContext('2d');
500
501 var chartData = {
502 labels: clabel,
503 datasets: [{
504 label: cpi18n.iolist_total_calls,
505 backgroundColor: 'rgba(34, 113, 177, .5)',
506 borderColor: '#2271B1',
507 borderWidth: 2,
508 hoverBackgroundColor: '#FF0000',
509 data: cdata,
510 fill: 'origin',
511 radius: 6,
512 pointBackgroundColor: '#B45252'
513 }]
514 };
515 var chartPlugins = {
516 title: {
517 display: true,
518 text: cpi18n.io_calls +' (' + cpi18n.chart_total +' '+ ctotal_calls +')'
519 },
520 legend: {
521 display: false
522 },
523 tooltip: {
524 borderWidth: 1,
525 borderColor: '#666',
526 displayColors: false,
527 backgroundColor: '#F5F5B5',
528 titleColor:'#666',
529 padding: 8,
530 footerColor: '#666',
531 callbacks: {
532 labelTextColor: function(context) {
533 return '#543453';
534 }
535 }
536 }
537 }
538 // We want a background colour for the downloaded PNG file
539 const plugin = {
540 id: 'custom_canvas_background_color',
541 beforeDraw: (chart) => {
542 const ctx = chart.canvas.getContext('2d');
543 ctx.save();
544 ctx.globalCompositeOperation = 'destination-over';
545 ctx.fillStyle = '#f0f0f1',
546 ctx.fillRect(0, 0, chart.width, chart.height);
547 ctx.restore();
548 }
549 }
550
551 var myChart = new Chart(ctx, {
552 type: 'line',
553 data: chartData,
554 options: {
555 animation: {
556 duration: 700,
557 onComplete: function() {
558 jQuery('#cp-footer-buttons').slideDown(200);
559 document.getElementById('download-png-img').href = myChart.toBase64Image();
560 }
561 },
562 indexAxis: _indexAxis,
563 plugins: chartPlugins
564 },
565 plugins:[plugin]
566 });
567
568 }
569 // =====================================================================
570 // Disk I/O chart.
571
572 function cpjs_diskio_chart( caxis, clabel, cdata ) {
573 'use strict';
574 // Switch between vertical and horizontal bars
575 var _indexAxis = caxis;
576 document.getElementById('htov').onclick = function() {
577 if ( _indexAxis == 'x' ) {
578 _indexAxis = 'y';
579 } else {
580 _indexAxis = 'x';
581 }
582 myChart.destroy();
583 myChart = new Chart(ctx, {
584 type: 'line',
585 options: {
586 animation: {
587 duration: 1000,
588 onComplete: function() {
589 document.getElementById('download-png-img').href = myChart.toBase64Image();
590 }
591 },
592 indexAxis: _indexAxis,
593 plugins: chartPlugins
594 },
595 plugins:[ plugin],
596 data: chartData
597 });
598 };
599 var ctx = document.getElementById('myChart').getContext('2d');
600
601 var chartData = {
602 labels: clabel,
603 datasets: [{
604 label: cpi18n.disk_io_bytes,
605 backgroundColor: 'rgba(143, 240, 164, .5)',
606 borderColor: '#41B141',
607 borderWidth: 2,
608 hoverBackgroundColor: '#FF0000',
609 data: cdata,
610 fill: 'origin',
611 radius: 6,
612 pointBackgroundColor: '#B45252'
613 }]
614 };
615 var chartPlugins = {
616 title: {
617 display: true,
618 text: cpi18n.disk_io_title,
619 },
620 legend: {
621 display: false
622 },
623 tooltip: {
624 borderWidth: 1,
625 borderColor: '#666',
626 displayColors: false,
627 backgroundColor: '#F5F5B5',
628 titleColor:'#666',
629 padding: 8,
630 footerColor: '#666',
631 callbacks: {
632 labelTextColor: function(context) {
633 return '#543453';
634 }
635 }
636 }
637 }
638 // We want a background colour for the downloaded PNG file
639 const plugin = {
640 id: 'custom_canvas_background_color',
641 beforeDraw: (chart) => {
642 const ctx = chart.canvas.getContext('2d');
643 ctx.save();
644 ctx.globalCompositeOperation = 'destination-over';
645 ctx.fillStyle = '#f0f0f1',
646 ctx.fillRect(0, 0, chart.width, chart.height);
647 ctx.restore();
648 }
649 }
650
651 var myChart = new Chart(ctx, {
652 type: 'line',
653 data: chartData,
654 options: {
655 animation: {
656 duration: 700,
657 onComplete: function() {
658 jQuery('#cp-footer-buttons').slideDown(200);
659 document.getElementById('download-png-img').href = myChart.toBase64Image();
660 }
661 },
662 indexAxis: _indexAxis,
663 plugins: chartPlugins
664 },
665 plugins:[plugin]
666 });
667 }
668
669 // =====================================================================
670 // EOF
671