PluginProbe
Code Profiler – WordPress Performance Profiling and Debugging Made Easy / 1.5.1
Code Profiler – WordPress Performance Profiling and Debugging Made Easy v1.5.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.5.1, at static/code-profiler.js

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