UNPKG

rollbar

Version:

Effortlessly track and debug errors in your JavaScript applications with Rollbar. This package includes advanced error tracking features and an intuitive interface to help you identify and fix issues more quickly.

358 lines (313 loc) 8.85 kB
import errorParser from '../errorParser.js'; import logger from '../logger.js'; import * as _ from '../utility.js'; function handleDomException(item, options, callback) { if (item.err && errorParser.Stack(item.err).name === 'DOMException') { var originalError = new Error(); originalError.name = item.err.name; originalError.message = item.err.message; originalError.stack = item.err.stack; originalError.nested = item.err; item.err = originalError; } callback(null, item); } function handleItemWithError(item, options, callback) { item.data = item.data || {}; if (item.err) { try { item.stackInfo = item.err._savedStackTrace || errorParser.parse(item.err, item.skipFrames); if (options.addErrorContext) { addErrorContext(item); } } catch (e) { logger.error('Error while parsing the error object.', e); try { item.message = item.err.message || item.err.description || item.message || String(item.err); } catch (e2) { item.message = String(item.err) || String(e2); } delete item.err; } } callback(null, item); } function addErrorContext(item) { var chain = []; var err = item.err; chain.push(err); while (err.nested || err.cause) { err = err.nested || err.cause; chain.push(err); } _.addErrorContext(item, chain); } function ensureItemHasSomethingToSay(item, options, callback) { if (!item.message && !item.stackInfo && !item.custom) { callback(new Error('No message, stack info, or custom data'), null); } callback(null, item); } function addBaseInfo(item, options, callback) { var environment = (options.payload && options.payload.environment) || options.environment; item.data = _.merge(item.data, { environment: environment, level: item.level, endpoint: options.endpoint, platform: 'browser', framework: 'browser-js', language: 'javascript', server: {}, uuid: item.uuid, notifier: { name: 'rollbar-browser-js', version: options.version, }, custom: item.custom, }); callback(null, item); } function addRequestInfo(window) { return function (item, options, callback) { var requestInfo = {}; if (window && window.location) { requestInfo.url = window.location.href; requestInfo.query_string = window.location.search; } var remoteString = '$remote_ip'; if (!options.captureIp) { remoteString = null; } else if (options.captureIp !== true) { remoteString += '_anonymize'; } if (remoteString) requestInfo.user_ip = remoteString; if (Object.keys(requestInfo).length > 0) { _.set(item, 'data.request', requestInfo); } callback(null, item); }; } function addClientInfo(window) { return function (item, options, callback) { if (!window) { return callback(null, item); } var nav = window.navigator || {}; var scr = window.screen || {}; _.set(item, 'data.client', { runtime_ms: item.timestamp - window._rollbarStartTime, timestamp: Math.round(item.timestamp / 1000), javascript: { browser: nav.userAgent, language: nav.language, cookie_enabled: nav.cookieEnabled, screen: { width: scr.width, height: scr.height, }, }, }); callback(null, item); }; } function addPluginInfo(window) { return function (item, options, callback) { if (!window || !window.navigator) { return callback(null, item); } var plugins = []; var navPlugins = window.navigator.plugins || []; var cur; for (var i = 0, l = navPlugins.length; i < l; ++i) { cur = navPlugins[i]; plugins.push({ name: cur.name, description: cur.description }); } _.set(item, 'data.client.javascript.plugins', plugins); callback(null, item); }; } function addBody(item, options, callback) { if (item.stackInfo) { if (item.stackInfo.traceChain) { addBodyTraceChain(item, options, callback); } else { addBodyTrace(item, options, callback); } } else { addBodyMessage(item, options, callback); } } function addBodyMessage(item, options, callback) { var message = item.message; var custom = item.custom; if (!message) { message = 'Item sent with null or missing arguments.'; } var result = { body: message, }; if (custom) { result.extra = _.merge(custom); } _.set(item, 'data.body', { message: result }); callback(null, item); } function stackFromItem(item, stackInfo = null) { // Transform a TraceKit stackInfo object into a Rollbar trace let stack = (stackInfo || item.stackInfo).stack; if ( stack && stack.length === 0 && item._unhandledStackInfo && item._unhandledStackInfo.stack ) { stack = item._unhandledStackInfo.stack; } return stack; } function addBodyTraceChain(item, options, callback) { var traceChain = item.stackInfo.traceChain; var traces = []; var traceChainLength = traceChain.length; for (var i = 0; i < traceChainLength; i++) { var trace = buildTrace(item, traceChain[i], options); traces.push(trace); } _.set(item, 'data.body', { trace_chain: traces }); callback(null, item); } function addBodyTrace(item, options, callback) { var stack = stackFromItem(item); if (stack) { var trace = buildTrace(item, item.stackInfo, options); _.set(item, 'data.body', { trace: trace }); callback(null, item); } else { var stackInfo = item.stackInfo; var guess = errorParser.guessErrorClass(stackInfo.message); var className = errorClass(stackInfo, guess[0], options); var message = guess[1]; item.message = className + ': ' + message; addBodyMessage(item, options, callback); } } function buildTrace(item, stackInfo, options) { var description = item && item.data.description; var custom = item && item.custom; var stack = stackFromItem(item, stackInfo); var guess = errorParser.guessErrorClass(stackInfo.message); var className = errorClass(stackInfo, guess[0], options); var message = guess[1]; var trace = { exception: { class: className, message: message, }, }; if (description) { trace.exception.description = description; } if (stack) { if (stack.length === 0) { trace.exception.stack = stackInfo.rawStack; trace.exception.raw = String(stackInfo.rawException); } var stackFrame; var frame; var code; var pre; var post; var contextLength; var i, mid; trace.frames = []; for (i = 0; i < stack.length; ++i) { stackFrame = stack[i]; frame = { filename: stackFrame.url ? _.sanitizeUrl(stackFrame.url) : '(unknown)', lineno: stackFrame.line || null, method: !stackFrame.func || stackFrame.func === '?' ? '[anonymous]' : stackFrame.func, colno: stackFrame.column, }; if (options.sendFrameUrl) { frame.url = stackFrame.url; } if ( frame.method && frame.method.endsWith && frame.method.endsWith('_rollbar_wrapped') ) { continue; } code = pre = post = null; contextLength = stackFrame.context ? stackFrame.context.length : 0; if (contextLength) { mid = Math.floor(contextLength / 2); pre = stackFrame.context.slice(0, mid); code = stackFrame.context[mid]; post = stackFrame.context.slice(mid); } if (code) { frame.code = code; } if (pre || post) { frame.context = {}; if (pre && pre.length) { frame.context.pre = pre; } if (post && post.length) { frame.context.post = post; } } if (stackFrame.args) { frame.args = stackFrame.args; } trace.frames.push(frame); } // NOTE(cory): reverse the frames since rollbar.com expects the most recent call last trace.frames.reverse(); if (custom) { trace.extra = _.merge(custom); } } return trace; } function errorClass(stackInfo, guess, options) { if (stackInfo.name) { return stackInfo.name; } else if (options.guessErrorClass) { return guess; } else { return '(unknown)'; } } function addScrubber(scrubFn) { return function (item, options, callback) { if (scrubFn) { var scrubFields = options.scrubFields || []; var scrubPaths = options.scrubPaths || []; item.data = scrubFn(item.data, scrubFields, scrubPaths); } callback(null, item); }; } export { handleDomException, handleItemWithError, ensureItemHasSomethingToSay, addBaseInfo, addRequestInfo, addClientInfo, addPluginInfo, addBody, addScrubber, };