%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /var/www/projetos/suporte.iigd.com.br/js/modules/Debug/
Upload File :
Create Path :
Current File : //var/www/projetos/suporte.iigd.com.br/js/modules/Debug/Debug.min.js

/**
 * ---------------------------------------------------------------------
 *
 * GLPI - Gestionnaire Libre de Parc Informatique
 *
 * http://glpi-project.org
 *
 * @copyright 2015-2024 Teclib' and contributors.
 * @copyright 2003-2014 by the INDEPNET Development Team.
 * @licence   https://www.gnu.org/licenses/gpl-3.0.html
 *
 * ---------------------------------------------------------------------
 *
 * LICENSE
 *
 * This file is part of GLPI.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * ---------------------------------------------------------------------
 */
window.GLPI=window.GLPI||{};window.GLPI.Debug=new class t{constructor(){this.ajax_requests=[];this.initial_request=null;this.widgets=[];this.TIMING_COLORS={queued:"#808080",redirect:"#00aaaa",fetch:"#004400",dns:"#00cc88",connection:"#ffaa00",initial_connection:"#ffaa88",ssl:"#cc00cc",request:"#00aa00",response:"#0000ee"};this.REQUEST_PATH_LENGTH=100}init(t){this.initial_request=t;$.each(this.initial_request.sql.queries,((t,e)=>{this.initial_request.sql.queries[t].query=this.cleanSQLQuery(e.query)}));this.refreshWidgetButtons();$(document).ajaxSend(((t,e,s)=>{if(s.url.indexOf("ajax/debug.php")!==-1){return}const n=Math.random().toString(16).slice(2);e.setRequestHeader("X-Glpi-Ajax-ID",n);e.headers=e.headers||{};e.headers["X-Glpi-Ajax-ID"]=n;const a=$("html").attr("data-glpi-request-id");if(a!==undefined){e.setRequestHeader("X-Glpi-Ajax-Parent-ID",a)}let i=s.data;if(s.type!=="POST"&&i===undefined){i={};const t=s.url.split("?")[1];if(t!==undefined){t.split("&").forEach((t=>{const[e,s]=t.split("=");i[e]=s}))}}else if(typeof i==="string"){const t={};i.split("&").forEach((e=>{const[s,n]=e.split("=");t[s]=decodeURIComponent(n);try{t[s]=JSON.parse(t[s])}catch(t){}}));i=t}this.ajax_requests.push({id:n,status:"...",status_type:"info",type:s.type,data:i,url:s.url,start:t.timeStamp});this.refreshWidgetButtons()}));$(document).ajaxComplete(((t,e,s)=>{if(s.url.indexOf("ajax/debug.php")!==-1){return}if(e.headers===undefined){return}const n=e.headers["X-Glpi-Ajax-ID"];if(n!==undefined){const t=this.ajax_requests.find((t=>t.id===n));if(t!==undefined){t.status=e.status;t.time=new Date-t.start;t.status_type=e.status>=200&&e.status<300?"success":"danger";this.requestAjaxDebugData(n)}}this.refreshWidgetButtons()}));$("#debug-toolbar").on("click",".debug-toolbar-widget",(t=>{const e=$(t.currentTarget).attr("data-glpi-debug-widget-id");this.showWidget(e);this.toggleExtraContentArea(true)}));const e=$("#debug-toolbar > .resize-handle");const s=$("#debug-toolbar-expanded-content");let n=false;e.on("mousedown",(t=>{if(t.buttons===1){n=true;t.preventDefault()}}));$(document).on("mousemove",(t=>{if(n&&t.buttons===1){const e=$(window).height();let n=e-t.pageY;n=Math.max(n,200);s.css("height",`${n}px`)}}));$(document).on("mouseup",(()=>{n=false}));s.on("click","button.request-link",(t=>{const e=$(t.currentTarget).text();this.showWidget("requests");const s=$(`#debug-toolbar-expanded-content #debug-requests-table tr[data-request-id="${e}"]`);if(s.length>0){s[0].scrollIntoView();s.click()}}))}requestAjaxDebugData(t,e=false){const s=this.ajax_requests.find((e=>e.id===t));$.ajax({url:CFG_GLPI.root_doc+"/ajax/debug.php",data:{ajax_id:t}}).done((t=>{s.profile=t;$.each(s.profile.sql.queries,((t,e)=>{s.profile.sql.queries[t].query=this.cleanSQLQuery(e.query)}));const n=$("#debug-toolbar-expanded-content");if(n.data("active-widget")!==undefined){this.showWidget(n.data("active-widget"),true)}if(s.server_global!==undefined){s.profile.globals["server"]=s.server_global}if(s.type==="POST"){s.profile.globals["post"]=s.data}else{s.profile.globals["get"]=s.data}this.refreshWidgetButtons();if(e){this.showWidget(n.data("active-widget"),true)}}))}cleanSQLQuery(t){const e=["UNION","FROM","WHERE","INNER JOIN","LEFT JOIN","ORDER BY","SORT"];const s=["UNION"];let n="";window.CodeMirror.runMode(t,"text/x-sql",((t,a)=>{t=escapeMarkupText(t);if(a!==null&&a!==undefined){if(e.includes(t.toUpperCase())){n+="</br>"}n+=`<span class="cm-${a.replace(" ","")}">${t}</span>`;if(s.includes(t.toUpperCase())){n+="</br>"}}else{n+=t}}));return n}getCombinedSQLData(){const t={total_requests:0,total_duration:0,queries:{}};t.queries[this.initial_request.id]=this.initial_request.sql.queries;this.ajax_requests.forEach((e=>{if(e.profile&&e.profile.sql!==undefined){t.queries[e.id]=e.profile.sql.queries}}));$.each(t.queries,((e,s)=>{s.forEach((e=>{t.total_requests+=1;t.total_duration+=parseInt(e["time"])}))}));return t}showDebugToolbar(){$(".debug-logo").prop("disabled",true);$(".debug-toolbar-content").removeClass("d-none");$("#debug-toolbar").addClass("w-100").css("width",null);$("body").removeClass("debug-folded")}hideDebugToolbar(){$(".debug-logo").prop("disabled",false);$(".debug-toolbar-content").addClass("d-none");$("#debug-toolbar-expanded-content").addClass("d-none");$("#debug-toolbar").removeClass("w-100").css("width","fit-content");$("body").addClass("debug-folded")}toggleExtraContentArea(t=false){const e=$("#debug-toolbar-expanded-content");const s=$('#debug-toolbar .debug-toolbar-controls button[name="toggle_content_area"] i');if(e.hasClass("d-none")||t){e.removeClass("d-none");s.removeClass("ti-square-arrow-up").addClass("ti-square-arrow-down")}else{e.addClass("d-none");s.removeClass("ti-square-arrow-down").addClass("ti-square-arrow-up")}}getProfile(t){if(t===this.initial_request.id){return this.initial_request}return this.ajax_requests.find((e=>e.id===t)).profile}getWidgetButton(t){return $(`#debug-toolbar .debug-toolbar-widgets li[data-glpi-debug-widget-id="${t}"]`)}refreshWidgetButtons(){const t=this.initial_request.server_performance;const e=+(t.memory_usage/1024/1024).toFixed(2);const s=`${t.execution_time} <span class="text-muted"> ms using </span> ${e} <span class="text-muted"> MiB </span>`;this.getWidgetButton("server_performance").find(".debug-text").html(s);const n=this.getCombinedSQLData();const a=`${n.total_requests} <span class="text-muted"> requests </span>`;this.getWidgetButton("sql").find(".debug-text").html(a);this.getWidgetButton("requests").find(".debug-text").html(`${this.ajax_requests.length} <span class="text-muted"> requests </span>`);const i=+window.performance.getEntriesByType("navigation")[0].domComplete.toFixed(2);const d=`${i} <span class="text-muted"> ms </span>`;this.getWidgetButton("client_performance").find(".debug-text").html(d)}showWidget(t,e=false,s=undefined,n={}){if(s===undefined){s=$("#debug-toolbar-expanded-content");const e=this.getWidgetButton(t);if(e.length>0){$("#debug-toolbar .debug-toolbar-widgets .debug-toolbar-widget").removeClass("active");e.addClass("active")}}s.data("active-widget",t);$.each(n,((t,e)=>{s.data(t,e)}));switch(t){case"server_performance":this.showServerPerformance(s,e);break;case"sql":this.showSQLRequests(s,e);break;case"globals":this.showGlobals(s);break;case"client_performance":this.showClientPerformance(s,e);break;case"profiler":this.showProfiler(s,e);break;case"requests":this.showRequests(s,e);break;case"request_summary":this.showRequestSummary(s);break;default:s.empty();s.append(`<div class="alert alert-danger"><h1>Content for widget ${t} not found</h1></div>`)}}showServerPerformance(t,e=false){if(!e){t.empty();t.append(`\n                <div class="py-2 px-3 col-xxl-7 col-xl-9 col-12">\n                    <h2 class="mb-3">Server performance</h2>\n                    <div class="datagrid"></div>\n                </div>\n            `)}const s=this.initial_request.server_performance;const n=(s.memory_usage/1024/1024).toFixed(2);const a=(s.memory_peak/1024/1024).toFixed(2);const i=(s.memory_limit/1024/1024).toFixed(2);let d=this.initial_request.server_performance.execution_time;this.ajax_requests.forEach((t=>{if(t.profile){d+=t.profile.server_performance.execution_time}}));d=d.toFixed(2);t.find(".datagrid").empty().append(`\n            <div class="datagrid-item">\n                <div class="datagrid-title">Initial Execution Time</div>\n                <div class="datagrid-content">${+this.initial_request.server_performance.execution_time} ms</div>\n            </div>\n            <div class="datagrid-item">\n                <div class="datagrid-title">Total Execution Time</div>\n                <div class="datagrid-content">${+d} ms</div>\n            </div>\n            <div class="datagrid-item">\n                <div class="datagrid-title">Memory Usage</div>\n                <div class="datagrid-content h-100 col-8">${+n} MiB / ${+i} MiB</div>\n            </div>\n            <div class="datagrid-item">\n                <div class="datagrid-title">Memory Peak</div>\n                <div class="datagrid-content">${+a} MiB / ${+i} MiB</div>\n            </div>\n        `)}showSQLRequests(t,e=false){const s=t.data("request_id");if(s!==undefined&&this.getProfile(s)===undefined){this.showMissingRequestData(t,t.data("request_id"));return}if(!e){t.empty();t.append(`\n                <div class="overflow-auto py-2 px-3">\n                   <h2 class="mb-3"></h2>\n                   <table id="debug-sql-request-table" class="table card-table">\n                      <thead>\n                      <tr>\n                         ${s===undefined?"<th>Request ID</th>":""}\n                         <th>Number</th><th>Query</th><th>Time</th><th>Rows</th><th>Warnings</th><th>Errors</th>\n                      </tr>\n                      </thead>\n                      <tbody></tbody>\n                   </table>\n                </div>\n            `);initSortableTable("debug-sql-request-table")}const n=t.find("table").first();const a=n.find("tbody").first();let i=new Set;a.find("tr td:first-child").each(((t,e)=>{i.add($(e).text())}));const d=this.getCombinedSQLData();let r="";$.each(d["queries"],((t,e)=>{if(i.has(t)||s!==undefined&&s!==t){return}e.forEach((e=>{r+=`\n                    <tr>\n                        ${s===undefined?`<td><button class="btn btn-link request-link">${t}</button></td>`:""}\n                        <td>${e["num"]}</td>\n                        <td>\n                            <div class="d-flex align-items-start" style="max-width: 50vw;">\n                                <div style="max-width: 50vw; white-space: break-spaces;" class="w-100"><code class="d-block cm-s-default border-0">${e["query"]}</code></div>\n                                <button type="button" class="ms-1 copy-code btn btn-sm btn-ghost-secondary" title="Copy query to clipboard">\n                                    <i class="ti ti-clipboard-copy"></i>\n                                </button>\n                            </div>\n                        </td>\n                        <td data-value-unit="ms">${e["time"]} ms</td>\n                        <td>${e["rows"]}</td>\n                        <td>${escapeMarkupText(e["warnings"])}</td>\n                        <td>${escapeMarkupText(e["errors"])}</td>\n                    </tr>\n                `}))}));a.append(r);$(".copy-code").on("click",(function(){const t=$(this).parent().find("code");copyTextToClipboard(t.text());const e=$(this).find("i");e.removeClass("ti-clipboard-copy").addClass("ti-check");setTimeout((()=>{e.removeClass("ti-check").addClass("ti-clipboard-copy")}),1e3)}));if(s!==undefined){let e=0;let n=0;$.each(d["queries"],((t,a)=>{if(t===s){e+=a.length;a.forEach((t=>{n+=parseFloat(t["time"])}))}}));t.find("h2").first().text(`${e} Queries took ${n} ms`)}else{t.find("h2").first().text(`${d.total_requests} Queries took ${d.total_duration} ms`)}if(n.data("sort")){n.find("thead th").eq(n.data("sort")).click().click()}}showGlobals(t){const e=(t,e)=>{if(t===undefined||t===null){e.append("Empty array");return}let s=t;try{s=JSON.stringify(t,null," ")}catch(s){if(typeof t!=="string"){e.append("Empty array");return}}const n=window.CodeMirror(e.get(0),{value:s,mode:"application/json",lineNumbers:true,readOnly:true,foldGutter:true,gutters:["CodeMirror-linenumbers","CodeMirror-foldgutter"]});e.data("editor",n)};const s=Math.floor(Math.random()*1e6);t.empty();t.append(`\n            <div>\n               <div id="debugpanel${s}" class="container-fluid card p-0 border-top-0" style="min-width: 400px; max-width: 90vw">\n                  <ul class="nav nav-pills" data-bs-toggle="tabs">\n                     <li class="nav-item"><a class="nav-link active" data-bs-toggle="tab" href="#debugpost${s}">POST</a></li>\n                     <li class="nav-item"><a class="nav-link" data-bs-toggle="tab" href="#debugget${s}">GET</a></li>\n                     <li class="nav-item"><a class="nav-link" data-bs-toggle="tab" href="#debugsession${s}">SESSION</a></li>\n                     <li class="nav-item"><a class="nav-link" data-bs-toggle="tab" href="#debugserver${s}">SERVER</a></li>\n                  </ul>\n\n                  <div class="card-body overflow-auto p-1">\n                     <div class="tab-content">\n                        <div id="debugpost${s}" class="cm-s-default tab-pane active"></div>\n                        <div id="debugget${s}" class="cm-s-default tab-pane"></div>\n                        <div id="debugsession${s}" class="cm-s-default tab-pane"></div>\n                        <div id="debugserver${s}" class="cm-s-default tab-pane"></div>\n                     </div>\n                  </div>\n               </div>\n            </div>\n        `);const n=t.data("request_id");const a=this.getProfile(n);if(a===undefined){this.showMissingRequestData(t,t.data("request_id"));return}const i=a.globals;e(i["post"],t.find(`#debugpost${s}`));e(i["get"],t.find(`#debugget${s}`));e(i["session"],t.find(`#debugsession${s}`));e(i["server"],t.find(`#debugserver${s}`));t.on("shown.bs.tab",'a[data-bs-toggle="tab"]',(e=>{const s=$(e.target).attr("href");const n=t.find(s);const a=n.data("previously_shown")||false;const i=n.data("editor");if(!a&&i){i.refresh();setTimeout((()=>{const t=i.lineCount();for(let e=t-1;e>1;e--){i.foldCode(window.CodeMirror.Pos(e,0))}}),100)}n.data("previously_shown",true)}));t.find('a[data-bs-toggle="tab"]').first().trigger("shown.bs.tab")}showClientPerformance(t,e=false){if(!e){t.empty()}const s=window.performance;const n=window.performance.getEntriesByType("navigation")[0];const a=window.performance.getEntriesByType("paint");const i=window.performance.getEntriesByType("resource");let d=a.filter((t=>t.name==="first-paint"));let r="Time to first paint";if(d.length===0){d=a.filter((t=>t.name==="first-contentful-paint"));r="Time to first contentful paint"}const o=d.length>0?d[0].startTime:-1;const l=n.domInteractive;const c=n.domComplete;const u=i.length;let h=i.reduce(((t,e)=>t+e.transferSize),0);h=h/1024/1024;t.append(`\n            <div class="py-2 px-3 col-xxl-7 col-xl-9 col-12">\n                <h2 class="mb-3">Client performance</h2>\n                <h3 class="mb-2">Timings</h3>\n                <div class="datagrid">\n                    <div class="datagrid-item">\n                        <div class="datagrid-title">${r}</div>\n                        <div class="datagrid-content">${+o.toFixed(2)} ms</div>\n                    </div>\n                    <div class="datagrid-item">\n                        <div class="datagrid-title">Time to DOM interactive</div>\n                        <div class="datagrid-content">${+l.toFixed(2)} ms</div>\n                    </div>\n                    <div class="datagrid-item">\n                        <div class="datagrid-title">Time to DOM complete</div>\n                        <div class="datagrid-content">${+c.toFixed(2)} ms</div>\n                    </div>\n                </div>\n                <h3 class="mt-3 mb-2">Resource Loading</h3>\n                <div class="datagrid">\n                    <div class="datagrid-item">\n                        <div class="datagrid-title">Total resources</div>\n                        <div class="datagrid-content">${u}</div>\n                    </div>\n                    <div class="datagrid-item">\n                        <div class="datagrid-title">Total resources size</div>\n                        <div class="datagrid-content">${+h.toFixed(2)} MiB</div>\n                    </div>\n                    \x3c!-- Keep empty item at the end to align with previous grid --\x3e\n                    <div class="datagrid-item"></div>\n                </div>\n            </div>\n        `);if(s.memory!=undefined){const e=s.memory.jsHeapSizeLimit/1024/1024;const n=s.memory.usedJSHeapSize/1024/1024;const a=s.memory.totalJSHeapSize/1024/1024;t.find(".datagrid:last").append(`\n                <h3 class="mt-3 mb-2">Memory</h3>\n                <div class="datagrid">\n                    <div class="datagrid-item">\n                        <div class="datagrid-title">Used JS Heap</div>\n                        <div class="datagrid-content">${+n.toFixed(2)}</div>\n                    </div>\n                    <div class="datagrid-item">\n                        <div class="datagrid-title">Total JS Heap</div>\n                        <div class="datagrid-content">${+a.toFixed(2)} MiB</div>\n                    </div>\n                    <div class="datagrid-item">\n                        <div class="datagrid-title">JS Heap Limit</div>\n                        <div class="datagrid-content">${+e.toFixed(2)} MiB</div>\n                    </div>\n                </div>\n            `)}}getProfilerCategoryColor(t){const e={core:"#526dad",db:"#9252ad",twig:"#64ad52",plugins:"#a077a6"};let s="";if(e[t]!==undefined){s=e[t]}else{let e=0;for(let s=0;s<t.length;s++){e=t.charCodeAt(s)+((e<<5)-e)}let n="#";for(let t=0;t<3;t++){const s=e>>t*8&255;n+=("00"+s.toString(16)).substr(-2)}s=n}const n=hexToRgb(s);const a=luminance([n["r"],n["g"],n["b"]])>.5?"var(--dark)":"var(--light)";return{bg_color:s,text_color:a}}getProfilerTable(t,e,s=0,n=0){let a=`\n            <table class="table table-striped card-table">\n                <thead>\n                    <tr>\n                       ${'<th style="min-width: 2rem"></th>'.repeat(s)}\n                       <th>Category</th>\n                       <th>Name</th>\n                       <th>Start</th>\n                       <th>End</th>\n                       <th>Duration</th>\n                       <th>Percent of parent</th>\n                   </tr>\n                </thead>\n                <tbody>\n        `;const i=6+s;const d=e.filter((e=>e.parent_id===t));d.forEach((t=>{const d=this.getProfilerCategoryColor(t.category);const r=t.end-t.start;let o=100;if(s>0){o=r/n*100}o=o.toFixed(2);a+=`\n                <tr data-profiler-section-id="${t.id}">\n                    ${'<td style="min-width: 2rem"></td>'.repeat(s)}\n                    <td>\n                        <span class="category-badge" style='background-color: ${d.bg_color}; color: ${d.text_color}'>\n                            ${escapeMarkupText(t.category)}\n                        </span>\n                    </td>\n                    <td>${escapeMarkupText(t.name)}</td><td>${t.start}</td><td>${t.end}</td>\n                    <td data-column="duration" data-duration-raw="${r}">${r.toFixed(0)} ms</td>\n                    <td>${o}%</td>\n                </tr>\n            `;const l=e.filter((e=>e.parent_id===t.id));if(l.length>0){const n=this.getProfilerTable(t.id,e,s+1,r);a+=`<tr><td colspan="${i}">${n}</td></tr>`}}));a+="</tbody></table>";return a}showProfiler(t,e=false){if(!e){t.empty()}t.append(`\n            <div>\n               <label>\n                 Hide near-instant sections (&lt;= 1 ms):\n                 <input type="checkbox" name="hide_instant_sections">\n               </label>\n            </div>\n        `);const s=t.data("request_id");const n=t.find('input[name="hide_instant_sections"]');const a=t.data("profiler_hide_instant_sections")||true;n.prop("checked",a);n.off("change").on("change",(e=>{const s=$(e.target).prop("checked");t.data("profiler_hide_instant_sections",s);const n=t.find("tr");n.removeClass("d-none");if(s){n.each(((t,e)=>{const s=$(e).find('> td[data-column="duration"]');if(s.length>0){const t=parseFloat(s.attr("data-duration-raw"));if(t<=1){$(e).addClass("d-none")}}}))}t.find("table").each(((t,e)=>{const s=$(e);const n=s.parent();if(s.find("> tbody > tr:not(.d-none)").length===0){s.addClass("d-none");if(n.prop("tagName")==="TD"){n.addClass("d-none")}}else{s.removeClass("d-none");if(n.prop("tagName")==="TD"){n.removeClass("d-none")}}}))}));const i=this.getProfile(s);if(i===undefined){this.showMissingRequestData(t,s);return}const d=i.profiler||{};const r=Object.values(d).sort(((t,e)=>t.start-e.start));t.find("> div").append(this.getProfilerTable(null,r));n.trigger("change")}showRequests(t,e=false){if(!e){t.empty();const e=Math.floor(Math.random()*1e6);t.append(`\n                <div class="request-timeline"></div>\n                <div class="d-flex flex-row h-100 split-panel-h">\n                    <div class="left-panel">\n                        <div class="overflow-auto h-100 me-2">\n                            <table id="debug-requests-table" class="table table-hover mb-1">\n                                <thead>\n                                    <tr>\n                                        <th>Number</th>\n                                        <th style="max-width: 200px; white-space: pre-wrap;">URL</th>\n                                        <th>Status</th>\n                                        <th>Type</th>\n                                        <th>Duration</th>\n                                    </tr>\n                                </thead>\n                                <tbody style="white-space: nowrap">\n                                </tbody>\n                            </table>\n                        </div>\n                    </div>\n                    <div class="resize-handle"></div>\n                    <div class="right-panel overflow-auto ms-2 flex-grow-1">\n                        <div id="debugpanel${e}" class="p-0 mt-n1">\n                            <ul class="nav nav-tabs" data-bs-toggle="tabs">\n                                <li class="nav-item">\n                                    <button class="nav-link" data-bs-toggle="tab" data-glpi-debug-widget-id="request_summary">Summary</button>\n                                </li>\n                                <li class="nav-item">\n                                    <button class="nav-link" data-bs-toggle="tab" data-glpi-debug-widget-id="sql">SQL</button>\n                                </li>\n                                <li class="nav-item">\n                                    <button class="nav-link" data-bs-toggle="tab" data-glpi-debug-widget-id="globals">Globals</button>\n                                </li>\n                                <li class="nav-item">\n                                    <button class="nav-link" data-bs-toggle="tab" data-glpi-debug-widget-id="profiler">Profiler</button>\n                                </li>\n                            </ul>\n\n                            <div class="card-body overflow-auto p-1">\n                                <div class="tab-content request-details-content-area">\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            `);this.showRequestTimeline(t.find(".request-timeline").eq(0));const s=window.location.pathname.substring(0,this.REQUEST_PATH_LENGTH);const n=s.length<window.location.pathname.length;t.find("#debug-requests-table tbody").append(`\n                <tr data-request-id="${this.initial_request.id}" class="cursor-pointer table-active">\n                    <td>0</td>\n                    <td style="max-width: 200px; white-space: pre-wrap;" title="${window.location.pathname}" data-truncated="${n?"true":"false"}">${s}</td>\n                    <td>-</td>\n                    <td>${this.initial_request.globals.server["REQUEST_METHOD"]||"-"}</td>\n                    <td>${this.initial_request.server_performance.execution_time} ms</td>\n                </tr>\n            `);if(n){t.find(`tr[data-request-id="${this.initial_request.id}"] td[data-truncated="true"]`).append(`<button type="button" class="ms-1 badge bg-secondary" name="show_full_url">\n                        <i class="ti ti-dots"></i>\n                    </button>`)}const a=t.find(".resize-handle");let i=false;a.on("mousedown",(t=>{if(t.buttons===1){i=true;t.preventDefault()}}));t.on("mousemove",(e=>{if(i&&e.buttons===1){const s=t.find("> div > div:first-child");const n=e.pageX-s.offset().left;s.css("flex",`0 0 ${n}px`)}}));t.on("mouseup",(()=>{i=false}));t.on("click","button[data-glpi-debug-widget-id]",(e=>{const s=$(e.currentTarget).attr("data-glpi-debug-widget-id");t.data("requests_active_widget",s);this.showWidget(s,false,t.find(".request-details-content-area"),{request_id:t.data("requests_request_id")||this.initial_request.id})}));t.on("click","#debug-requests-table tbody tr",(e=>{t.data("requests_request_id",$(e.currentTarget).attr("data-request-id"));$(e.currentTarget).addClass("table-active").siblings().removeClass("table-active");this.showWidget(t.data("requests_active_widget")||"request_summary",false,t.find(".request-details-content-area"),{request_id:t.data("requests_request_id")||this.initial_request.id})}));t.on("click",'button[name="show_full_url"]',(t=>{const e=$(t.currentTarget);const s=e.closest("td");s.text(s.attr("title"));e.hide()}));if(t.data("requests_request_id")===undefined){t.data("requests_request_id",this.initial_request.id)}if(t.find(".request-details-content-area").data("request_id")===undefined){t.find(".request-details-content-area").data("request_id",this.initial_request.id)}t.find('button[data-glpi-debug-widget-id="request_summary"]').click();initSortableTable("debug-requests-table")}this.ajax_requests.forEach((e=>{const s=t.find(`tr[data-request-id="${e.id}"]`);if(s.length===0){const s=t.find("#debug-requests-table tbody tr").length;const n=e.url.substring(0,this.REQUEST_PATH_LENGTH);const a=n.length<e.url.length;t.find("#debug-requests-table tbody").append(`\n                    <tr data-request-id="${e.id}" class="cursor-pointer">\n                        <td>${s}</td>\n                        <td style="max-width: 200px; white-space: pre-wrap;" title="${e.url}" data-truncated="${a?"true":"false"}">${n}</td>\n                        <td>${e.status}</td>\n                        <td>${e.type}</td>\n                        <td data-value-unit="ms">${e.time} ms</td>\n                    </tr>\n                `);if(a){if(t.find(`tr[data-request-id="${e.id}"] td[data-truncated="true"] button[name="show_full_url"]`).length===0){t.find(`tr[data-request-id="${e.id}"] td[data-truncated="true"]`).append(`<button type="button" class="ms-1 badge bg-secondary" name="show_full_url">\n                        <i class="ti ti-dots"></i>\n                    </button>`)}}const i=t.find(`tr[data-request-id="${e.id}"]`);i.css("background-color","#FFFF7B80");setTimeout((()=>{i.css("background-color","transparent")}),2e3);const d=t.find("#debug-requests-table");if(d.data("sort")){d.find("thead th").eq(d.data("sort")).click().click()}else{d.parent().scrollTop(d.parent()[0].scrollHeight)}}else{s.find("> td:nth-child(3)").text(e.status);s.find("> td:nth-child(5)").text(`${e.time} ms`)}}))}showMissingRequestData(t,e){t.empty();t.append(`\n            <div class="alert alert-danger">\n            <span>No debug data was found for this request immediately after it finished. Some requests like /front/locale.php will never have data as they intentionally close the session.</span>\n            </div>\n            <button type="button" class="btn btn-primary" data-request-id="${e}"><i class="ti ti-reload"></i>Retry</button>\n        `);t.find("button").on("click",(t=>{const e=$(t.currentTarget);const s=e.data("request-id");this.requestAjaxDebugData(s,true)}))}showRequestSummary(t){t.empty();const e=this.getProfile(t.data("request_id"));if(e===undefined){this.showMissingRequestData(t,t.data("request_id"));return}const s=e.server_performance;const n=(s.memory_usage/1024/1024).toFixed(2);const a=(s.memory_peak/1024/1024).toFixed(2);const i=(s.memory_limit/1024/1024).toFixed(2);let d=e.server_performance.execution_time;let r=0;let o=0;$.each(e.sql["queries"],((t,e)=>{o++;r+=parseFloat(e["time"])}));t.append(`\n            <h1>Request Summary (${e.id})</h1>\n            <table class="table">\n                <tbody>\n                    <tr>\n                        <td>\n                            Initial Execution Time: ${d} ms\n                        </td>\n                        <td>\n                            Memory Usage: ${n} MiB / ${i} MiB\n                            <br>\n                            Memory Peak: ${a} MiB / ${i} MiB\n                        </td>\n                    </tr>\n                    <tr>\n                        <td>\n                            SQL Requests: ${o}\n                            <br>\n                            SQL Duration: ${r} ms\n                        </td>\n                    </tr>\n                </tbody>\n            </table>\n        `)}getAllRequestTimings(){const t=window.performance.getEntriesByType("navigation")[0];const e=window.performance.getEntriesByType("resource");const s=[];s.push({type:"navigation",name:t.name,start:t.startTime,end:t.responseEnd,bounds:{},sections:{queued:[t.startTime,t.redirectStart],redirect:[t.redirectStart,t.redirectEnd],fetch:[t.redirectEnd,t.redirectStart],dns:[t.domainLookupStart,t.domainLookupEnd],connection:[t.connectStart,t.connectEnd],initial_connection:[t.connectStart,t.secureConnectionStart],ssl:[t.secureConnectionStart,t.connectEnd],request:[t.requestStart,t.responseStart],response:[t.responseStart,t.responseEnd]}});$.each(e,((t,e)=>{s.push({type:e.initiatorType,name:e.name,start:e.startTime,end:e.responseEnd,bounds:{},sections:{queued:[e.startTime,e.redirectStart!==0?e.redirectStart:e.domainLookupStart],redirect:[e.redirectStart,e.redirectEnd],fetch:[e.redirectEnd,e.redirectStart],dns:[e.domainLookupStart,e.domainLookupEnd],connection:[e.connectStart,e.connectEnd],initial_connection:[e.connectStart,e.secureConnectionStart],ssl:[e.secureConnectionStart,e.connectEnd],request:[e.requestStart,e.responseStart],response:[e.responseStart,e.responseEnd]}})}));let n=0;$.each(s,((t,e)=>{const s=e.sections.response[1];if(s>n){n=s}}));return{end_ts:n,timings:s}}showRequestTimeline(t){t.empty();const e=this.getAllRequestTimings();const s=e.end_ts;const n=e.timings;const a=window.performance.timeOrigin;const i=[];const d=(t,e,s)=>{let n=false;$.each(t,((t,a)=>{if(e>=a.start&&e<=a.end||s>=a.start&&s<=a.end){n=true;return false}}));return n};$.each(n,((t,e)=>{let s=null;$.each(i,((t,n)=>{if(!d(n,e.start,e.end)){s=n;return false}}));if(s===null){s=[e];i.push(s)}else{s.push(e)}}));const r=10;const o=150;const l=4;const c=2;t.append(`\n            <canvas class="d-none" height="${i.length*(l+c)+12}"></canvas>\n        `);const u=t.find("canvas").eq(0);t.closest("#debug-toolbar").on("keyup",(t=>{t.preventDefault();t.stopPropagation();if(t.keyCode===84){u.toggleClass("d-none")}}));const h=u[0].getContext("2d");const g=100;const f=u.css("color");const p=window.setInterval((()=>{if(t.find("canvas").length===0){window.clearInterval(p);return}u.trigger("render")}),1e3/r);const m=(t,e,s)=>{const n=u.closest("#debug-toolbar-expanded-content").data("requests_request_id");let i=false;if(n===this.initial_request.id&&t.type==="navigation"){i=true}else{const d=this.ajax_requests.find((t=>t.id===n));if(d===undefined){return false}const r=[];$.each(s,((t,e)=>{if(e.name.endsWith(d.url)){r.push({i:t,entry:e})}}));if(r.length===1&&r[0].i===e){i=true}else{let s=null;r.forEach(((e,n)=>{if(s===null){s=n;return}const i=n.start-a;if(Math.abs(i-t.start)<Math.abs(s.start-t.start)){s=n}}));i=s!==null&&s.i===e}}return i};let b=null;u.on("render",(()=>{if(u.hasClass("d-none")){return}u.attr("width",u.parent().width());const t=u.width();const e=u.height();const n=Math.ceil(s/100)*100;const a=Math.min(Math.ceil(t/o),Math.ceil(n/g));const d=[];for(let e=0;e<a;e++){d.push({canvas_x:Math.round(t/a*e),time:Math.ceil(n/a*e/100)*100})}h.fillStyle="#80808040";h.fillRect(0,0,t,e);$.each(d,((t,s)=>{h.fillStyle=f;h.strokeStyle=f;h.font=h.font.replace(/\d+px/,"10px");h.beginPath();h.moveTo(s.canvas_x,0);h.lineTo(s.canvas_x,e);h.stroke();h.fillText(`${s.time} ms`,s.canvas_x+2,10)}));$.each(i,((e,n)=>{const a=e*(l+c)+12;$.each(n,((e,i)=>{const d=m(i,e,n);const r=i.sections;$.each(r,((e,n)=>{if(n[0]===0&&n[1]===0){return}const r=this.TIMING_COLORS[e]||"#00aa00";const o=Math.round((n[1]-n[0])/s*t);const c=Math.round(n[0]/s*t);i.bounds[e]={x:c,y:a,width:o,height:l};h.fillStyle=r;h.fillRect(c,a,o,l);if(d){const t=h.strokeStyle;h.strokeStyle="#ffff00";h.strokeRect(c,a,o,l);h.strokeRect(c-1,a-1,o+2,l+2);h.strokeStyle=t}}))}))}));if(b!==null){h.fillStyle="#808080";const t=b.target.section;const e=t.sections[b.target.timing][1]-t.sections[b.target.timing][0];let s=t.name;if(s.length>100){s=s.slice(0,100)+"..."}const n=`${s} ${b.target.timing} (${e.toFixed(0)} ms)`;h.font=h.font.replace(/\d+px/,"14px");const a=h.measureText(n).width;h.fillRect(t.bounds[b.target.timing].x,t.bounds[b.target.timing].y+l,a+4,18);h.fillStyle=f;h.fillText(n,t.bounds[b.target.timing].x+2,t.bounds[b.target.timing].y+l+14)}}));u.on("mousemove",(t=>{const e=t.offsetX;const s=t.offsetY;let n=null;$.each(i,((t,a)=>{$.each(a,((t,a)=>{$.each(a.bounds,((t,i)=>{if(e>=i.x&&e<=i.x+i.width&&s>=i.y&&s<=i.y+i.height){n={section:a,timing:t};return false}}));if(n!==null){return false}}));if(n!==null){return false}}));if(n!==null){b={target:n};u.css("cursor","pointer")}else{b=null;u.css("cursor","default")}}));u.on("mouseleave",(()=>{b=null;u.css("cursor","default")}));u.on("click",(()=>{if(b!==null){const t=b.target.section;let e=null;if(t.type==="navigation"){e=this.initial_request.id}else{const s=[];$.each(this.ajax_requests,((e,n)=>{if(t.name.endsWith(n.url)){s.push(n)}}));if(s.length===1){e=s[0].id}else{let n=null;s.forEach(((e,s)=>{if(n===null){n=s;return}const i=s.start-a;if(Math.abs(i-t.start)<Math.abs(n.start-t.start)){n=s}}));if(n!==null){e=n.id}}}if(e!==null){const t=u.closest("#debug-toolbar-expanded-content");t.data("requests_request_id",e);this.showWidget(t.data("requests_active_widget")||"request_summary",false,t.find(".request-details-content-area"),{request_id:t.data("requests_request_id")});u.trigger("render")}}}))}};

Zerion Mini Shell 1.0