UNPKG

posthog-js

Version:

Posthog-js allows you to automatically capture usage and send events to PostHog.

156 lines • 7.82 kB
"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); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ExceptionObserver = void 0; var globals_1 = require("@posthog/browser-common/utils/globals"); var globals_2 = require("../../utils/globals"); var logger_1 = require("@posthog/browser-common/utils/logger"); var constants_1 = require("../../constants"); var core_1 = require("@posthog/core"); var logger = (0, logger_1.createLogger)('[ExceptionAutocapture]'); var ExceptionObserver = /** @class */ (function () { function ExceptionObserver(instance) { var _this = this; var _a; this._startCapturing = function () { var _a; if (!globals_1.window || !_this.isEnabled || !((_a = globals_2.assignableWindow.__PosthogExtensions__) === null || _a === void 0 ? void 0 : _a.errorWrappingFunctions)) { return; } var wrapOnError = globals_2.assignableWindow.__PosthogExtensions__.errorWrappingFunctions.wrapOnError; var wrapUnhandledRejection = globals_2.assignableWindow.__PosthogExtensions__.errorWrappingFunctions.wrapUnhandledRejection; var wrapConsoleError = globals_2.assignableWindow.__PosthogExtensions__.errorWrappingFunctions.wrapConsoleError; try { if (!_this._unwrapOnError && _this._config.capture_unhandled_errors) { _this._unwrapOnError = wrapOnError(_this.captureException.bind(_this)); } if (!_this._unwrapUnhandledRejection && _this._config.capture_unhandled_rejections) { _this._unwrapUnhandledRejection = wrapUnhandledRejection(_this.captureException.bind(_this)); } if (!_this._unwrapConsoleError && _this._config.capture_console_errors) { _this._unwrapConsoleError = wrapConsoleError(_this.captureException.bind(_this)); } } catch (e) { logger.error('failed to start', e); _this._stopCapturing(); } }; this._instance = instance; this._remoteEnabled = !!((_a = this._instance.persistence) === null || _a === void 0 ? void 0 : _a.props[constants_1.EXCEPTION_CAPTURE_ENABLED_SERVER_SIDE]); // Burst protection is scoped per exception type: captures ten exceptions before rate // limiting, then refills at a rate of one token / 10 second period (e.g. captures 1 // rate-limited exception of that type every 10 seconds until the burst ends). The bucket // size and refill rate can be tuned via the `exceptionRateLimiterBucketSize` and // `exceptionRateLimiterRefillRate` config options. this._rateLimiter = new core_1.BucketedRateLimiter(__assign(__assign({}, (0, core_1.resolveExceptionRateLimiterConfig)(this._instance.config.error_tracking)), { refillInterval: 10000, _logger: logger })); this._config = this._requiredConfig(); this.startIfEnabledOrStop(); } ExceptionObserver.prototype._requiredConfig = function () { var providedConfig = this._instance.config.capture_exceptions; var config = { capture_unhandled_errors: false, capture_unhandled_rejections: false, capture_console_errors: false, }; if ((0, core_1.isObject)(providedConfig)) { config = __assign(__assign({}, config), providedConfig); } else if ((0, core_1.isUndefined)(providedConfig) ? this._remoteEnabled : providedConfig) { config = __assign(__assign({}, config), { capture_unhandled_errors: true, capture_unhandled_rejections: true }); } return config; }; Object.defineProperty(ExceptionObserver.prototype, "isEnabled", { get: function () { return (this._config.capture_console_errors || this._config.capture_unhandled_errors || this._config.capture_unhandled_rejections); }, enumerable: false, configurable: true }); ExceptionObserver.prototype.startIfEnabledOrStop = function () { if (this.isEnabled) { logger.info('enabled'); this._stopCapturing(); this._loadScript(this._startCapturing); } else { this._stopCapturing(); } }; ExceptionObserver.prototype._loadScript = function (cb) { var _a, _b, _c; if ((_a = globals_2.assignableWindow.__PosthogExtensions__) === null || _a === void 0 ? void 0 : _a.errorWrappingFunctions) { // already loaded cb(); return; } (_c = (_b = globals_2.assignableWindow.__PosthogExtensions__) === null || _b === void 0 ? void 0 : _b.loadExternalDependency) === null || _c === void 0 ? void 0 : _c.call(_b, this._instance, 'exception-autocapture', function (err) { if (err) { return logger.error('failed to load script', err); } cb(); }); }; ExceptionObserver.prototype._stopCapturing = function () { var _a, _b, _c; (_a = this._unwrapOnError) === null || _a === void 0 ? void 0 : _a.call(this); this._unwrapOnError = undefined; (_b = this._unwrapUnhandledRejection) === null || _b === void 0 ? void 0 : _b.call(this); this._unwrapUnhandledRejection = undefined; (_c = this._unwrapConsoleError) === null || _c === void 0 ? void 0 : _c.call(this); this._unwrapConsoleError = undefined; }; ExceptionObserver.prototype.onRemoteConfig = function (result) { var _a; if (!result.ok) { // Failure behaves like a response without an autocaptureExceptions key. return; } var response = result.config; if (!('autocaptureExceptions' in response)) { return; } var autocaptureExceptionsResponse = response.autocaptureExceptions; // store this in-memory in case persistence is disabled this._remoteEnabled = !!autocaptureExceptionsResponse || false; if (this._instance.persistence) { this._instance.persistence.register((_a = {}, _a[constants_1.EXCEPTION_CAPTURE_ENABLED_SERVER_SIDE] = this._remoteEnabled, _a)); } this._config = this._requiredConfig(); this.startIfEnabledOrStop(); }; ExceptionObserver.prototype.onConfigChange = function () { this._config = this._requiredConfig(); }; ExceptionObserver.prototype.captureException = function (errorProperties) { var _a, _b, _c, _d; var exceptionType = (_c = (_b = (_a = errorProperties === null || errorProperties === void 0 ? void 0 : errorProperties.$exception_list) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.type) !== null && _c !== void 0 ? _c : 'Exception'; var isRateLimited = this._rateLimiter.consumeRateLimit(exceptionType); if (isRateLimited) { logger.info('Skipping exception capture because of client rate limiting.', { exception: exceptionType, }); return; } (_d = this._instance.exceptions) === null || _d === void 0 ? void 0 : _d.sendExceptionEvent(errorProperties); }; return ExceptionObserver; }()); exports.ExceptionObserver = ExceptionObserver; //# sourceMappingURL=index.js.map