Created
April 11, 2013 03:59
-
-
Save cheeaun/5360637 to your computer and use it in GitHub Desktop.
Crittercism's JS lib for logging errors/exceptions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var Crittercism = function () { | |
| function l(a) { | |
| var a = a || { | |
| guess: !0 | |
| }, b = a.e || null, | |
| a = !! a.guess, | |
| c = new l.implementation, | |
| b = c.run(b); | |
| return a ? c.guessAnonymousFunctions(b) : b | |
| } | |
| var k = null, | |
| B = null, | |
| m = !1, | |
| i = function () { | |
| try { | |
| return "localStorage" in window && null !== window.localStorage | |
| } catch (a) { | |
| return !1 | |
| } | |
| }, n = function () { | |
| i() && (localStorage["Crittercism.last_seen"] = (new Date).toString()) | |
| }, C = function () { | |
| var a = localStorage.getItem("Crittercism.last_seen"); | |
| if (a) try { | |
| return new Date(a) | |
| } catch (b) { | |
| return null | |
| } else return null | |
| }, t = function () { | |
| if (i()) try { | |
| return localStorage.getItem("Crittercism.did") | |
| } catch (a) { | |
| return "" | |
| } else return "" | |
| }, | |
| j = null, | |
| q = !1, | |
| r = [], | |
| w = 0, | |
| u = function (a) { | |
| q ? j.postMessage(a, "*") : r.push(a) | |
| }, D = function () { | |
| for (; message = r.pop();) j.postMessage(message, "*") | |
| }, o = function (a) { | |
| switch (a.data.type) { | |
| case "iframeSyn": | |
| j = a.source; | |
| j.postMessage({ | |
| type: "clientSynAck" | |
| }, "*"); | |
| break; | |
| case "iframeSynAck": | |
| j = a.source; | |
| j.postMessage({ | |
| type: "clientAck" | |
| }, "*"); | |
| q = !0; | |
| D(); | |
| break; | |
| case "iframeAck": | |
| q = !0; | |
| D(); | |
| break; | |
| case "setDeviceId": | |
| a = a.data.contents.deviceId, i() && localStorage.setItem("Crittercism.did", a) | |
| } | |
| }; | |
| "undefined" === typeof inTest && window.addEventListener("message", | |
| o, !1); | |
| document.getElementById("crittercism_iframe") && (j = document.getElementById("crittercism_iframe"), j.postMessage({ | |
| type: "clientSyn" | |
| }, "*")); | |
| l.implementation = function () {}; | |
| l.implementation.prototype = { | |
| run: function (a, b) { | |
| a = a || this.createException(); | |
| b = b || this.mode(a); | |
| return b === "other" ? this.other(arguments.callee) : this[b](a) | |
| }, | |
| createException: function () { | |
| try { | |
| this.undef() | |
| } catch (a) { | |
| return a | |
| } | |
| }, | |
| mode: function (a) { | |
| return a.arguments && a.stack ? "chrome" : typeof a.message === "string" && typeof window !== "undefined" && window.opera ? !a.stacktrace || a.message.indexOf("\n") > -1 && a.message.split("\n").length > a.stacktrace.split("\n").length ? "opera9" : !a.stack ? "opera10a" : a.stacktrace.indexOf("called from line") < 0 ? "opera10b" : "opera11" : a.stack ? "firefox" : "other" | |
| }, | |
| instrumentFunction: function (a, b, c) { | |
| var a = a || window, | |
| d = a[b]; | |
| a[b] = function () { | |
| c.call(this, l().slice(4)); | |
| return a[b]._instrumented.apply(this, arguments) | |
| }; | |
| a[b]._instrumented = d | |
| }, | |
| deinstrumentFunction: function (a, b) { | |
| if (a[b].constructor === Function && a[b]._instrumented && a[b]._instrumented.constructor === | |
| Function) a[b] = a[b]._instrumented | |
| }, | |
| chrome: function (a) { | |
| a = (a.stack + "\n").replace(/^\S[^\(]+?[\n$]/gm, "").replace(/^\s+(at eval )?at\s+/gm, "").replace(/^([^\(]+?)([\n$])/gm, "{anonymous}()@$1$2").replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm, "{anonymous}()@$1").split("\n"); | |
| a.pop(); | |
| return a | |
| }, | |
| firefox: function (a) { | |
| return a.stack.replace(/(?:\n@:0)?\s+$/m, "").replace(/^\(/gm, "{anonymous}(").split("\n") | |
| }, | |
| opera11: function (a) { | |
| for (var b = /^.*line (\d+), column (\d+)(?: in (.+))? in (\S+):$/, a = a.stacktrace.split("\n"), | |
| c = [], d = 0, f = a.length; d < f; d = d + 2) { | |
| var e = b.exec(a[d]); | |
| if (e) { | |
| var g = e[4] + ":" + e[1] + ":" + e[2], | |
| e = e[3] || "global code", | |
| e = e.replace(/<anonymous function: (\S+)>/, "$1").replace(/<anonymous function>/, "{anonymous}"); | |
| c.push(e + "@" + g + " -- " + a[d + 1].replace(/^\s+/, "")) | |
| } | |
| } | |
| return c | |
| }, | |
| opera10b: function (a) { | |
| for (var b = /^(.*)@(.+):(\d+)$/, a = a.stacktrace.split("\n"), c = [], d = 0, f = a.length; d < f; d++) { | |
| var e = b.exec(a[d]); | |
| e && c.push((e[1] ? e[1] + "()" : "global code") + "@" + e[2] + ":" + e[3]) | |
| } | |
| return c | |
| }, | |
| opera10a: function (a) { | |
| for (var b = /Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i, | |
| a = a.stacktrace.split("\n"), c = [], d = 0, f = a.length; d < f; d = d + 2) { | |
| var e = b.exec(a[d]); | |
| e && c.push((e[3] || "{anonymous}") + "()@" + e[2] + ":" + e[1] + " -- " + a[d + 1].replace(/^\s+/, "")) | |
| } | |
| return c | |
| }, | |
| opera9: function (a) { | |
| for (var b = /Line (\d+).*script (?:in )?(\S+)/i, a = a.message.split("\n"), c = [], d = 2, f = a.length; d < f; d = d + 2) { | |
| var e = b.exec(a[d]); | |
| e && c.push("{anonymous}()@" + e[2] + ":" + e[1] + " -- " + a[d + 1].replace(/^\s+/, "")) | |
| } | |
| return c | |
| }, | |
| other: function (a) { | |
| for (var b = /function\s*([\w\-$]+)?\s*\(/i, c = [], d, f; a && a.arguments && c.length < 10;) { | |
| d = b.test(a.toString()) ? | |
| RegExp.$1 || "{anonymous}" : "{anonymous}"; | |
| f = Array.prototype.slice.call(a.arguments || []); | |
| c[c.length] = d + "(" + this.stringifyArguments(f) + ")"; | |
| a = a.caller | |
| } | |
| return c | |
| }, | |
| stringifyArguments: function (a) { | |
| for (var b = [], c = Array.prototype.slice, d = 0; d < a.length; ++d) { | |
| var f = a[d]; | |
| f === void 0 ? b[d] = "undefined" : f === null ? b[d] = "null" : f.constructor && (f.constructor === Array ? b[d] = f.length < 3 ? "[" + this.stringifyArguments(f) + "]" : "[" + this.stringifyArguments(c.call(f, 0, 1)) + "..." + this.stringifyArguments(c.call(f, -1)) + "]" : f.constructor === Object ? | |
| b[d] = "#object" : f.constructor === Function ? b[d] = "#function" : f.constructor === String ? b[d] = '"' + f + '"' : f.constructor === Number && (b[d] = f)) | |
| } | |
| return b.join(",") | |
| }, | |
| sourceCache: {}, | |
| ajax: function (a) { | |
| var b = this.createXMLHTTPObject(); | |
| if (b) try { | |
| b.open("GET", a, false); | |
| b.send(null); | |
| return b.responseText | |
| } catch (c) {} | |
| return "" | |
| }, | |
| createXMLHTTPObject: function () { | |
| for (var a, b = [function () { | |
| return new XMLHttpRequest | |
| }, function () { | |
| return new ActiveXObject("Msxml2.XMLHTTP") | |
| }, function () { | |
| return new ActiveXObject("Msxml3.XMLHTTP") | |
| }, function () { | |
| return new ActiveXObject("Microsoft.XMLHTTP") | |
| } | |
| ], | |
| c = 0; c < b.length; c++) try { | |
| a = b[c](); | |
| this.createXMLHTTPObject = b[c]; | |
| return a | |
| } catch (d) {} | |
| }, | |
| isSameDomain: function (a) { | |
| return typeof location !== "undefined" && a.indexOf(location.hostname) !== -1 | |
| }, | |
| getSource: function (a) { | |
| a in this.sourceCache || (this.sourceCache[a] = this.ajax(a).split("\n")); | |
| return this.sourceCache[a] | |
| }, | |
| guessAnonymousFunctions: function (a) { | |
| for (var b = 0; b < a.length; ++b) { | |
| var c = /^(.*?)(?::(\d+))(?::(\d+))?(?: -- .+)?$/, | |
| d = a[b], | |
| f = /\{anonymous\}\(.*\)@(.*)/.exec(d); | |
| if (f) { | |
| var e = c.exec(f[1]); | |
| if (e) { | |
| c = e[1]; | |
| f = e[2]; | |
| e = e[3] || 0; | |
| if (c && this.isSameDomain(c) && f) { | |
| c = this.guessAnonymousFunction(c, f, e); | |
| a[b] = d.replace("{anonymous}", c) | |
| } | |
| } | |
| } | |
| } | |
| return a | |
| }, | |
| guessAnonymousFunction: function (a, b) { | |
| var c; | |
| try { | |
| c = this.findFunctionName(this.getSource(a), b) | |
| } catch (d) { | |
| c = "getSource failed with url: " + a + ", exception: " + d.toString() | |
| } | |
| return c | |
| }, | |
| findFunctionName: function (a, b) { | |
| for (var c = /function\s+([^(]*?)\s*\(([^)]*)\)/, d = /['"]?([0-9A-Za-z_]+)['"]?\s*[:=]\s*function\b/, f = /['"]?([0-9A-Za-z_]+)['"]?\s*[:=]\s*(?:eval|new Function)\b/, e = "", g, h = Math.min(b, | |
| 20), i, j = 0; j < h; ++j) { | |
| g = a[b - j - 1]; | |
| i = g.indexOf("//"); | |
| i >= 0 && (g = g.substr(0, i)); | |
| if (g) { | |
| e = g + e; | |
| if ((g = d.exec(e)) && g[1]) return g[1]; | |
| if ((g = c.exec(e)) && g[1]) return g[1]; | |
| if ((g = f.exec(e)) && g[1]) return g[1] | |
| } | |
| } | |
| return "(?)" | |
| } | |
| }; | |
| var E = function (a) { | |
| for (var b = [], c = [/^crittercismErrorHandler/i, /^printStackTrace/i], d = 0, f = a.length; d < f; d++) { | |
| for (var e = a[d], g = false, h = 0, i = c.length; h < i; h++) if (e.match(c[h])) { | |
| g = true; | |
| break | |
| } | |
| g || b.push(e) | |
| } | |
| return b | |
| }, F, h = { | |
| metadata: {} | |
| }, x = !1, | |
| y = function (a) { | |
| return typeof a == "undefined" || a == null || a == "" | |
| }, G = function () { | |
| battery = | |
| null; | |
| if (navigator.battery) battery = navigator.battery.level; | |
| else if (navigator.mozBattery) battery = navigator.mozBattery.level; | |
| else if (navigator.webkitBattery) battery = navigator.webkitBattery.level; | |
| return battery | |
| }, H = function () { | |
| u({ | |
| type: "metadata", | |
| contents: { | |
| app_id: k, | |
| device_id: t(), | |
| library_version: "pre", | |
| device_name: "html5", | |
| metadata: h.metadata | |
| } | |
| }) | |
| }, J = function () { | |
| if (i()) try { | |
| return JSON.parse(localStorage.getItem("Crittercism.app_state")) || {} | |
| } catch (a) { | |
| return h || {} | |
| } else return h || {} | |
| }, z = function () { | |
| var a = J(); | |
| if (i()) { | |
| for (var b = | |
| h, c = 0, d = 0; d < localStorage.length; d++) { | |
| var f = localStorage.key(d), | |
| c = c + f.length * 2; | |
| y(localStorage.getItem(f)) || (c = c + localStorage.getItem(localStorage.key(d)).length * 2) | |
| } | |
| b.local_storage = c | |
| } | |
| G() && (a.battery_level = G()); | |
| a.app_version = F; | |
| return a | |
| }; | |
| window.onerror = function (a) { | |
| ++w; | |
| var b = E(l({ | |
| e: a, | |
| guess: true | |
| })); | |
| u({ | |
| type: "crash", | |
| contents: { | |
| app_id: k, | |
| app_state: z(), | |
| breadcrumbs: s, | |
| did: t(), | |
| exception_name: "Error", | |
| exception_reason: a, | |
| library_version: "pre", | |
| unsymbolized_stacktrace: b | |
| } | |
| }); | |
| return true | |
| }; | |
| var s; | |
| i() ? (o = localStorage.getItem("Crittercism.breadcrumbs") || | |
| "[]", o = JSON.parse(o)) : o = []; | |
| s = { | |
| current_session: [], | |
| previous_session: o | |
| }; | |
| var K = function () { | |
| function a(a) { | |
| return a < 10 ? "0" + a : a | |
| } | |
| var b = new Date; | |
| return b.getUTCFullYear() + "-" + a(b.getUTCMonth() + 1) + "-" + a(b.getUTCDate()) + "T" + a(b.getUTCHours()) + ":" + a(b.getUTCMinutes()) + ":" + a(b.getUTCSeconds()) + "Z" | |
| }, p = [], | |
| A = null, | |
| I = 21, | |
| v = null, | |
| L = function (a) { | |
| if (p.length < 20) { | |
| var b = a && typeof a.name == "string" ? a.name : "Unknown Exception (No name passed by caller)", | |
| a = a && typeof a.message == "string" ? a.message : "Unknown Exception Reason (No reason passed by caller)", | |
| c = E(l({ | |
| e: a, | |
| guess: true | |
| })), | |
| b = { | |
| type: "handled_exception", | |
| contents: { | |
| app_id: k, | |
| hashed_device_id: t(), | |
| library_version: "pre", | |
| exceptions: [{ | |
| library_version: "pre", | |
| exception_name: b, | |
| exception_reason: a, | |
| library_version: "pre", | |
| state: z(), | |
| unsymbolized_stacktrace: c | |
| } | |
| ] | |
| } | |
| }; | |
| p.push(b) | |
| } | |
| return this | |
| }; | |
| return { | |
| init: function (a) { | |
| m = true; | |
| k = a.appId; | |
| F = a.appVersion || "unspecified"; | |
| B = a._iframeSrc || "https://api.crittercism.com/html5-static/html/iframe.html"; | |
| if (document.getElementById("critterframe") == null) { | |
| a = document.createElement("iframe"); | |
| a.id = "critterframe"; | |
| a.src = B; | |
| a.style.display = "none"; | |
| document.body.appendChild(a) | |
| } | |
| if (a = x == false) if (i()) a = (a = C()) ? new Date - a >= 18E5 ? true : false : true; | |
| else a = true; | |
| if (a) { | |
| u({ | |
| type: "appLoad", | |
| contents: { | |
| app_id: k, | |
| did: t(), | |
| library_version: "pre", | |
| app_state: z() | |
| } | |
| }); | |
| x = true | |
| } | |
| n(); | |
| return this | |
| }, | |
| setMetadata: function (a) { | |
| if (m) { | |
| h.metadata.username && y(a.username) && (a.username = h.metadata.username); | |
| h.metadata = a; | |
| H() | |
| } else throw Error("Crittercism.init call required before setMetadata"); | |
| n(); | |
| return this | |
| }, | |
| setValue: function (a, b) { | |
| if (m) { | |
| y(a) || | |
| (h.metadata[a] = b); | |
| H() | |
| } else throw Error("Crittercism.init call required before setValue"); | |
| n(); | |
| return this | |
| }, | |
| setUsername: function (a) { | |
| if (m) h.metadata.username = a; | |
| else throw Error("Crittercism.init call required before setUsername"); | |
| n(); | |
| return this | |
| }, | |
| logHandledException: function (a) { | |
| if (m) { | |
| L(a); | |
| var b = function () { | |
| v = p.length; | |
| v > 0 && u(p.pop()); | |
| A = v != 0 || I != 0 ? window.setTimeout(b, 2E4) : null; | |
| I = v | |
| }; | |
| A == null && b() | |
| } else throw Error("Crittercism.init call required before logHandledException"); | |
| n(); | |
| return this | |
| }, | |
| leaveBreadcrumb: function (a) { | |
| if (m) if (typeof a == | |
| "string") { | |
| s.current_session.push([a, K()]); | |
| i() && (localStorage["Crittercism.breadcrumbs"] = JSON.stringify(s.current_session)) | |
| } else throw Error("Invalid breadcrumb type; must be a string"); | |
| else throw Error("Crittercism.init call required before leaveBreadcrumb"); | |
| n(); | |
| return this | |
| }, | |
| _dumpState: function () { | |
| return { | |
| appId: k, | |
| appState: h, | |
| breadcrumbs: s, | |
| communicationReady: q, | |
| crashesRecorded: w, | |
| messageQueue: r.slice(), | |
| lastSeen: C(), | |
| handledExceptionQueue: p, | |
| exceptionSendTimer: A | |
| } | |
| }, | |
| _reset: function () { | |
| x = q = k = false; | |
| h = {}; | |
| r = [] | |
| }, | |
| _crashesRecorded: function () { | |
| return w | |
| }, | |
| _resetQueues: function () { | |
| r = []; | |
| p = [] | |
| } | |
| } | |
| }(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment