您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
log uncaught window (XHR.send, XHR.onerror, $.ajax...) exceptions and write them in the document as bootstrap alert html elements
当前为
// ==UserScript== // @name Bubble Logger // @require https://code.jquery.com/jquery-3.4.1.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js // @namespace http://tampermonkey.net/ // @version 0.1 // @license MIT // @description log uncaught window (XHR.send, XHR.onerror, $.ajax...) exceptions and write them in the document as bootstrap alert html elements // @author Sergio Lopez // @match http*://*/* // @icon https://store-images.s-microsoft.com/image/apps.32031.13510798887630003.b4c5c861-c9de-4301-99ce-5af68bf21fd1.ba559483-bc2c-4eb9-a17e-c302009b2690?w=180&h=180&q=60 // @resource REMOTE_CSS https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css // @grant GM_xmlhttpRequest // @grant GM_getResourceText // @grant GM_addStyle // ==/UserScript== //IIFE (function() { "use strict"; const $ = window.jQuery; const spinner = $("<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" style=\"margin: auto; background: none; display: block; shape-rendering: crispedges; animation-play-state: running; animation-delay: 0s;\" width=\"50px\" height=\"50px\" viewBox=\"0 0 100 100\" preserveAspectRatio=\"xMidYMid\"> <g style=\"animation-play-state: running; animation-delay: 0s;\"> <circle cx=\"60\" cy=\"50\" r=\"4\" fill=\"#ffffff\" style=\"animation-play-state: running; animation-delay: 0s;\"> <animate attributeName=\"cx\" repeatCount=\"indefinite\" dur=\"1s\" values=\"95;35\" keyTimes=\"0;1\" begin=\"-0.67s\" style=\"animation-play-state: running; animation-delay: 0s;\"></animate> <animate attributeName=\"fill-opacity\" repeatCount=\"indefinite\" dur=\"1s\" values=\"0;1;1\" keyTimes=\"0;0.2;1\" begin=\"-0.67s\" style=\"animation-play-state: running; animation-delay: 0s;\"></animate> </circle> <circle cx=\"60\" cy=\"50\" r=\"4\" fill=\"#ffffff\" style=\"animation-play-state: running; animation-delay: 0s;\"> <animate attributeName=\"cx\" repeatCount=\"indefinite\" dur=\"1s\" values=\"95;35\" keyTimes=\"0;1\" begin=\"-0.33s\" style=\"animation-play-state: running; animation-delay: 0s;\"></animate> <animate attributeName=\"fill-opacity\" repeatCount=\"indefinite\" dur=\"1s\" values=\"0;1;1\" keyTimes=\"0;0.2;1\" begin=\"-0.33s\" style=\"animation-play-state: running; animation-delay: 0s;\"></animate> </circle> <circle cx=\"60\" cy=\"50\" r=\"4\" fill=\"#ffffff\" style=\"animation-play-state: running; animation-delay: 0s;\"> <animate attributeName=\"cx\" repeatCount=\"indefinite\" dur=\"1s\" values=\"95;35\" keyTimes=\"0;1\" begin=\"0s\" style=\"animation-play-state: running; animation-delay: 0s;\"></animate> <animate attributeName=\"fill-opacity\" repeatCount=\"indefinite\" dur=\"1s\" values=\"0;1;1\" keyTimes=\"0;0.2;1\" begin=\"0s\" style=\"animation-play-state: running; animation-delay: 0s;\"></animate> </circle> </g><g transform=\"translate(-15 0)\" style=\"animation-play-state: running; animation-delay: 0s;\"> <path d=\"M50 50L20 50A30 30 0 0 0 80 50Z\" fill=\"#005bbf\" transform=\"rotate(90 50 50)\" style=\"animation-play-state: running; animation-delay: 0s;\"></path> <path d=\"M50 50L20 50A30 30 0 0 0 80 50Z\" fill=\"#005bbf\" style=\"animation-play-state: running; animation-delay: 0s;\"> <animateTransform attributeName=\"transform\" type=\"rotate\" repeatCount=\"indefinite\" dur=\"1s\" values=\"0 50 50;45 50 50;0 50 50\" keyTimes=\"0;0.5;1\" style=\"animation-play-state: running; animation-delay: 0s;\"></animateTransform> </path> <path d=\"M50 50L20 50A30 30 0 0 1 80 50Z\" fill=\"#005bbf\" style=\"animation-play-state: running; animation-delay: 0s;\"> <animateTransform attributeName=\"transform\" type=\"rotate\" repeatCount=\"indefinite\" dur=\"1s\" values=\"0 50 50;-45 50 50;0 50 50\" keyTimes=\"0;0.5;1\" style=\"animation-play-state: running; animation-delay: 0s;\"></animateTransform> </path></g> <!-- [ldio] generated by https://loading.io/ --></svg>"); const bubbleStates = ["primary", "danger", "warning"]; let startTime = new Date(); console.defaultError = console.error.bind(console); console.errors = []; console.defaultWarn = console.warn.bind(console); console.warns = []; console.defaultInfo = console.info.bind(console); console.infos = []; const messagesBox = $("<div class=\"messagesBox\">"); const containerSvg = $("<div class=\"svgContainer\">"); const containerErrors = $("<div class=\"containerErrors\">"); spinner.appendTo(containerSvg); containerSvg.appendTo(messagesBox) containerErrors.prependTo(messagesBox); messagesBox.appendTo($('body')) // containerErrors.prependTo(container); function bubbleErrorInHtml(event, bubbleType) { bubbleType = bubbleStates.includes(bubbleType) ? bubbleType : "primary"; // set the message to display: none to fade it in later. const messagesBox = $("<div class=\"alert alert-dismissible fade show\" style=\"display: none;\">"); messagesBox.addClass("alert-" + bubbleType); // a close button const close = $("<button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\">×</button>"); if (typeof event === "string") { messagesBox.append(close); // adding the close button to the message messagesBox.append(event); // adding the error response to the message messagesBox.prependTo(containerErrors).fadeIn(300); //.delay(10000).fadeOut(500); //.delay(5000).fadeOut(500); } else { // set the message to display: none to fade it in later. const messagesBox = $("<div class=\"alert alert-dismissible fade show\" style=\"display: none;\">"); messagesBox.addClass("alert-" + bubbleType); const close = $("<button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\">×</button>"); messagesBox.append(close); // adding the close button to the message messagesBox.append(event.statusCode + " " + event.url + " " + event.duration); // adding the error response to the message messagesBox.prependTo(containerErrors).fadeIn(300); //.delay(10000).fadeOut(500); //.delay(5000).fadeOut(500); } } console.error = function() { bubbleErrorInHtml(arguments[0], "danger"); // default & console.error() console.defaultError.apply(console, arguments); // new & array data console.errors.push(Array.from(arguments)); }; console.warn = function() { bubbleErrorInHtml(arguments[0], "warning"); // default & console.error() console.defaultWarn.apply(console, arguments); // new & array data console.warns.push(Array.from(arguments)); }; console.info = function() { bubbleErrorInHtml(arguments[0], "primary"); // default & console.error() console.defaultInfo.apply(console, arguments); // new & array data console.infos.push(Array.from(arguments)); }; // Load remote CSS // @see https://github.com/Tampermonkey/tampermonkey/issues/835 const spinnerCss = ".loadingio-spinner-bean-eater-m1d52hd0p4d {top:50% !important; left:50% !important}"; GM_addStyle(spinnerCss); const myCss = GM_getResourceText("REMOTE_CSS"); GM_addStyle(myCss); const errorMessageCss = ".alert {opacity: 0.9; margin: 0px !important; font-size:13px !important}"; GM_addStyle(errorMessageCss); const messagesBoxCss = ".messagesBox {position: fixed !important; top: 0% !important; width: 100% !important; z-index: 99999999 !important;}"; GM_addStyle(messagesBoxCss); const containerErrorsCss = ".containerErrors {position: fixed !important; top: 0% !important; max-height: 400px !important; width: 100% !important; overflow-y: scroll !important; z-index: 99999999 !important;}"; GM_addStyle(containerErrorsCss); const containerSvgCss = ".svgContainer {position: fixed !important; bottom: 0% !important; max-height: 50px !important; width: 100% !important; z-index: 99999999 !important;}"; GM_addStyle(containerSvgCss); window.addEventListener("load", function() { if (window) { let _onerror = function(event, url, lineNo, columnNo, error) { let eventMessage = event.message ? event.message.toLowerCase() : ""; if (!eventMessage) { eventMessage = event.target.id || event.target.src; } let substring = "script error"; if (eventMessage.indexOf(substring) > -1) { alert("Script Error: See Browser Console for Detail"); } else { let message = [ "Message: " + eventMessage, "URL: " + url, "Line: " + lineNo, "Column: " + columnNo, "Error object: " + JSON.stringify(error) ].join(" - "); console.error(message); } //GM_notification('text', 'title', 'https://store-images.s-microsoft.com/image/apps.32031.13510798887630003.b4c5c861-c9de-4301-99ce-5af68bf21fd1.ba559483-bc2c-4eb9-a17e-c302009b2690?w=180&h=180&q=60', ()=>{console.log('click');}) return false; }; // Handle Uncaught Errors window.onerror = function() { let args = Array.prototype.slice.call(arguments); // logger.error(args); if (_onerror) { return _onerror.apply(window, args); } return false; }; } window.addEventListener("unhandledrejection", function(promiseRejectionEvent) { console.error("window.rejectionhandled: " + (promiseRejectionEvent.reason.message || promiseRejectionEvent.error || promiseRejectionEvent)); }); window.addEventListener("rejectionhandled", function(promiseRejectionEvent) { console.error("window.rejectionhandled: " + (promiseRejectionEvent.reason.message || promiseRejectionEvent.error || promiseRejectionEvent)); }); window.addEventListener("error", function(errorEvent) { console.error("window.error: " + (event.reason.message || errorEvent.error || errorEvent)); }); window.addEventListener("fetch", function(event) { console.warn("window.fetch: " + (event.reason.message || event.error || event)); event.respondWith( fetch(event.request) ); }); $.error = function(message) { //alert(["jQuery error", message || e.error].join()); console.error("jQuery: " + message); }; $.ajax({ url: window.location.href, success: function(data, textStatus, event) { let time = (new Date() - startTime) + "ms"; console.info(event.status + " " + window.location.href + " " + time); }, error: function(error) { console.error(event.status + " " + window.location.href + " " + event.statusText); } }); (function(XHR) { "use strict"; let stats = []; let timeoutId = null; let open = XHR.prototype.open; let send = XHR.prototype.send; XHR.prototype.open = function(method, url, async, user, pass) { this._url = url; open.call(this, method, url, async, user, pass); }; function sendToConsole(event, stats) { stats.forEach((stat) => { if (stat.statusCode >= 200 && stat.statusCode < 400) { console.info(stat); } else if (stat.statusCode === 404) { console.warn(stat); } else { console.error(stat); } }); } //Monkey patch send to be able to profile responses time and log it XHR.prototype.send = function(data) { let self = this; let start; let oldOnReadyStateChange; let url = this._url; function onReadyStateChange(event) { //Info: Log all you need from event if (self.readyState === 4 /* complete */) { let time = new Date() - start; stats.push({ url: url, duration: time + "ms", statusCode: event.currentTarget.status }); if (!timeoutId) { timeoutId = window.setTimeout(function() { sendToConsole(event, stats); timeoutId = null; stats = []; }, 2000); } } if (oldOnReadyStateChange) { oldOnReadyStateChange(); } } if (!this.noIntercept) { start = new Date(); if (this.addEventListener) { this.addEventListener("readystatechange", onReadyStateChange, false); } else { oldOnReadyStateChange = this.onreadystatechange; this.onreadystatechange = onReadyStateChange; } } send.call(this, data); }; })(XMLHttpRequest); }); } )();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址