"use strict"; var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var child = require("child_process"); var http = require("http"); var os = require('os'); var nodestacktrace = require('stack-trace'); var path = require('path'); var https = require('https'); var url = require('url'); var Fs = require('fs'); var Path = require('path'); var SubmissionResponse = (function () { function SubmissionResponse(statusCode, message) { this.success = false; this.badRequest = false; this.serviceUnavailable = false; this.paymentRequired = false; this.unableToAuthenticate = false; this.notFound = false; this.requestEntityTooLarge = false; this.statusCode = statusCode; this.message = message; this.success = statusCode >= 200 && statusCode <= 299; this.badRequest = statusCode === 400; this.serviceUnavailable = statusCode === 503; this.paymentRequired = statusCode === 402; this.unableToAuthenticate = statusCode === 401 || statusCode === 403; this.notFound = statusCode === 404; this.requestEntityTooLarge = statusCode === 413; } return SubmissionResponse; }()); exports.SubmissionResponse = SubmissionResponse; var SettingsManager = (function () { function SettingsManager() { } SettingsManager.onChanged = function (handler) { !!handler && this._handlers.push(handler); }; SettingsManager.applySavedServerSettings = function (config) { if (!config || !config.isValid) { return; } var savedSettings = this.getSavedServerSettings(config); config.log.info("Applying saved settings: v" + savedSettings.version); config.settings = Utils.merge(config.settings, savedSettings.settings); this.changed(config); }; SettingsManager.getVersion = function (config) { if (!config || !config.isValid) { return 0; } var savedSettings = this.getSavedServerSettings(config); return savedSettings.version || 0; }; SettingsManager.checkVersion = function (version, config) { var currentVersion = this.getVersion(config); if (version <= currentVersion) { return; } config.log.info("Updating settings from v" + currentVersion + " to v" + version); this.updateSettings(config, currentVersion); }; SettingsManager.updateSettings = function (config, version) { var _this = this; if (!config || !config.enabled) { return; } var unableToUpdateMessage = 'Unable to update settings'; if (!config.isValid) { config.log.error(unableToUpdateMessage + ": ApiKey is not set."); return; } if (!version || version < 0) { version = this.getVersion(config); } config.log.info("Checking for updated settings from: v" + version + "."); config.submissionClient.getSettings(config, version, function (response) { if (!config || !response || !response.success || !response.settings) { config.log.warn(unableToUpdateMessage + ": " + response.message); return; } config.settings = Utils.merge(config.settings, response.settings); var savedServerSettings = SettingsManager.getSavedServerSettings(config); for (var key in savedServerSettings) { if (response.settings[key]) { continue; } delete config.settings[key]; } var newSettings = { version: response.settingsVersion, settings: response.settings }; config.storage.settings.save(newSettings); config.log.info("Updated settings: v" + newSettings.version); _this.changed(config); }); }; SettingsManager.changed = function (config) { var handlers = this._handlers; for (var index = 0; index < handlers.length; index++) { try { handlers[index](config); } catch (ex) { config.log.error("Error calling onChanged handler: " + ex); } } }; SettingsManager.getSavedServerSettings = function (config) { var item = config.storage.settings.get()[0]; if (item && item.value && item.value.version && item.value.settings) { return item.value; } return { version: 0, settings: {} }; }; SettingsManager._handlers = []; return SettingsManager; }()); exports.SettingsManager = SettingsManager; var DefaultLastReferenceIdManager = (function () { function DefaultLastReferenceIdManager() { this._lastReferenceId = null; } DefaultLastReferenceIdManager.prototype.getLast = function () { return this._lastReferenceId; }; DefaultLastReferenceIdManager.prototype.clearLast = function () { this._lastReferenceId = null; }; DefaultLastReferenceIdManager.prototype.setLast = function (eventId) { this._lastReferenceId = eventId; }; return DefaultLastReferenceIdManager; }()); exports.DefaultLastReferenceIdManager = DefaultLastReferenceIdManager; var ConsoleLog = (function () { function ConsoleLog() { } ConsoleLog.prototype.trace = function (message) { this.log('trace', message); }; ConsoleLog.prototype.info = function (message) { this.log('info', message); }; ConsoleLog.prototype.warn = function (message) { this.log('warn', message); }; ConsoleLog.prototype.error = function (message) { this.log('error', message); }; ConsoleLog.prototype.log = function (level, message) { if (console) { var msg = "[" + level + "] Exceptionless: " + message; if (console[level]) { console[level](msg); } else if (console.log) { console["log"](msg); } } }; return ConsoleLog; }()); exports.ConsoleLog = ConsoleLog; var NullLog = (function () { function NullLog() { } NullLog.prototype.trace = function (message) { }; NullLog.prototype.info = function (message) { }; NullLog.prototype.warn = function (message) { }; NullLog.prototype.error = function (message) { }; return NullLog; }()); exports.NullLog = NullLog; var EventPluginContext = (function () { function EventPluginContext(client, event, contextData) { this.client = client; this.event = event; this.contextData = contextData ? contextData : new ContextData(); } Object.defineProperty(EventPluginContext.prototype, "log", { get: function () { return this.client.config.log; }, enumerable: true, configurable: true }); return EventPluginContext; }()); exports.EventPluginContext = EventPluginContext; var EventPluginManager = (function () { function EventPluginManager() { } EventPluginManager.run = function (context, callback) { var wrap = function (plugin, next) { return function () { try { if (!context.cancelled) { plugin.run(context, next); } } catch (ex) { context.cancelled = true; context.log.error("Error running plugin '" + plugin.name + "': " + ex.message + ". Discarding Event."); } if (context.cancelled && !!callback) { callback(context); } }; }; var plugins = context.client.config.plugins; var wrappedPlugins = []; if (!!callback) { wrappedPlugins[plugins.length] = wrap({ name: 'cb', priority: 9007199254740992, run: callback }, null); } for (var index = plugins.length - 1; index > -1; index--) { wrappedPlugins[index] = wrap(plugins[index], !!callback || (index < plugins.length - 1) ? wrappedPlugins[index + 1] : null); } wrappedPlugins[0](); }; EventPluginManager.addDefaultPlugins = function (config) { config.addPlugin(new ConfigurationDefaultsPlugin()); config.addPlugin(new ErrorPlugin()); config.addPlugin(new DuplicateCheckerPlugin()); config.addPlugin(new EventExclusionPlugin()); config.addPlugin(new ModuleInfoPlugin()); config.addPlugin(new RequestInfoPlugin()); config.addPlugin(new EnvironmentInfoPlugin()); config.addPlugin(new SubmissionMethodPlugin()); }; return EventPluginManager; }()); exports.EventPluginManager = EventPluginManager; var HeartbeatPlugin = (function () { function HeartbeatPlugin(heartbeatInterval) { if (heartbeatInterval === void 0) { heartbeatInterval = 30000; } this.priority = 100; this.name = 'HeartbeatPlugin'; this._interval = heartbeatInterval; } HeartbeatPlugin.prototype.run = function (context, next) { clearInterval(this._intervalId); var user = context.event.data['@user']; if (user && user.identity) { this._intervalId = setInterval(function () { return context.client.submitSessionHeartbeat(user.identity); }, this._interval); } next && next(); }; return HeartbeatPlugin; }()); exports.HeartbeatPlugin = HeartbeatPlugin; var ReferenceIdPlugin = (function () { function ReferenceIdPlugin() { this.priority = 20; this.name = 'ReferenceIdPlugin'; } ReferenceIdPlugin.prototype.run = function (context, next) { if ((!context.event.reference_id || context.event.reference_id.length === 0) && context.event.type === 'error') { context.event.reference_id = Utils.guid().replace('-', '').substring(0, 10); } next && next(); }; return ReferenceIdPlugin; }()); exports.ReferenceIdPlugin = ReferenceIdPlugin; var DefaultEventQueue = (function () { function DefaultEventQueue(config) { this._handlers = []; this._processingQueue = false; this._config = config; } DefaultEventQueue.prototype.enqueue = function (event) { var eventWillNotBeQueued = 'The event will not be queued.'; var config = this._config; var log = config.log; if (!config.enabled) { log.info("Configuration is disabled. " + eventWillNotBeQueued); return; } if (!config.isValid) { log.info("Invalid Api Key. " + eventWillNotBeQueued); return; } if (this.areQueuedItemsDiscarded()) { log.info("Queue items are currently being discarded. " + eventWillNotBeQueued); return; } this.ensureQueueTimer(); var timestamp = config.storage.queue.save(event); var logText = "type=" + event.type + " " + (!!event.reference_id ? 'refid=' + event.reference_id : ''); if (timestamp) { log.info("Enqueuing event: " + timestamp + " " + logText); } else { log.error("Could not enqueue event " + logText); } }; DefaultEventQueue.prototype.process = function (isAppExiting) { var _this = this; var queueNotProcessed = 'The queue will not be processed.'; var config = this._config; var log = config.log; if (this._processingQueue) { return; } log.info('Processing queue...'); if (!config.enabled) { log.info("Configuration is disabled. " + queueNotProcessed); return; } if (!config.isValid) { log.info("Invalid Api Key. " + queueNotProcessed); return; } this._processingQueue = true; this.ensureQueueTimer(); try { var events_1 = config.storage.queue.get(config.submissionBatchSize); if (!events_1 || events_1.length === 0) { this._processingQueue = false; return; } log.info("Sending " + events_1.length + " events to " + config.serverUrl + "."); config.submissionClient.postEvents(events_1.map(function (e) { return e.value; }), config, function (response) { _this.processSubmissionResponse(response, events_1); _this.eventsPosted(events_1.map(function (e) { return e.value; }), response); log.info('Finished processing queue.'); _this._processingQueue = false; }, isAppExiting); } catch (ex) { log.error("Error processing queue: " + ex); this.suspendProcessing(); this._processingQueue = false; } }; DefaultEventQueue.prototype.suspendProcessing = function (durationInMinutes, discardFutureQueuedItems, clearQueue) { var config = this._config; if (!durationInMinutes || durationInMinutes <= 0) { durationInMinutes = 5; } config.log.info("Suspending processing for " + durationInMinutes + " minutes."); this._suspendProcessingUntil = new Date(new Date().getTime() + (durationInMinutes * 60000)); if (discardFutureQueuedItems) { this._discardQueuedItemsUntil = this._suspendProcessingUntil; } if (clearQueue) { config.storage.queue.clear(); } }; DefaultEventQueue.prototype.onEventsPosted = function (handler) { !!handler && this._handlers.push(handler); }; DefaultEventQueue.prototype.eventsPosted = function (events, response) { var handlers = this._handlers; for (var index = 0; index < handlers.length; index++) { try { handlers[index](events, response); } catch (ex) { this._config.log.error("Error calling onEventsPosted handler: " + ex); } } }; DefaultEventQueue.prototype.areQueuedItemsDiscarded = function () { return this._discardQueuedItemsUntil && this._discardQueuedItemsUntil > new Date(); }; DefaultEventQueue.prototype.ensureQueueTimer = function () { var _this = this; if (!this._queueTimer) { this._queueTimer = setInterval(function () { return _this.onProcessQueue(); }, 10000); } }; DefaultEventQueue.prototype.isQueueProcessingSuspended = function () { return this._suspendProcessingUntil && this._suspendProcessingUntil > new Date(); }; DefaultEventQueue.prototype.onProcessQueue = function () { if (!this.isQueueProcessingSuspended() && !this._processingQueue) { this.process(); } }; DefaultEventQueue.prototype.processSubmissionResponse = function (response, events) { var noSubmission = 'The event will not be submitted.'; var config = this._config; var log = config.log; if (response.success) { log.info("Sent " + events.length + " events."); this.removeEvents(events); return; } if (response.serviceUnavailable) { log.error('Server returned service unavailable.'); this.suspendProcessing(); return; } if (response.paymentRequired) { log.info('Too many events have been submitted, please upgrade your plan.'); this.suspendProcessing(null, true, true); return; } if (response.unableToAuthenticate) { log.info("Unable to authenticate, please check your configuration. " + noSubmission); this.suspendProcessing(15); this.removeEvents(events); return; } if (response.notFound || response.badRequest) { log.error("Error while trying to submit data: " + response.message); this.suspendProcessing(60 * 4); this.removeEvents(events); return; } if (response.requestEntityTooLarge) { var message = 'Event submission discarded for being too large.'; if (config.submissionBatchSize > 1) { log.error(message + " Retrying with smaller batch size."); config.submissionBatchSize = Math.max(1, Math.round(config.submissionBatchSize / 1.5)); } else { log.error(message + " " + noSubmission); this.removeEvents(events); } return; } if (!response.success) { log.error("Error submitting events: " + (response.message || 'Please check the network tab for more info.')); this.suspendProcessing(); } }; DefaultEventQueue.prototype.removeEvents = function (events) { for (var index = 0; index < (events || []).length; index++) { this._config.storage.queue.remove(events[index].timestamp); } }; return DefaultEventQueue; }()); exports.DefaultEventQueue = DefaultEventQueue; var InMemoryStorageProvider = (function () { function InMemoryStorageProvider(maxQueueItems) { if (maxQueueItems === void 0) { maxQueueItems = 250; } this.queue = new InMemoryStorage(maxQueueItems); this.settings = new InMemoryStorage(1); } return InMemoryStorageProvider; }()); exports.InMemoryStorageProvider = InMemoryStorageProvider; var DefaultSubmissionClient = (function () { function DefaultSubmissionClient() { this.configurationVersionHeader = 'x-exceptionless-configversion'; } DefaultSubmissionClient.prototype.postEvents = function (events, config, callback, isAppExiting) { var data = JSON.stringify(events); var request = this.createRequest(config, 'POST', config.serverUrl + "/api/v2/events", data); var cb = this.createSubmissionCallback(config, callback); return config.submissionAdapter.sendRequest(request, cb, isAppExiting); }; DefaultSubmissionClient.prototype.postUserDescription = function (referenceId, description, config, callback) { var path = config.serverUrl + "/api/v2/events/by-ref/" + encodeURIComponent(referenceId) + "/user-description"; var data = JSON.stringify(description); var request = this.createRequest(config, 'POST', path, data); var cb = this.createSubmissionCallback(config, callback); return config.submissionAdapter.sendRequest(request, cb); }; DefaultSubmissionClient.prototype.getSettings = function (config, version, callback) { var request = this.createRequest(config, 'GET', config.serverUrl + "/api/v2/projects/config?v=" + version); var cb = function (status, message, data, headers) { if (status !== 200) { return callback(new SettingsResponse(false, null, -1, null, message)); } var settings; try { settings = JSON.parse(data); } catch (e) { config.log.error("Unable to parse settings: '" + data + "'"); } if (!settings || isNaN(settings.version)) { return callback(new SettingsResponse(false, null, -1, null, 'Invalid configuration settings.')); } callback(new SettingsResponse(true, settings.settings || {}, settings.version)); }; return config.submissionAdapter.sendRequest(request, cb); }; DefaultSubmissionClient.prototype.sendHeartbeat = function (sessionIdOrUserId, closeSession, config) { var request = this.createRequest(config, 'GET', config.heartbeatServerUrl + "/api/v2/events/session/heartbeat?id=" + sessionIdOrUserId + "&close=" + closeSession); config.submissionAdapter.sendRequest(request); }; DefaultSubmissionClient.prototype.createRequest = function (config, method, url, data) { if (data === void 0) { data = null; } return { method: method, url: url, data: data, apiKey: config.apiKey, userAgent: config.userAgent }; }; DefaultSubmissionClient.prototype.createSubmissionCallback = function (config, callback) { var _this = this; return function (status, message, data, headers) { var settingsVersion = headers && parseInt(headers[_this.configurationVersionHeader], 10); SettingsManager.checkVersion(settingsVersion, config); callback(new SubmissionResponse(status, message)); }; }; return DefaultSubmissionClient; }()); exports.DefaultSubmissionClient = DefaultSubmissionClient; var Utils = (function () { function Utils() { } Utils.addRange = function (target) { var values = []; for (var _i = 1; _i < arguments.length; _i++) { values[_i - 1] = arguments[_i]; } if (!target) { target = []; } if (!values || values.length === 0) { return target; } for (var index = 0; index < values.length; index++) { if (values[index] && target.indexOf(values[index]) < 0) { target.push(values[index]); } } return target; }; Utils.getHashCode = function (source) { if (!source || source.length === 0) { return 0; } var hash = 0; for (var index = 0; index < source.length; index++) { var character = source.charCodeAt(index); hash = ((hash << 5) - hash) + character; hash |= 0; } return hash; }; Utils.getCookies = function (cookies, exclusions) { var result = {}; var parts = (cookies || '').split('; '); for (var index = 0; index < parts.length; index++) { var cookie = parts[index].split('='); if (!Utils.isMatch(cookie[0], exclusions)) { result[cookie[0]] = cookie[1]; } } return !Utils.isEmpty(result) ? result : null; }; Utils.guid = function () { function s4() { return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1); } return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); }; Utils.merge = function (defaultValues, values) { var result = {}; for (var key in defaultValues || {}) { if (!!defaultValues[key]) { result[key] = defaultValues[key]; } } for (var key in values || {}) { if (!!values[key]) { result[key] = values[key]; } } return result; }; Utils.parseVersion = function (source) { if (!source) { return null; } var versionRegex = /(v?((\d+)\.(\d+)(\.(\d+))?)(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?(?:\+([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?)/; var matches = versionRegex.exec(source); if (matches && matches.length > 0) { return matches[0]; } return null; }; Utils.parseQueryString = function (query, exclusions) { if (!query || query.length === 0) { return null; } var pairs = query.split('&'); if (pairs.length === 0) { return null; } var result = {}; for (var index = 0; index < pairs.length; index++) { var pair = pairs[index].split('='); if (!Utils.isMatch(pair[0], exclusions)) { result[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); } } return !Utils.isEmpty(result) ? result : null; }; Utils.randomNumber = function () { return Math.floor(Math.random() * 9007199254740992); }; Utils.isMatch = function (input, patterns, ignoreCase) { if (ignoreCase === void 0) { ignoreCase = true; } if (!input || typeof input !== 'string') { return false; } var trim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; input = (ignoreCase ? input.toLowerCase() : input).replace(trim, ''); return (patterns || []).some(function (pattern) { if (typeof pattern !== 'string') { return false; } pattern = (ignoreCase ? pattern.toLowerCase() : pattern).replace(trim, ''); if (pattern.length <= 0) { return false; } var startsWithWildcard = pattern[0] === '*'; if (startsWithWildcard) { pattern = pattern.slice(1); } var endsWithWildcard = pattern[pattern.length - 1] === '*'; if (endsWithWildcard) { pattern = pattern.substring(0, pattern.length - 1); } if (startsWithWildcard && endsWithWildcard) { return pattern.length <= input.length && input.indexOf(pattern, 0) !== -1; } if (startsWithWildcard) { return Utils.endsWith(input, pattern); } if (endsWithWildcard) { return Utils.startsWith(input, pattern); } return input === pattern; }); }; Utils.isEmpty = function (input) { return input === null || (typeof (input) === 'object' && Object.keys(input).length === 0); }; Utils.startsWith = function (input, prefix) { return input.substring(0, prefix.length) === prefix; }; Utils.endsWith = function (input, suffix) { return input.indexOf(suffix, input.length - suffix.length) !== -1; }; Utils.stringify = function (data, exclusions, maxDepth) { function stringifyImpl(obj, excludedKeys) { var cache = []; return JSON.stringify(obj, function (key, value) { if (Utils.isMatch(key, excludedKeys)) { return; } if (typeof value === 'object' && !!value) { if (cache.indexOf(value) !== -1) { return; } cache.push(value); } return value; }); } if (({}).toString.call(data) === '[object Object]') { var flattened = {}; for (var prop in data) { var value = data[prop]; if (value === data) { continue; } flattened[prop] = data[prop]; } return stringifyImpl(flattened, exclusions); } if (({}).toString.call(data) === '[object Array]') { var result = []; for (var index = 0; index < data.length; index++) { result[index] = JSON.parse(stringifyImpl(data[index], exclusions)); } return JSON.stringify(result); } return stringifyImpl(data, exclusions); }; Utils.toBoolean = function (input, defaultValue) { if (defaultValue === void 0) { defaultValue = false; } if (typeof input === 'boolean') { return input; } if (input === null || typeof input !== 'number' && typeof input !== 'string') { return defaultValue; } switch ((input + '').toLowerCase().trim()) { case 'true': case 'yes': case '1': return true; case 'false': case 'no': case '0': case null: return false; } return defaultValue; }; return Utils; }()); exports.Utils = Utils; var Configuration = (function () { function Configuration(configSettings) { this.defaultTags = []; this.defaultData = {}; this.enabled = true; this.lastReferenceIdManager = new DefaultLastReferenceIdManager(); this.settings = {}; this._serverUrl = 'https://collector.exceptionless.io'; this._heartbeatServerUrl = 'https://heartbeat.exceptionless.io'; this._updateSettingsWhenIdleInterval = 120000; this._dataExclusions = []; this._userAgentBotPatterns = []; this._plugins = []; this._handlers = []; function inject(fn) { return typeof fn === 'function' ? fn(this) : fn; } configSettings = Utils.merge(Configuration.defaults, configSettings); this.log = inject(configSettings.log) || new NullLog(); this.apiKey = configSettings.apiKey; this.serverUrl = configSettings.serverUrl; this.heartbeatServerUrl = configSettings.heartbeatServerUrl; this.updateSettingsWhenIdleInterval = configSettings.updateSettingsWhenIdleInterval; this.environmentInfoCollector = inject(configSettings.environmentInfoCollector); this.errorParser = inject(configSettings.errorParser); this.lastReferenceIdManager = inject(configSettings.lastReferenceIdManager) || new DefaultLastReferenceIdManager(); this.moduleCollector = inject(configSettings.moduleCollector); this.requestInfoCollector = inject(configSettings.requestInfoCollector); this.submissionBatchSize = inject(configSettings.submissionBatchSize) || 50; this.submissionAdapter = inject(configSettings.submissionAdapter); this.submissionClient = inject(configSettings.submissionClient) || new DefaultSubmissionClient(); this.storage = inject(configSettings.storage) || new InMemoryStorageProvider(); this.queue = inject(configSettings.queue) || new DefaultEventQueue(this); SettingsManager.applySavedServerSettings(this); EventPluginManager.addDefaultPlugins(this); } Object.defineProperty(Configuration.prototype, "apiKey", { get: function () { return this._apiKey; }, set: function (value) { this._apiKey = value || null; this.log.info("apiKey: " + this._apiKey); this.changed(); }, enumerable: true, configurable: true }); Object.defineProperty(Configuration.prototype, "isValid", { get: function () { return !!this.apiKey && this.apiKey.length >= 10; }, enumerable: true, configurable: true }); Object.defineProperty(Configuration.prototype, "serverUrl", { get: function () { return this._serverUrl; }, set: function (value) { if (!!value) { this._serverUrl = value; this._heartbeatServerUrl = value; this.log.info("serverUrl: " + value); this.changed(); } }, enumerable: true, configurable: true }); Object.defineProperty(Configuration.prototype, "heartbeatServerUrl", { get: function () { return this._heartbeatServerUrl; }, set: function (value) { if (!!value) { this._heartbeatServerUrl = value; this.log.info("heartbeatServerUrl: " + value); this.changed(); } }, enumerable: true, configurable: true }); Object.defineProperty(Configuration.prototype, "updateSettingsWhenIdleInterval", { get: function () { return this._updateSettingsWhenIdleInterval; }, set: function (value) { if (typeof value !== 'number') { return; } if (value <= 0) { value = -1; } else if (value > 0 && value < 15000) { value = 15000; } this._updateSettingsWhenIdleInterval = value; this.log.info("updateSettingsWhenIdleInterval: " + value); this.changed(); }, enumerable: true, configurable: true }); Object.defineProperty(Configuration.prototype, "dataExclusions", { get: function () { var exclusions = this.settings['@@DataExclusions']; return this._dataExclusions.concat(exclusions && exclusions.split(',') || []); }, enumerable: true, configurable: true }); Configuration.prototype.addDataExclusions = function () { var exclusions = []; for (var _i = 0; _i < arguments.length; _i++) { exclusions[_i - 0] = arguments[_i]; } this._dataExclusions = Utils.addRange.apply(Utils, [this._dataExclusions].concat(exclusions)); }; Object.defineProperty(Configuration.prototype, "userAgentBotPatterns", { get: function () { var patterns = this.settings['@@UserAgentBotPatterns']; return this._userAgentBotPatterns.concat(patterns && patterns.split(',') || []); }, enumerable: true, configurable: true }); Configuration.prototype.addUserAgentBotPatterns = function () { var userAgentBotPatterns = []; for (var _i = 0; _i < arguments.length; _i++) { userAgentBotPatterns[_i - 0] = arguments[_i]; } this._userAgentBotPatterns = Utils.addRange.apply(Utils, [this._userAgentBotPatterns].concat(userAgentBotPatterns)); }; Object.defineProperty(Configuration.prototype, "plugins", { get: function () { return this._plugins.sort(function (p1, p2) { return (p1.priority < p2.priority) ? -1 : (p1.priority > p2.priority) ? 1 : 0; }); }, enumerable: true, configurable: true }); Configuration.prototype.addPlugin = function (pluginOrName, priority, pluginAction) { var plugin = !!pluginAction ? { name: pluginOrName, priority: priority, run: pluginAction } : pluginOrName; if (!plugin || !plugin.run) { this.log.error('Add plugin failed: Run method not defined'); return; } if (!plugin.name) { plugin.name = Utils.guid(); } if (!plugin.priority) { plugin.priority = 0; } var pluginExists = false; var plugins = this._plugins; for (var index = 0; index < plugins.length; index++) { if (plugins[index].name === plugin.name) { pluginExists = true; break; } } if (!pluginExists) { plugins.push(plugin); } }; Configuration.prototype.removePlugin = function (pluginOrName) { var name = typeof pluginOrName === 'string' ? pluginOrName : pluginOrName.name; if (!name) { this.log.error('Remove plugin failed: Plugin name not defined'); return; } var plugins = this._plugins; for (var index = 0; index < plugins.length; index++) { if (plugins[index].name === name) { plugins.splice(index, 1); break; } } }; Configuration.prototype.setVersion = function (version) { if (!!version) { this.defaultData['@version'] = version; } }; Configuration.prototype.setUserIdentity = function (userInfoOrIdentity, name) { var USER_KEY = '@user'; var userInfo = typeof userInfoOrIdentity !== 'string' ? userInfoOrIdentity : { identity: userInfoOrIdentity, name: name }; var shouldRemove = !userInfo || (!userInfo.identity && !userInfo.name); if (shouldRemove) { delete this.defaultData[USER_KEY]; } else { this.defaultData[USER_KEY] = userInfo; } this.log.info("user identity: " + (shouldRemove ? 'null' : userInfo.identity)); }; Object.defineProperty(Configuration.prototype, "userAgent", { get: function () { return 'exceptionless-node/1.4.3'; }, enumerable: true, configurable: true }); Configuration.prototype.useSessions = function (sendHeartbeats, heartbeatInterval) { if (sendHeartbeats === void 0) { sendHeartbeats = true; } if (heartbeatInterval === void 0) { heartbeatInterval = 30000; } if (sendHeartbeats) { this.addPlugin(new HeartbeatPlugin(heartbeatInterval)); } }; Configuration.prototype.useReferenceIds = function () { this.addPlugin(new ReferenceIdPlugin()); }; Configuration.prototype.useLocalStorage = function () { }; Configuration.prototype.useDebugLogger = function () { this.log = new ConsoleLog(); }; Configuration.prototype.onChanged = function (handler) { !!handler && this._handlers.push(handler); }; Configuration.prototype.changed = function () { var handlers = this._handlers; for (var index = 0; index < handlers.length; index++) { try { handlers[index](this); } catch (ex) { this.log.error("Error calling onChanged handler: " + ex); } } }; Object.defineProperty(Configuration, "defaults", { get: function () { if (Configuration._defaultSettings === null) { Configuration._defaultSettings = {}; } return Configuration._defaultSettings; }, enumerable: true, configurable: true }); Configuration._defaultSettings = null; return Configuration; }()); exports.Configuration = Configuration; var EventBuilder = (function () { function EventBuilder(event, client, pluginContextData) { this._validIdentifierErrorMessage = 'must contain between 8 and 100 alphanumeric or \'-\' characters.'; this.target = event; this.client = client; this.pluginContextData = pluginContextData || new ContextData(); } EventBuilder.prototype.setType = function (type) { if (!!type) { this.target.type = type; } return this; }; EventBuilder.prototype.setSource = function (source) { if (!!source) { this.target.source = source; } return this; }; EventBuilder.prototype.setReferenceId = function (referenceId) { if (!this.isValidIdentifier(referenceId)) { throw new Error("ReferenceId " + this._validIdentifierErrorMessage); } this.target.reference_id = referenceId; return this; }; EventBuilder.prototype.setEventReference = function (name, id) { if (!name) { throw new Error('Invalid name'); } if (!id || !this.isValidIdentifier(id)) { throw new Error("Id " + this._validIdentifierErrorMessage); } this.setProperty('@ref:' + name, id); return this; }; EventBuilder.prototype.setMessage = function (message) { if (!!message) { this.target.message = message; } return this; }; EventBuilder.prototype.setGeo = function (latitude, longitude) { if (latitude < -90.0 || latitude > 90.0) { throw new Error('Must be a valid latitude value between -90.0 and 90.0.'); } if (longitude < -180.0 || longitude > 180.0) { throw new Error('Must be a valid longitude value between -180.0 and 180.0.'); } this.target.geo = latitude + "," + longitude; return this; }; EventBuilder.prototype.setUserIdentity = function (userInfoOrIdentity, name) { var userInfo = typeof userInfoOrIdentity !== 'string' ? userInfoOrIdentity : { identity: userInfoOrIdentity, name: name }; if (!userInfo || (!userInfo.identity && !userInfo.name)) { return this; } this.setProperty('@user', userInfo); return this; }; EventBuilder.prototype.setUserDescription = function (emailAddress, description) { if (emailAddress && description) { this.setProperty('@user_description', { email_address: emailAddress, description: description }); } return this; }; EventBuilder.prototype.setManualStackingInfo = function (signatureData, title) { if (signatureData) { var stack = { signature_data: signatureData }; if (title) { stack.title = title; } this.setProperty('@stack', stack); } return this; }; EventBuilder.prototype.setManualStackingKey = function (manualStackingKey, title) { if (manualStackingKey) { var data = { 'ManualStackingKey': manualStackingKey }; this.setManualStackingInfo(data, title); } return this; }; EventBuilder.prototype.setValue = function (value) { if (!!value) { this.target.value = value; } return this; }; EventBuilder.prototype.addTags = function () { var tags = []; for (var _i = 0; _i < arguments.length; _i++) { tags[_i - 0] = arguments[_i]; } this.target.tags = Utils.addRange.apply(Utils, [this.target.tags].concat(tags)); return this; }; EventBuilder.prototype.setProperty = function (name, value, maxDepth, excludedPropertyNames) { if (!name || (value === undefined || value == null)) { return this; } if (!this.target.data) { this.target.data = {}; } var result = JSON.parse(Utils.stringify(value, this.client.config.dataExclusions.concat(excludedPropertyNames || []), maxDepth)); if (!Utils.isEmpty(result)) { this.target.data[name] = result; } return this; }; EventBuilder.prototype.markAsCritical = function (critical) { if (critical) { this.addTags('Critical'); } return this; }; EventBuilder.prototype.addRequestInfo = function (request) { if (!!request) { this.pluginContextData['@request'] = request; } return this; }; EventBuilder.prototype.submit = function (callback) { this.client.submitEvent(this.target, this.pluginContextData, callback); }; EventBuilder.prototype.isValidIdentifier = function (value) { if (!value) { return true; } if (value.length < 8 || value.length > 100) { return false; } for (var index = 0; index < value.length; index++) { var code = value.charCodeAt(index); var isDigit = (code >= 48) && (code <= 57); var isLetter = ((code >= 65) && (code <= 90)) || ((code >= 97) && (code <= 122)); var isMinus = code === 45; if (!(isDigit || isLetter) && !isMinus) { return false; } } return true; }; return EventBuilder; }()); exports.EventBuilder = EventBuilder; var ContextData = (function () { function ContextData() { } ContextData.prototype.setException = function (exception) { if (exception) { this['@@_Exception'] = exception; } }; Object.defineProperty(ContextData.prototype, "hasException", { get: function () { return !!this['@@_Exception']; }, enumerable: true, configurable: true }); ContextData.prototype.getException = function () { return this['@@_Exception'] || null; }; ContextData.prototype.markAsUnhandledError = function () { this['@@_IsUnhandledError'] = true; }; Object.defineProperty(ContextData.prototype, "isUnhandledError", { get: function () { return !!this['@@_IsUnhandledError']; }, enumerable: true, configurable: true }); ContextData.prototype.setSubmissionMethod = function (method) { if (method) { this['@@_SubmissionMethod'] = method; } }; ContextData.prototype.getSubmissionMethod = function () { return this['@@_SubmissionMethod'] || null; }; return ContextData; }()); exports.ContextData = ContextData; var ExceptionlessClient = (function () { function ExceptionlessClient(settingsOrApiKey, serverUrl) { var _this = this; if (typeof settingsOrApiKey === 'object') { this.config = new Configuration(settingsOrApiKey); } else { this.config = new Configuration({ apiKey: settingsOrApiKey, serverUrl: serverUrl }); } this.updateSettingsTimer(5000); this.config.onChanged(function (config) { return _this.updateSettingsTimer(_this._timeoutId > 0 ? 5000 : 0); }); this.config.queue.onEventsPosted(function (events, response) { return _this.updateSettingsTimer(); }); } ExceptionlessClient.prototype.createException = function (exception) { var pluginContextData = new ContextData(); pluginContextData.setException(exception); return this.createEvent(pluginContextData).setType('error'); }; ExceptionlessClient.prototype.submitException = function (exception, callback) { this.createException(exception).submit(callback); }; ExceptionlessClient.prototype.createUnhandledException = function (exception, submissionMethod) { var builder = this.createException(exception); builder.pluginContextData.markAsUnhandledError(); builder.pluginContextData.setSubmissionMethod(submissionMethod); return builder; }; ExceptionlessClient.prototype.submitUnhandledException = function (exception, submissionMethod, callback) { this.createUnhandledException(exception, submissionMethod).submit(callback); }; ExceptionlessClient.prototype.createFeatureUsage = function (feature) { return this.createEvent().setType('usage').setSource(feature); }; ExceptionlessClient.prototype.submitFeatureUsage = function (feature, callback) { this.createFeatureUsage(feature).submit(callback); }; ExceptionlessClient.prototype.createLog = function (sourceOrMessage, message, level) { var builder = this.createEvent().setType('log'); if (message && level) { builder = builder.setSource(sourceOrMessage).setMessage(message).setProperty('@level', level); } else if (message) { builder = builder.setSource(sourceOrMessage).setMessage(message); } else { builder = builder.setMessage(sourceOrMessage); try { var caller = this.createLog.caller; builder = builder.setSource(caller && caller.caller && caller.caller.name); } catch (e) { this.config.log.trace('Unable to resolve log source: ' + e.message); } } return builder; }; ExceptionlessClient.prototype.submitLog = function (sourceOrMessage, message, level, callback) { this.createLog(sourceOrMessage, message, level).submit(callback); }; ExceptionlessClient.prototype.createNotFound = function (resource) { return this.createEvent().setType('404').setSource(resource); }; ExceptionlessClient.prototype.submitNotFound = function (resource, callback) { this.createNotFound(resource).submit(callback); }; ExceptionlessClient.prototype.createSessionStart = function () { return this.createEvent().setType('session'); }; ExceptionlessClient.prototype.submitSessionStart = function (callback) { this.createSessionStart().submit(callback); }; ExceptionlessClient.prototype.submitSessionEnd = function (sessionIdOrUserId) { if (sessionIdOrUserId) { this.config.log.info("Submitting session end: " + sessionIdOrUserId); this.config.submissionClient.sendHeartbeat(sessionIdOrUserId, true, this.config); } }; ExceptionlessClient.prototype.submitSessionHeartbeat = function (sessionIdOrUserId) { if (sessionIdOrUserId) { this.config.log.info("Submitting session heartbeat: " + sessionIdOrUserId); this.config.submissionClient.sendHeartbeat(sessionIdOrUserId, false, this.config); } }; ExceptionlessClient.prototype.createEvent = function (pluginContextData) { return new EventBuilder({ date: new Date() }, this, pluginContextData); }; ExceptionlessClient.prototype.submitEvent = function (event, pluginContextData, callback) { function cancelled(context) { if (!!context) { context.cancelled = true; } return !!callback && callback(context); } var context = new EventPluginContext(this, event, pluginContextData); if (!event) { return cancelled(context); } if (!this.config.enabled) { this.config.log.info('Event submission is currently disabled.'); return cancelled(context); } if (!event.data) { event.data = {}; } if (!event.tags || !event.tags.length) { event.tags = []; } EventPluginManager.run(context, function (ctx) { var config = ctx.client.config; var ev = ctx.event; if (!ctx.cancelled) { if (!ev.type || ev.type.length === 0) { ev.type = 'log'; } if (!ev.date) { ev.date = new Date(); } config.queue.enqueue(ev); if (ev.reference_id && ev.reference_id.length > 0) { ctx.log.info("Setting last reference id '" + ev.reference_id + "'"); config.lastReferenceIdManager.setLast(ev.reference_id); } } !!callback && callback(ctx); }); }; ExceptionlessClient.prototype.updateUserEmailAndDescription = function (referenceId, email, description, callback) { var _this = this; if (!referenceId || !email || !description || !this.config.enabled) { return !!callback && callback(new SubmissionResponse(500, 'cancelled')); } var userDescription = { email_address: email, description: description }; this.config.submissionClient.postUserDescription(referenceId, userDescription, this.config, function (response) { if (!response.success) { _this.config.log.error("Failed to submit user email and description for event '" + referenceId + "': " + response.statusCode + " " + response.message); } !!callback && callback(response); }); }; ExceptionlessClient.prototype.getLastReferenceId = function () { return this.config.lastReferenceIdManager.getLast(); }; ExceptionlessClient.prototype.updateSettingsTimer = function (initialDelay) { var _this = this; this.config.log.info("Updating settings timer with delay: " + initialDelay); this._timeoutId = clearTimeout(this._timeoutId); this._timeoutId = clearInterval(this._intervalId); var interval = this.config.updateSettingsWhenIdleInterval; if (interval > 0) { var updateSettings = function () { return SettingsManager.updateSettings(_this.config); }; if (initialDelay > 0) { this._timeoutId = setTimeout(updateSettings, initialDelay); } this._intervalId = setInterval(updateSettings, interval); } }; Object.defineProperty(ExceptionlessClient, "default", { get: function () { if (ExceptionlessClient._instance === null) { ExceptionlessClient._instance = new ExceptionlessClient(null); } return ExceptionlessClient._instance; }, enumerable: true, configurable: true }); ExceptionlessClient._instance = null; return ExceptionlessClient; }()); exports.ExceptionlessClient = ExceptionlessClient; var ConfigurationDefaultsPlugin = (function () { function ConfigurationDefaultsPlugin() { this.priority = 10; this.name = 'ConfigurationDefaultsPlugin'; } ConfigurationDefaultsPlugin.prototype.run = function (context, next) { var config = context.client.config; var defaultTags = config.defaultTags || []; for (var index = 0; index < defaultTags.length; index++) { var tag = defaultTags[index]; if (!!tag && context.event.tags.indexOf(tag) < 0) { context.event.tags.push(tag); } } var defaultData = config.defaultData || {}; for (var key in defaultData) { if (!!defaultData[key]) { var result = JSON.parse(Utils.stringify(defaultData[key], config.dataExclusions)); if (!Utils.isEmpty(result)) { context.event.data[key] = result; } } } next && next(); }; return ConfigurationDefaultsPlugin; }()); exports.ConfigurationDefaultsPlugin = ConfigurationDefaultsPlugin; var ErrorPlugin = (function () { function ErrorPlugin() { this.priority = 30; this.name = 'ErrorPlugin'; } ErrorPlugin.prototype.run = function (context, next) { var ERROR_KEY = '@error'; var ignoredProperties = [ 'arguments', 'column', 'columnNumber', 'description', 'fileName', 'message', 'name', 'number', 'line', 'lineNumber', 'opera#sourceloc', 'sourceId', 'sourceURL', 'stack', 'stackArray', 'stacktrace' ]; var exception = context.contextData.getException(); if (!!exception) { context.event.type = 'error'; if (!context.event.data[ERROR_KEY]) { var config = context.client.config; var parser = config.errorParser; if (!parser) { throw new Error('No error parser was defined.'); } var result = parser.parse(context, exception); if (!!result) { var additionalData = JSON.parse(Utils.stringify(exception, config.dataExclusions.concat(ignoredProperties))); if (!Utils.isEmpty(additionalData)) { if (!result.data) { result.data = {}; } result.data['@ext'] = additionalData; } context.event.data[ERROR_KEY] = result; } } } next && next(); }; return ErrorPlugin; }()); exports.ErrorPlugin = ErrorPlugin; var ModuleInfoPlugin = (function () { function ModuleInfoPlugin() { this.priority = 50; this.name = 'ModuleInfoPlugin'; } ModuleInfoPlugin.prototype.run = function (context, next) { var ERROR_KEY = '@error'; var collector = context.client.config.moduleCollector; if (context.event.data[ERROR_KEY] && !context.event.data['@error'].modules && !!collector) { var modules = collector.getModules(context); if (modules && modules.length > 0) { context.event.data[ERROR_KEY].modules = modules; } } next && next(); }; return ModuleInfoPlugin; }()); exports.ModuleInfoPlugin = ModuleInfoPlugin; var RequestInfoPlugin = (function () { function RequestInfoPlugin() { this.priority = 70; this.name = 'RequestInfoPlugin'; } RequestInfoPlugin.prototype.run = function (context, next) { var REQUEST_KEY = '@request'; var config = context.client.config; var collector = config.requestInfoCollector; if (!context.event.data[REQUEST_KEY] && !!collector) { var requestInfo = collector.getRequestInfo(context); if (!!requestInfo) { if (Utils.isMatch(requestInfo.user_agent, config.userAgentBotPatterns)) { context.log.info('Cancelling event as the request user agent matches a known bot pattern'); context.cancelled = true; } else { context.event.data[REQUEST_KEY] = requestInfo; } } } next && next(); }; return RequestInfoPlugin; }()); exports.RequestInfoPlugin = RequestInfoPlugin; var EnvironmentInfoPlugin = (function () { function EnvironmentInfoPlugin() { this.priority = 80; this.name = 'EnvironmentInfoPlugin'; } EnvironmentInfoPlugin.prototype.run = function (context, next) { var ENVIRONMENT_KEY = '@environment'; var collector = context.client.config.environmentInfoCollector; if (!context.event.data[ENVIRONMENT_KEY] && collector) { var environmentInfo = collector.getEnvironmentInfo(context); if (!!environmentInfo) { context.event.data[ENVIRONMENT_KEY] = environmentInfo; } } next && next(); }; return EnvironmentInfoPlugin; }()); exports.EnvironmentInfoPlugin = EnvironmentInfoPlugin; var SubmissionMethodPlugin = (function () { function SubmissionMethodPlugin() { this.priority = 100; this.name = 'SubmissionMethodPlugin'; } SubmissionMethodPlugin.prototype.run = function (context, next) { var submissionMethod = context.contextData.getSubmissionMethod(); if (!!submissionMethod) { context.event.data['@submission_method'] = submissionMethod; } next && next(); }; return SubmissionMethodPlugin; }()); exports.SubmissionMethodPlugin = SubmissionMethodPlugin; var DuplicateCheckerPlugin = (function () { function DuplicateCheckerPlugin(getCurrentTime, interval) { var _this = this; if (getCurrentTime === void 0) { getCurrentTime = function () { return Date.now(); }; } if (interval === void 0) { interval = 30000; } this.priority = 1010; this.name = 'DuplicateCheckerPlugin'; this._mergedEvents = []; this._processedHashcodes = []; this._getCurrentTime = getCurrentTime; this._interval = interval; setInterval(function () { while (_this._mergedEvents.length > 0) { _this._mergedEvents.shift().resubmit(); } }, interval); } DuplicateCheckerPlugin.prototype.run = function (context, next) { var _this = this; function getHashCode(error) { var hashCode = 0; while (error) { if (error.message && error.message.length) { hashCode += (hashCode * 397) ^ Utils.getHashCode(error.message); } if (error.stack_trace && error.stack_trace.length) { hashCode += (hashCode * 397) ^ Utils.getHashCode(JSON.stringify(error.stack_trace)); } error = error.inner; } return hashCode; } var error = context.event.data['@error']; var hashCode = getHashCode(error); if (hashCode) { var count = context.event.count || 1; var now_1 = this._getCurrentTime(); var merged = this._mergedEvents.filter(function (s) { return s.hashCode === hashCode; })[0]; if (merged) { merged.incrementCount(count); merged.updateDate(context.event.date); context.log.info('Ignoring duplicate event with hash: ' + hashCode); context.cancelled = true; } if (!context.cancelled && this._processedHashcodes.some(function (h) { return h.hash === hashCode && h.timestamp >= (now_1 - _this._interval); })) { context.log.trace('Adding event with hash: ' + hashCode); this._mergedEvents.push(new MergedEvent(hashCode, context, count)); context.cancelled = true; } if (!context.cancelled) { context.log.trace('Enqueueing event with hash: ' + hashCode + 'to cache.'); this._processedHashcodes.push({ hash: hashCode, timestamp: now_1 }); while (this._processedHashcodes.length > 50) { this._processedHashcodes.shift(); } } } next && next(); }; return DuplicateCheckerPlugin; }()); exports.DuplicateCheckerPlugin = DuplicateCheckerPlugin; var MergedEvent = (function () { function MergedEvent(hashCode, context, count) { this.hashCode = hashCode; this._context = context; this._count = count; } MergedEvent.prototype.incrementCount = function (count) { this._count += count; }; MergedEvent.prototype.resubmit = function () { this._context.event.count = this._count; this._context.client.config.queue.enqueue(this._context.event); }; MergedEvent.prototype.updateDate = function (date) { if (date > this._context.event.date) { this._context.event.date = date; } }; return MergedEvent; }()); var EventExclusionPlugin = (function () { function EventExclusionPlugin() { this.priority = 45; this.name = 'EventExclusionPlugin'; } EventExclusionPlugin.prototype.run = function (context, next) { function getLogLevel(level) { switch ((level || '').toLowerCase().trim()) { case 'trace': case 'true': case '1': case 'yes': return 0; case 'debug': return 1; case 'info': return 2; case 'warn': return 3; case 'error': return 4; case 'fatal': return 5; case 'off': case 'false': case '0': case 'no': return 6; default: return -1; } } function getMinLogLevel(settings, loggerName) { if (loggerName === void 0) { loggerName = '*'; } return getLogLevel(getTypeAndSourceSetting(settings, 'log', loggerName, 'Trace') + ''); } function getTypeAndSourceSetting(settings, type, source, defaultValue) { if (settings === void 0) { settings = {}; } if (defaultValue === void 0) { defaultValue = undefined; } if (!type) { return defaultValue; } var isLog = type === 'log'; var sourcePrefix = "@@" + type + ":"; var value = settings[sourcePrefix + source]; if (value) { return !isLog ? Utils.toBoolean(value) : value; } for (var key in settings) { if (Utils.startsWith(key.toLowerCase(), sourcePrefix.toLowerCase()) && Utils.isMatch(source, [key.substring(sourcePrefix.length)])) { return !isLog ? Utils.toBoolean(settings[key]) : settings[key]; } } return defaultValue; } var ev = context.event; var log = context.log; var settings = context.client.config.settings; if (ev.type === 'log') { var minLogLevel = getMinLogLevel(settings, ev.source); var logLevel = getLogLevel(ev.data['@level']); if (logLevel >= 0 && (logLevel > 5 || logLevel < minLogLevel)) { log.info('Cancelling log event due to minimum log level.'); context.cancelled = true; } } else if (ev.type === 'error') { var error = ev.data['@error']; while (!context.cancelled && error) { if (getTypeAndSourceSetting(settings, ev.type, error.type, true) === false) { log.info("Cancelling error from excluded exception type: " + error.type); context.cancelled = true; } error = error.inner; } } else if (getTypeAndSourceSetting(settings, ev.type, ev.source, true) === false) { log.info("Cancelling event from excluded type: " + ev.type + " and source: " + ev.source); context.cancelled = true; } next && next(); }; return EventExclusionPlugin; }()); exports.EventExclusionPlugin = EventExclusionPlugin; var SettingsResponse = (function () { function SettingsResponse(success, settings, settingsVersion, exception, message) { if (settingsVersion === void 0) { settingsVersion = -1; } if (exception === void 0) { exception = null; } if (message === void 0) { message = null; } this.success = false; this.settingsVersion = -1; this.success = success; this.settings = settings; this.settingsVersion = settingsVersion; this.exception = exception; this.message = message; } return SettingsResponse; }()); exports.SettingsResponse = SettingsResponse; var InMemoryStorage = (function () { function InMemoryStorage(maxItems) { this.items = []; this.lastTimestamp = 0; this.maxItems = maxItems; } InMemoryStorage.prototype.save = function (value) { if (!value) { return null; } var items = this.items; var timestamp = Math.max(Date.now(), this.lastTimestamp + 1); var item = { timestamp: timestamp, value: value }; if (items.push(item) > this.maxItems) { items.shift(); } this.lastTimestamp = timestamp; return item.timestamp; }; InMemoryStorage.prototype.get = function (limit) { return this.items.slice(0, limit); }; InMemoryStorage.prototype.remove = function (timestamp) { var items = this.items; for (var i = 0; i < items.length; i++) { if (items[i].timestamp === timestamp) { items.splice(i, 1); return; } } }; InMemoryStorage.prototype.clear = function () { this.items = []; }; return InMemoryStorage; }()); exports.InMemoryStorage = InMemoryStorage; var KeyValueStorageBase = (function () { function KeyValueStorageBase(maxItems) { this.lastTimestamp = 0; this.maxItems = maxItems; } KeyValueStorageBase.prototype.save = function (value, single) { if (!value) { return null; } this.ensureIndex(); var items = this.items; var timestamp = Math.max(Date.now(), this.lastTimestamp + 1); var key = this.getKey(timestamp); var json = JSON.stringify(value); try { this.write(key, json); this.lastTimestamp = timestamp; if (items.push(timestamp) > this.maxItems) { this.delete(this.getKey(items.shift())); } } catch (e) { return null; } return timestamp; }; KeyValueStorageBase.prototype.get = function (limit) { var _this = this; this.ensureIndex(); return this.items.slice(0, limit) .map(function (timestamp) { var key = _this.getKey(timestamp); try { var json = _this.read(key); var value = JSON.parse(json, parseDate); return { timestamp: timestamp, value: value }; } catch (error) { _this.safeDelete(key); return null; } }) .filter(function (item) { return item != null; }); }; KeyValueStorageBase.prototype.remove = function (timestamp) { this.ensureIndex(); var items = this.items; var index = items.indexOf(timestamp); if (index >= 0) { var key = this.getKey(timestamp); this.safeDelete(key); items.splice(index, 1); } ; }; KeyValueStorageBase.prototype.clear = function () { var _this = this; this.items.forEach(function (item) { return _this.safeDelete(_this.getKey(item)); }); this.items = []; }; KeyValueStorageBase.prototype.ensureIndex = function () { if (!this.items) { this.items = this.createIndex(); this.lastTimestamp = Math.max.apply(Math, [0].concat(this.items)) + 1; } }; KeyValueStorageBase.prototype.safeDelete = function (key) { try { this.delete(key); } catch (error) { } }; KeyValueStorageBase.prototype.createIndex = function () { var _this = this; try { var keys = this.readAllKeys(); return keys.map(function (key) { try { var timestamp = _this.getTimestamp(key); if (!timestamp) { _this.safeDelete(key); return null; } return timestamp; } catch (error) { _this.safeDelete(key); return null; } }).filter(function (timestamp) { return timestamp != null; }) .sort(function (a, b) { return a - b; }); } catch (error) { return []; } }; return KeyValueStorageBase; }()); exports.KeyValueStorageBase = KeyValueStorageBase; function parseDate(key, value) { var dateRegx = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/g; if (typeof value === 'string') { var a = dateRegx.exec(value); if (a) { return new Date(value); } } return value; } ; var NodeFileStorage = (function (_super) { __extends(NodeFileStorage, _super); function NodeFileStorage(namespace, folder, prefix, maxItems, fs) { if (prefix === void 0) { prefix = 'ex-'; } if (maxItems === void 0) { maxItems = 20; } _super.call(this, maxItems); if (!folder) { folder = Path.join(Path.dirname(require.main.filename), '.exceptionless'); } var subfolder = Path.join(folder, namespace); this.directory = Path.resolve(subfolder); this.prefix = prefix; this.fs = fs ? fs : Fs; this.mkdir(this.directory); } NodeFileStorage.prototype.write = function (key, value) { this.fs.writeFileSync(key, value); }; NodeFileStorage.prototype.read = function (key) { return this.fs.readFileSync(key, 'utf8'); }; NodeFileStorage.prototype.readAllKeys = function () { var _this = this; return this.fs.readdirSync(this.directory) .filter(function (file) { return file.indexOf(_this.prefix) === 0; }) .map(function (file) { return Path.join(_this.directory, file); }); }; NodeFileStorage.prototype.delete = function (key) { this.fs.unlinkSync(key); }; NodeFileStorage.prototype.getKey = function (timestamp) { return Path.join(this.directory, "" + this.prefix + timestamp + ".json"); }; NodeFileStorage.prototype.getTimestamp = function (key) { return parseInt(Path.basename(key, '.json') .substr(this.prefix.length), 10); }; NodeFileStorage.prototype.mkdir = function (path) { var dirs = path.split(Path.sep); var root = ''; while (dirs.length > 0) { var dir = dirs.shift(); if (dir === '') { root = Path.sep; } if (!this.fs.existsSync(root + dir)) { this.fs.mkdirSync(root + dir); } root += dir + Path.sep; } }; ; return NodeFileStorage; }(KeyValueStorageBase)); exports.NodeFileStorage = NodeFileStorage; var NodeEnvironmentInfoCollector = (function () { function NodeEnvironmentInfoCollector() { } NodeEnvironmentInfoCollector.prototype.getEnvironmentInfo = function (context) { function getIpAddresses() { var ips = []; var interfaces = os.networkInterfaces(); Object.keys(interfaces).forEach(function (name) { interfaces[name].forEach(function (iface) { if ('IPv4' === iface.family && !iface.internal) { ips.push(iface.address); } }); }); return ips.join(', '); } if (!os) { return null; } var environmentInfo = { processor_count: os.cpus().length, total_physical_memory: os.totalmem(), available_physical_memory: os.freemem(), command_line: process.argv.join(' '), process_name: (process.title || '').replace(/[\uE000-\uF8FF]/g, ''), process_id: process.pid + '', process_memory_size: process.memoryUsage().heapTotal, architecture: os.arch(), o_s_name: os.type(), o_s_version: os.release(), ip_address: getIpAddresses(), machine_name: os.hostname(), runtime_version: process.version, data: { loadavg: os.loadavg(), platform: os.platform(), tmpdir: os.tmpdir(), uptime: os.uptime() } }; if (os.endianness) { environmentInfo.data.endianness = os.endianness(); } return environmentInfo; }; return NodeEnvironmentInfoCollector; }()); exports.NodeEnvironmentInfoCollector = NodeEnvironmentInfoCollector; var NodeErrorParser = (function () { function NodeErrorParser() { } NodeErrorParser.prototype.parse = function (context, exception) { function getStackFrames(stackFrames) { var frames = []; for (var index = 0; index < stackFrames.length; index++) { var frame = stackFrames[index]; frames.push({ name: frame.getMethodName() || frame.getFunctionName(), file_name: frame.getFileName(), line_number: frame.getLineNumber() || 0, column: frame.getColumnNumber() || 0, declaring_type: frame.getTypeName(), data: { is_native: frame.isNative() || (!!frame.filename && frame.filename[0] !== '/' && frame.filename[0] !== '.') } }); } return frames; } if (!nodestacktrace) { throw new Error('Unable to load the stack trace library.'); } var stackFrames = nodestacktrace.parse(exception) || []; return { type: exception.name, message: exception.message, stack_trace: getStackFrames(stackFrames) }; }; return NodeErrorParser; }()); exports.NodeErrorParser = NodeErrorParser; var NodeModuleCollector = (function () { function NodeModuleCollector() { this.initialized = false; this.installedModules = {}; } NodeModuleCollector.prototype.getModules = function (context) { var _this = this; this.initialize(); if (!require.main) { return []; } var modulePath = path.dirname(require.main.filename) + '/node_modules/'; var pathLength = modulePath.length; var loadedKeys = Object.keys(require.cache); var loadedModules = {}; loadedKeys.forEach(function (key) { var id = key.substr(pathLength); id = id.substr(0, id.indexOf('/')); loadedModules[id] = true; }); return Object.keys(loadedModules) .map(function (key) { return _this.installedModules[key]; }) .filter(function (m) { return m !== undefined; }); }; NodeModuleCollector.prototype.initialize = function () { var _this = this; if (this.initialized) { return; } this.initialized = true; var output = child.spawnSync('npm', ['ls', '--depth=0', '--json']).stdout; if (!output) { return; } var json; try { json = JSON.parse(output.toString()); } catch (e) { return; } var items = json.dependencies; if (!items) { return; } var id = 0; this.installedModules = {}; Object.keys(items).forEach(function (key) { var item = items[key]; var theModule = { module_id: id++, name: key, version: item.version }; _this.installedModules[key] = theModule; }); }; return NodeModuleCollector; }()); exports.NodeModuleCollector = NodeModuleCollector; var NodeRequestInfoCollector = (function () { function NodeRequestInfoCollector() { } NodeRequestInfoCollector.prototype.getRequestInfo = function (context) { var REQUEST_KEY = '@request'; if (!context.contextData[REQUEST_KEY]) { return null; } var exclusions = context.client.config.dataExclusions; var request = context.contextData[REQUEST_KEY]; var requestInfo = { client_ip_address: request.ip, user_agent: request.headers['user-agent'], is_secure: request.secure, http_method: request.method, host: request.hostname || request.host, path: request.path, post_data: JSON.parse(Utils.stringify(request.body || {}, exclusions)), cookies: Utils.getCookies(request.headers.cookie, exclusions), query_string: JSON.parse(Utils.stringify(request.params || {}, exclusions)) }; var host = request.headers.host; var port = host && parseInt(host.slice(host.indexOf(':') + 1), 10); if (port > 0) { requestInfo.port = port; } return requestInfo; }; return NodeRequestInfoCollector; }()); exports.NodeRequestInfoCollector = NodeRequestInfoCollector; var NodeSubmissionAdapter = (function () { function NodeSubmissionAdapter() { } NodeSubmissionAdapter.prototype.sendRequest = function (request, callback, isAppExiting) { var _this = this; if (isAppExiting) { this.sendRequestSync(request, callback); return; } var parsedHost = url.parse(request.url); var options = { auth: "client:" + request.apiKey, headers: {}, hostname: parsedHost.hostname, method: request.method, port: parsedHost.port && parseInt(parsedHost.port, 10), path: request.url }; options.headers['User-Agent'] = request.userAgent; if (request.method === 'POST') { options.headers = { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(request.data) }; } var protocol = (parsedHost.protocol === 'https' ? https : http); var clientRequest = protocol.request(options, function (response) { var body = ''; response.setEncoding('utf8'); response.on('data', function (chunk) { return body += chunk; }); response.on('end', function () { return _this.complete(response, body, response.headers, callback); }); }); clientRequest.on('error', function (error) { return callback && callback(500, error.message); }); clientRequest.end(request.data); }; NodeSubmissionAdapter.prototype.complete = function (response, responseBody, responseHeaders, callback) { var message; if (response.statusCode === 0) { message = 'Unable to connect to server.'; } else if (response.statusCode < 200 || response.statusCode > 299) { message = response.statusMessage || response.message; } callback && callback(response.statusCode || 500, message, responseBody, responseHeaders); }; NodeSubmissionAdapter.prototype.sendRequestSync = function (request, callback) { var requestJson = JSON.stringify(request); var res = child.spawnSync(process.execPath, [require.resolve('./submitSync.js')], { input: requestJson, stdio: ['pipe', 'pipe', process.stderr] }); var out = res.stdout.toString(); var result = JSON.parse(out); callback && callback(result.status, result.message, result.data, result.headers); }; return NodeSubmissionAdapter; }()); exports.NodeSubmissionAdapter = NodeSubmissionAdapter; var NodeFileStorageProvider = (function () { function NodeFileStorageProvider(folder, prefix, maxQueueItems) { if (maxQueueItems === void 0) { maxQueueItems = 250; } this.queue = new NodeFileStorage('q', folder, prefix, maxQueueItems); this.settings = new NodeFileStorage('settings', folder, prefix, 1); } return NodeFileStorageProvider; }()); exports.NodeFileStorageProvider = NodeFileStorageProvider; var EXIT = 'exit'; var UNCAUGHT_EXCEPTION = 'uncaughtException'; var SIGINT = 'SIGINT'; var SIGINT_CODE = 2; var defaults = Configuration.defaults; defaults.environmentInfoCollector = new NodeEnvironmentInfoCollector(); defaults.errorParser = new NodeErrorParser(); defaults.moduleCollector = new NodeModuleCollector(); defaults.requestInfoCollector = new NodeRequestInfoCollector(); defaults.submissionAdapter = new NodeSubmissionAdapter(); Configuration.prototype.useLocalStorage = function () { this.storage = new NodeFileStorageProvider(); SettingsManager.applySavedServerSettings(this); this.changed(); }; function getListenerCount(emitter, event) { if (emitter.listenerCount) { return emitter.listenerCount(event); } return require('events').listenerCount(emitter, event); } function onUncaughtException(callback) { var originalEmit = process.emit; process.emit = function (type, error) { if (type === UNCAUGHT_EXCEPTION) { callback(error); } return originalEmit.apply(this, arguments); }; } onUncaughtException(function (error) { ExceptionlessClient.default.submitUnhandledException(error, UNCAUGHT_EXCEPTION); }); process.on(SIGINT, function () { if (getListenerCount(process, SIGINT) <= 1) { process.exit(128 + SIGINT_CODE); } }); process.on(EXIT, function (code) { function getExitCodeReason(exitCode) { if (exitCode === 1) { return 'Uncaught Fatal Exception'; } if (exitCode === 3) { return 'Internal JavaScript Parse Error'; } if (exitCode === 4) { return 'Internal JavaScript Evaluation Failure'; } if (exitCode === 5) { return 'Fatal Exception'; } if (exitCode === 6) { return 'Non-function Internal Exception Handler '; } if (exitCode === 7) { return 'Internal Exception Handler Run-Time Failure'; } if (exitCode === 8) { return 'Uncaught Exception'; } if (exitCode === 9) { return 'Invalid Argument'; } if (exitCode === 10) { return 'Internal JavaScript Run-Time Failure'; } if (exitCode === 12) { return 'Invalid Debug Argument'; } return null; } var client = ExceptionlessClient.default; var message = getExitCodeReason(code); if (message !== null) { client.submitLog(EXIT, message, 'Error'); } client.config.queue.process(true); }); Error.stackTraceLimit = Infinity; //# sourceMappingURL=exceptionless.node.js.map