UNPKG

raygun

Version:

Raygun package for Node.js, written in TypeScript

296 lines (295 loc) 10.5 kB
/* * raygun * https://github.com/MindscapeHQ/raygun4node * * Copyright (c) 2015 MindscapeHQ * Licensed under the MIT license. */ "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.RaygunMessageBuilder = void 0; var os_1 = __importDefault(require("os")); var stack_trace_1 = __importDefault(require("stack-trace")); var raygun_human_1 = require("./raygun.human"); var debug = require("debug")("raygun"); var packageDetails = require("../package.json"); /** * Filter properties in obj according to provided filters. * Also removes any recursive self-referencing object. * @param obj - object to apply filter * @param filters - list of keys to filter * @param explored - Set that contains already explored nodes, used internally * @returns object after applying the filters */ function filterKeys(obj, filters, explored) { if (explored === void 0) { explored = null; } if (!obj || !filters || typeof obj !== "object") { return obj; } // create or update the explored set with the incoming object var _explored = (explored === null || explored === void 0 ? void 0 : explored.add(obj)) || new Set([obj]); // Make temporary copy of the object to avoid mutating the original // Cast to Record<string, object> to enforce type check and avoid using any var _obj = __assign({}, obj); Object.keys(obj).forEach(function (key) { // Remove child if: // - the key is in the filter array // - the value is already in the explored Set if (filters.indexOf(key) > -1 || _explored.has(_obj[key])) { delete _obj[key]; } else { _obj[key] = filterKeys(_obj[key], filters, _explored); } }); return _obj; } /** * Extract stacktrace from provided Error * @param error - error to process * @param options - builder options * @returns created stack trace */ function getStackTrace(error, options) { var stack = []; var trace = stack_trace_1.default.parse(error); trace.forEach(function (callSite) { var frame = { lineNumber: callSite.getLineNumber(), className: callSite.getTypeName() || "unknown", fileName: callSite.getFileName(), methodName: callSite.getFunctionName() || "[anonymous]", }; if (!!options.reportColumnNumbers && typeof callSite.getColumnNumber === "function") { frame.columnNumber = callSite.getColumnNumber(); } stack.push(frame); }); return stack; } /** * Created an error payload to send * @param error - error to process * @param options - builder options * @returns created error */ function buildError(error, options) { var builtError = { stackTrace: getStackTrace(error, options), message: error.message || "NoMessage", className: error.name, }; var innerError = undefined; if (options.innerErrorFieldName) { innerError = typeof error[options.innerErrorFieldName] === "function" ? error[options.innerErrorFieldName]() : error[options.innerErrorFieldName]; } if (innerError instanceof Error) { builtError.innerError = buildError(innerError, options); } return builtError; } var RaygunMessageBuilder = /** @class */ (function () { function RaygunMessageBuilder(options) { if (options === void 0) { options = {}; } options = options || {}; this.options = options; this._filters = options.filters || []; this.message = { occurredOn: options.timestamp || new Date(), details: { client: { name: "raygun-node", version: packageDetails.version, }, }, }; } RaygunMessageBuilder.prototype.build = function () { // TODO - this provides no type safety that you actually passed what is needed // probably need to abandon the fluent builder pattern for better types return this.message; }; /** * Add error details to builder * @param error - error to add */ // eslint-disable-next-line @typescript-eslint/no-explicit-any RaygunMessageBuilder.prototype.setErrorDetails = function (error) { if (!(error instanceof Error) && typeof error !== "string" && this.options.useHumanStringForObject) { error = (0, raygun_human_1.humanString)(error); this.message.details.groupingKey = error .replace(/\W+/g, "") .substring(0, 64); } if (typeof error === "string") { this.message.details.error = { message: error, stackTrace: [], className: "Error", }; return this; } this.message.details.error = buildError(error, this.options); return this; }; /** * Set environment details from OS to builder */ RaygunMessageBuilder.prototype.setEnvironmentDetails = function () { var environment = { osVersion: "".concat(os_1.default.type(), " ").concat(os_1.default.platform(), " ").concat(os_1.default.release()), architecture: os_1.default.arch(), totalPhysicalMemory: os_1.default.totalmem(), availablePhysicalMemory: os_1.default.freemem(), utcOffset: new Date().getTimezoneOffset() / -60.0, }; // cpus seems to return undefined on some systems var cpus = os_1.default.cpus(); if (cpus && cpus.length && cpus.length > 0) { environment.processorCount = cpus.length; environment.cpu = cpus[0].model; } this.message.details.environment = environment; return this; }; /** * Set machine name to builder * @param machineName - the machine name, if not provided reads from OS */ RaygunMessageBuilder.prototype.setMachineName = function (machineName) { this.message.details.machineName = machineName || os_1.default.hostname(); return this; }; /** * Set custom data to builder * @param customData - optional CustomData object */ RaygunMessageBuilder.prototype.setUserCustomData = function (customData) { this.message.details.userCustomData = customData; return this; }; /** * Set tags to builder * @param tags - List of Tags */ RaygunMessageBuilder.prototype.setTags = function (tags) { if (Array.isArray(tags)) { this.message.details.tags = tags; } return this; }; /** * Set Request to builder * @param request - optional request object */ RaygunMessageBuilder.prototype.setRequestDetails = function (request) { if (request) { var host = "hostname" in request ? request.hostname : request.host; this.message.details.request = { hostName: host, url: request.path, httpMethod: request.method, ipAddress: request.ip, queryString: filterKeys(request.query, this._filters), headers: filterKeys(request.headers, this._filters), form: filterKeys(request.body, this._filters), }; } return this; }; /** * Set user info to builder * @param user - either a function or a UserMessageData object */ RaygunMessageBuilder.prototype.setUser = function (user) { if (!user) { return this; } var userData; if (user instanceof Function) { userData = user(); } else { userData = user; } if (userData instanceof Object) { this.message.details.user = this.extractUserProperties(userData); } else if (typeof userData === "string") { this.message.details.user = { identifier: userData }; } return this; }; /** * Set application version to builder * @param version - version as String */ RaygunMessageBuilder.prototype.setVersion = function (version) { this.message.details.version = version; return this; }; RaygunMessageBuilder.prototype.extractUserProperties = function (userData) { var data = {}; if (userData.identifier) { data.identifier = userData.identifier; } if (userData.isAnonymous) { data.isAnonymous = userData.isAnonymous; } if (userData.email) { data.email = userData.email; } if (userData.fullName) { data.fullName = userData.fullName; } if (userData.firstName) { data.firstName = userData.firstName; } if (userData.uuid) { data.uuid = userData.uuid; } return data; }; /** * Set list of breadcrumbs to builder * @param breadcrumbs - optional list of breadcrumbs */ RaygunMessageBuilder.prototype.setBreadcrumbs = function (breadcrumbs) { debug("[raygun.messageBuilder.ts] Added breadcrumbs: ".concat((breadcrumbs === null || breadcrumbs === void 0 ? void 0 : breadcrumbs.length) || 0)); if (breadcrumbs) { this.message.details.breadcrumbs = __spreadArray([], breadcrumbs, true); } return this; }; return RaygunMessageBuilder; }()); exports.RaygunMessageBuilder = RaygunMessageBuilder;