backtrace-js
Advanced tools
Comparing version 0.0.5 to 0.0.6
116
lib/index.js
@@ -5,3 +5,3 @@ exports.report = report; | ||
var myVersion = "0.0.5"; // should match package.json | ||
var myVersion = "0.0.6"; // should match package.json | ||
var initialized = false; | ||
@@ -20,2 +20,4 @@ var uuidArray = new Uint8Array(16); | ||
var contextLineCount; | ||
var filter; | ||
var sampling; | ||
@@ -36,2 +38,4 @@ function report(err, attributes, callback) { | ||
token = options.token; | ||
filter = options.filter; | ||
sampling = options.sampling; | ||
userAttributes = extend({}, options.attributes || {}); | ||
@@ -43,4 +47,6 @@ contextLineCount = options.contextLineCount || 200; | ||
if (!endpoint) console.error(new Error("Backtrace: missing 'endpoint' option.").stack); | ||
if (!token) console.error(new Error("Backtrace: missing 'token' option.").stack); | ||
if (!endpoint) | ||
console.error(new Error("Backtrace: missing 'endpoint' option.").stack); | ||
if (!token) | ||
console.error(new Error("Backtrace: missing 'token' option.").stack); | ||
@@ -58,3 +64,3 @@ if (!disableGlobalHandler) { | ||
function registerGlobalHandler() { | ||
window.addEventListener('error', onGlobalError, false); | ||
window.addEventListener("error", onGlobalError, false); | ||
@@ -71,3 +77,3 @@ function onGlobalError(ev) { | ||
function registerPromiseHandler() { | ||
window.addEventListener('unhandledrejection', onGlobalPromiseRejected, false); | ||
window.addEventListener("unhandledrejection", onGlobalPromiseRejected, false); | ||
@@ -92,8 +98,15 @@ function onGlobalPromiseRejected(ev) { | ||
agentVersion: myVersion, | ||
attributes: extend({ | ||
"process.age": getUptime(), | ||
"user.agent": navigator.userAgent, | ||
}, userAttributes), | ||
attributes: extend( | ||
{ | ||
"process.age": getUptime(), | ||
"user.agent": navigator.userAgent | ||
"hostname": window.location && window.location.hostname | ||
"referer": window.location && window.location.href | ||
}, | ||
userAttributes | ||
), | ||
annotations: {}, | ||
tabWidth: tabWidth, | ||
threads: { default: { stack: [] } }, | ||
mainThread: "default" | ||
}; | ||
@@ -107,3 +120,3 @@ this.logLines = []; | ||
this.report.classifiers = [err.name]; | ||
this.report.attributes['error.message'] = err.message; | ||
this.report.attributes["error.message"] = err.message; | ||
this.report.sourceCode = {}; | ||
@@ -126,3 +139,3 @@ | ||
wantedSourceCode[sourceCodePath] = wantedSourceCode[sourceCodePath] || []; | ||
wantedSourceCode[sourceCodePath].push({line: line, column: column}); | ||
wantedSourceCode[sourceCodePath].push({ line: line, column: column }); | ||
@@ -134,3 +147,3 @@ var frame = { | ||
sourceCode: sourceCodePath, | ||
library: sourceCodePath, | ||
library: sourceCodePath | ||
}; | ||
@@ -142,4 +155,4 @@ stackArray.push(frame); | ||
main: { | ||
stack: stackArray, | ||
}, | ||
stack: stackArray | ||
} | ||
}; | ||
@@ -150,3 +163,3 @@ this.report.mainThread = "main"; | ||
this.report.sourceCode[sourceCodePath] = { | ||
path: sourceCodePath, | ||
path: sourceCodePath | ||
}; | ||
@@ -162,3 +175,4 @@ } | ||
first = false; | ||
queryString += encodeURIComponent(key) + "=" + encodeURIComponent(query[key]); | ||
queryString += | ||
encodeURIComponent(key) + "=" + encodeURIComponent(query[key]); | ||
} | ||
@@ -171,12 +185,18 @@ return endpoint + path + queryString; | ||
if (filter && !filter(this.report)) { | ||
return; | ||
} else if (sampling && Math.random() > sampling) { | ||
return; | ||
} | ||
var reportedError = false; | ||
var postString = JSON.stringify(this.report); | ||
var query = {token: token, format: 'json'}; | ||
var query = { token: token, format: "json" }; | ||
var fullUrl = makeFullUrl(endpoint, "/post", query); | ||
var req = new XMLHttpRequest(); | ||
req.addEventListener('readystatechange', onReadyStateChange, false); | ||
req.addEventListener('error', onErrorEvent, false); | ||
req.open('POST', fullUrl); | ||
req.setRequestHeader('Content-Type', 'text/plain'); | ||
req.addEventListener("readystatechange", onReadyStateChange, false); | ||
req.addEventListener("error", onErrorEvent, false); | ||
req.open("POST", fullUrl); | ||
req.setRequestHeader("Content-Type", "text/plain"); | ||
req.send(postString); | ||
@@ -199,3 +219,3 @@ | ||
} | ||
function onErrorEvent(ev) { | ||
@@ -208,4 +228,7 @@ reportError(new Error("request failed")); | ||
if (!isValidAttr(value)) { | ||
console.error(new Error("Attempted to add attribute with invalid type '" + | ||
typeof(value) + "'").stack); | ||
console.error( | ||
new Error( | ||
"Attempted to add attribute with invalid type '" + typeof value + "'" | ||
).stack | ||
); | ||
return; | ||
@@ -220,3 +243,9 @@ } | ||
var allowPrivateProps = !!options.allowPrivateProps; | ||
addAttrs(this.report.attributes, new Set(), prefix, object, allowPrivateProps); | ||
addAttrs( | ||
this.report.attributes, | ||
new Set(), | ||
prefix, | ||
object, | ||
allowPrivateProps | ||
); | ||
}; | ||
@@ -233,3 +262,3 @@ | ||
ts: new Date(), | ||
msg: msg, | ||
msg: msg | ||
}); | ||
@@ -239,4 +268,6 @@ }; | ||
BacktraceReport.prototype.addAnnotation = function(key, value) { | ||
if (typeof(key) !== 'string') { | ||
console.error(new Error("Attempted to add annotation with non-string key").stack); | ||
if (typeof key !== "string") { | ||
console.error( | ||
new Error("Attempted to add annotation with non-string key").stack | ||
); | ||
return; | ||
@@ -252,4 +283,8 @@ } | ||
} catch (err) { | ||
console.error(new Error("Attempted to add annotation which could not be JSON serialized: " + | ||
err.message).stack); | ||
console.error( | ||
new Error( | ||
"Attempted to add annotation which could not be JSON serialized: " + | ||
err.message | ||
).stack | ||
); | ||
return; | ||
@@ -268,3 +303,5 @@ } | ||
if (err instanceof Error) return true; | ||
console.error(new Error("Attempted to report error with non Error type").stack); | ||
console.error( | ||
new Error("Attempted to report error with non Error type").stack | ||
); | ||
return false; | ||
@@ -291,7 +328,7 @@ } | ||
var s = b.toString(16); | ||
return (b < 0x10) ? ("0" + s) : s; | ||
return b < 0x10 ? "0" + s : s; | ||
} | ||
function getTimestamp() { | ||
return Math.floor((new Date()).getTime() / 1000) | ||
return Math.floor(new Date().getTime() / 1000); | ||
} | ||
@@ -309,5 +346,7 @@ | ||
function isValidAttr(value) { | ||
return (typeof(value) === 'string' || | ||
typeof(value) === 'boolean' || | ||
typeof(value) === 'number'); | ||
return ( | ||
typeof value === "string" || | ||
typeof value === "boolean" || | ||
typeof value === "number" | ||
); | ||
} | ||
@@ -321,7 +360,7 @@ | ||
if (!obj.hasOwnProperty(key)) continue; | ||
if (!allowPrivateProps && key[0] === '_') continue; | ||
if (!allowPrivateProps && key[0] === "_") continue; | ||
var value = obj[key]; | ||
if (isValidAttr(value)) { | ||
attributes[prefix + key] = value; | ||
} else if (!Array.isArray(value) && typeof(value) === 'object') { | ||
} else if (!Array.isArray(value) && typeof value === "object") { | ||
addAttrs(attributes, seenObjs, key + ".", value, allowPrivateProps); | ||
@@ -331,2 +370,1 @@ } | ||
} | ||
{ | ||
"name": "backtrace-js", | ||
"version": "0.0.5", | ||
"version": "0.0.6", | ||
"description": "Backtrace.io error reporting tool for client-side applications", | ||
"main": "lib/index.js", | ||
"author": "Andrew Kelley <akelley@backtrace.io>", | ||
"author": "Backtrace <team@backtrace.io>", | ||
"license": "MIT", | ||
@@ -8,0 +8,0 @@ "devDependencies": { |
@@ -24,2 +24,34 @@ # backtrace-js | ||
### bt.initialize([options]) | ||
This is intended to be one of the first things your application does during | ||
initialization. It registers a handler for `uncaughtException` which will | ||
spawn a detached child process to perform the error report and then crash | ||
in the same way that your application would have crashed without the handler. | ||
#### Options | ||
See [backtrace-node](https://github.com/backtrace-labs/backtrace-node#documentation)'s documentation for the complete options list. | ||
In addition to all [backtrace-node](https://github.com/backtrace-labs/backtrace-node#documentation)'s options, Backtrace-JS includes `sampling` and `filter`. | ||
##### `sampling` | ||
Optional. | ||
Sets a percentage of reports which should be sent. | ||
For example, `sampling: 0.25` would send 25/100 reports. | ||
##### `filter` | ||
Optional. | ||
Set a pre-send function which allows custom filtering of reports. | ||
This function accepts the backtrace report object and should return `true` if the report SHOULD be sent or return `false` if the report should NOT be sent. | ||
Example: | ||
``` | ||
filter: function(report) { | ||
if (report.attributes["error.message"] == "Script Error.") { | ||
return Math.random() >= 0.5; // Sample half of this kind of report | ||
} | ||
return true; // Otherwise, always send the report | ||
} | ||
``` | ||
## Testing | ||
@@ -26,0 +58,0 @@ |
@@ -1,13 +0,21 @@ | ||
var bt = require('../lib/index'); | ||
var bt = require("../lib/index"); | ||
bt.initialize({ | ||
token: "my test token", | ||
endpoint: "http://localhost:11369", | ||
endpoint: "http://localhost:11369" | ||
// sampling: 0.25, // Should send 25/100 caught errors | ||
// filter: function(report) { | ||
// if (report.attributes["error.message"] == "Script Error.") { | ||
// var shouldSend = Math.random() >= 0.5; | ||
// return shouldSend; | ||
// } | ||
// return true; | ||
// } | ||
}); | ||
var btnDom = document.getElementById('error-button'); | ||
var btnDom = document.getElementById("error-button"); | ||
btnDom.addEventListener('click', onBtnClick, false); | ||
btnDom.addEventListener("click", onBtnClick, false); | ||
function onBtnClick(ev) { | ||
badFnCall() | ||
badFnCall(); | ||
} |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
12903
353
70
1