@newrelic/video-core 4.0.2 → 4.1.1-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","mappings":"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","sources":["webpack://@newrelic/video-core/./src/optimizedHttpClient.js","webpack://@newrelic/video-core/./src/constants.js","webpack://@newrelic/video-core/./src/log.js","webpack://@newrelic/video-core/./src/tracker.js","webpack://@newrelic/video-core/./src/videotrackerstate.js","webpack://@newrelic/video-core/./src/utils.js","webpack://@newrelic/video-core/./src/harvestScheduler.js","webpack://@newrelic/video-core/./src/core.js","webpack://@newrelic/video-core/./src/retryQueueHandler.js","webpack://@newrelic/video-core/./src/eventAggregator.js","webpack://@newrelic/video-core/./src/recordEvent.js","webpack://@newrelic/video-core/./src/chrono.js","webpack://@newrelic/video-core/./src/agent.js","webpack://@newrelic/video-core/./src/emitter.js","webpack://@newrelic/video-core/./src/videoConfiguration.js","webpack://@newrelic/video-core/./src/videotracker.js","webpack://@newrelic/video-core/webpack/bootstrap","webpack://@newrelic/video-core/./src/index.js"],"sourcesContent":["import { dataSize, shouldRetry } from \"./utils\";\nimport Log from \"./log\";\n\n/**\n * Optimized HTTP client for video analytics data transmission with\n * performance monitoring and efficient request handling.\n */\nexport class OptimizedHttpClient {\n /**\n * Sends data to the specified URL with performance monitoring.\n * @param {object} requestOptions - Request configuration\n * @param {string} requestOptions.url - Target URL\n * @param {object} requestOptions.payload - Request payload\n * @param {object} requestOptions.options - Additional options\n * @param {Function} callback - Callback function for handling response\n * @returns {Promise<void>}\n */\n async send(requestOptions, callback) {\n const { url, payload, options = {} } = requestOptions;\n\n try {\n // Validate input\n if (!url || !payload) {\n throw new Error(\"URL and payload are required\");\n }\n\n // Create request object\n const request = {\n url,\n payload,\n options,\n callback,\n };\n\n // Execute request immediately\n await this.executeRequest(request);\n } catch (error) {\n Log.error(\"Failed to send request:\", error.message);\n callback({ retry: false, status: 0, error: error.message });\n }\n }\n\n /**\n * Executes an HTTP request with timeout and error handling.\n * @param {object} request - Request object\n * @private\n */\n async executeRequest(request) {\n const { url, payload, options, callback } = request;\n const startTime = Date.now();\n\n try {\n const requestBody = JSON.stringify(payload.body);\n\n // Handle final harvest with sendBeacon\n if (options.isFinalHarvest && navigator.sendBeacon) {\n const success = await this.sendWithBeacon(url, requestBody);\n const result = { success, status: success ? 204 : 0 };\n this.handleRequestComplete(request, result, startTime);\n return;\n }\n\n // Use fetch with timeout\n const response = await this.fetchWithTimeout(\n url,\n {\n method: \"POST\",\n body: requestBody,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n keepalive: options.isFinalHarvest,\n },\n 10000\n );\n\n const result = {\n success: response.ok,\n status: response.status,\n statusText: response.statusText,\n };\n\n this.handleRequestComplete(request, result, startTime);\n } catch (error) {\n const result = {\n success: false,\n status: 0,\n error: error.message,\n };\n\n this.handleRequestComplete(request, result, startTime);\n }\n }\n\n /**\n * Handles request completion.\n * @param {object} request - Request object\n * @param {object} result - Request result\n * @param {number} startTime - Request start timestamp\n * @param {string} endpoint - The endpoint that was used for the request\n * @private\n */\n handleRequestComplete(request, result) {\n const { callback } = request;\n\n // Use smart retry logic based on HTTP status codes\n const shouldRetryRequest =\n !result.success &&\n (result.status === 0 || // Network/timeout errors\n shouldRetry(result.status)); // Smart status code-based retry\n\n callback({\n retry: shouldRetryRequest,\n status: result.status,\n error: result.error,\n });\n }\n\n /**\n * Sends data using navigator.sendBeacon for final harvests.\n * @param {string} url - Target URL\n * @param {string} body - Request body\n * @returns {Promise<boolean>} True if successful\n * @private\n */\n async sendWithBeacon(url, body) {\n try {\n return navigator.sendBeacon(url, body);\n } catch (error) {\n Log.warn(\"sendBeacon failed, falling back to fetch:\", error.message);\n return false;\n }\n }\n\n /**\n * Fetch with timeout implementation.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/AbortController|MDN AbortController}\n * @param {string} url - Target URL\n * @param {object} options - Fetch options\n * @param {number} timeout - Timeout in milliseconds\n * @returns {Promise<Response>} Fetch response\n * @private\n */\n async fetchWithTimeout(url, options, timeout) {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error.name === \"AbortError\") {\n throw new Error(`Request timeout after ${timeout}ms`);\n }\n throw error;\n }\n }\n}\n\nexport default OptimizedHttpClient;\n","/**\n * Constants for the library.\n * @class Constants\n * @static\n */\nclass Constants {}\n\n/**\n * Enum for types/positions of ads.\n * @example var type = Constants.AdPositions.PRE\n * @enum {String}\n */\nConstants.AdPositions = {\n /** For ads shown before the content. */\n PRE: \"pre\",\n /** For ads shown during the content. */\n MID: \"mid\",\n /** For ads shown after the content. */\n POST: \"post\",\n};\n\n// bam.nr-data.net\n//bam-cell.nr-data.net\n\nConstants.COLLECTOR = {\n US: [\"bam.nr-data.net\", \"bam-cell.nr-data.net\"],\n EU: \"bam.eu01.nr-data.net\",\n Staging: \"staging-bam-cell.nr-data.net\",\n GOV: \"gov-bam.nr-data.net\",\n};\n\n// ====== VALID EVENT TYPES ======\nConstants.VALID_EVENT_TYPES = [\n \"VideoAction\",\n \"VideoAdAction\",\n \"VideoErrorAction\",\n \"VideoCustomAction\",\n];\n\nConstants.MAX_PAYLOAD_SIZE = 1048576; // 1MB = 1024 × 1024 bytes\nConstants.MAX_BEACON_SIZE = 61440; // 60KB = 60 × 1024 bytes\nConstants.MAX_EVENTS_PER_BATCH = 1000;\nConstants.INTERVAL = 10000; //10 seconds\n\nexport default Constants;\n","/**\n * Static Log class\n *\n * @class\n * @static\n */\nclass Log {\n /**\n * Sends an error console log.\n * @param {...any} [msg] Message to show\n * @static\n */\n static error(...msg) {\n _report(msg, Log.Levels.ERROR, \"darkred\");\n }\n\n /**\n * Sends a warning console log.\n * @method Log.warn\n * @static\n * @param {...any} msg Message to show\n */\n static warn(...msg) {\n _report(msg, Log.Levels.WARNING, \"darkorange\");\n }\n\n /**\n * Sends a notice console log.\n * @method Log.notice\n * @static\n * @param {...any} msg Message to show\n */\n static notice(...msg) {\n _report([].slice.call(arguments), Log.Levels.NOTICE, \"darkcyan\");\n }\n\n /**\n * Sends a debug message to console.\n * @method Log.debug\n * @static\n * @param {...any} msg Message to show\n */\n static debug(...msg) {\n _report(msg, Log.Levels.DEBUG, \"indigo\");\n }\n\n /**\n * This utility method will add most of the HTML5 common event listeners to the player sent.\n * Events will be reported as DEBUG level messages.\n *\n * @example\n * // Already included events:\n * ['canplay', 'buffering', 'waiting', 'ended', 'play', 'playing', 'pause', 'resume', 'error',\n * 'abort', 'seek', 'seeking', 'seeked', 'stalled', 'dispose', 'loadeddata', 'loadstart',\n * 'loadedmetadata']\n *\n * @method Log.debugCommonVideoEvents\n * @static\n * @param {object|function} o Object to attach the events.\n * @param {array} [extraEvents]\n * An array of extra events to watch. ie: ['timeupdate', 'progress'].\n * If the first item is null, no common events will be added.\n * @param {function} [report] Callback function called to report events.\n * Default calls Log.debug()\n */\n static debugCommonVideoEvents(o, extraEvents, report) {\n try {\n if (Log.level <= Log.Levels.DEBUG) {\n report =\n report ||\n function (e) {\n Log.debug(\"Event: \" + e.type);\n };\n\n var playerEvents = [\n \"canplay\",\n \"buffering\",\n \"waiting\",\n \"ended\",\n \"play\",\n \"playing\",\n \"pause\",\n \"resume\",\n \"error\",\n \"abort\",\n \"seek\",\n \"seeking\",\n \"seeked\",\n \"stalled\",\n \"dispose\",\n \"loadeddata\",\n \"loadstart\",\n \"loadedmetadata\",\n ];\n if (extraEvents) {\n if (extraEvents[0] === null) {\n extraEvents.shift();\n playerEvents = extraEvents;\n } else {\n playerEvents = playerEvents.concat(extraEvents);\n }\n }\n\n for (var i = 0; i < playerEvents.length; i++) {\n if (typeof o === \"function\") {\n o.call(window, playerEvents[i], report);\n } else if (o.on) {\n o.on(playerEvents[i], report);\n } else if (o.addEventListener) {\n o.addEventListener(playerEvents[i], report);\n } else if (o.addEventHandler) {\n o.addEventHandler(playerEvents[i], report);\n } else {\n Log.warn(\n \"debugCommonVideoEvents: No common listener function found for \",\n o\n );\n }\n }\n }\n } catch (err) {\n Log.warn(err);\n }\n }\n}\n\n/**\n * Enum for log levels\n * @enum {integer}\n * @static\n * @var\n */\nLog.Levels = {\n /** No console outputs */\n SILENT: 5,\n /** Console will show errors */\n ERROR: 4,\n /** Console will show warnings */\n WARNING: 3,\n /** Console will show notices (ie: life-cyrcle logs) */\n NOTICE: 2,\n /** Console will show debug messages. */\n DEBUG: 1,\n /** Show all messages. */\n ALL: 0,\n};\n\n/**\n * Only logs of this imporance or higher will be shown.\n * @example Log.level = Log.Levels.ALL\n * @default Log.Levels.ERROR\n * @static\n */\nLog.level = Log.Levels.ERROR;\n\n/**\n * If true, logs will be outputed with colors.\n * @default true\n * @static\n */\nLog.colorful = true;\n\n/**\n * If true, logs will include the time mark.\n * @default true\n * @static\n */\nLog.includeTime = true;\n\n/**\n * Prefix included at the start of every log.\n * @default '[New Relic]'\n * @static\n */\nLog.prefix = \"[nrvideo]\";\n\n// PRIVATE MEMBERS\n\n/**\n * Returns a console message\n *\n * @private\n * @param {array} msg Message array, error object or array of messages.\n * @param {Log.Level} [level=Log.Levels.NOTICE] Defines the level of the error sent.\n * Only errors with higher or equal level than Log.logLevel will be displayed.\n * @param {string} [color='darkgreen'] Color of the header\n * @see {@link Log.level}\n */\nfunction _report(msg, level, color) {\n level = level || Log.Levels.NOTICE;\n color = color || \"darkcyan\";\n\n var prefix = Log.prefix;\n if (Log.includeTime) prefix += _getCurrentTime() + \" \";\n prefix += _level2letter(level) + \":\";\n\n // Show messages in actual console if level is enought\n if (Log.level <= level && level !== Log.Levels.SILENT) {\n if (\n !Log.colorful ||\n (typeof document !== \"undefined\" && document.documentMode)\n ) {\n // document.documentMode exits only in IE\n _plainReport(msg, prefix);\n } else {\n // choose log method\n var logMethod;\n if (level === Log.Levels.ERROR && console.error) {\n logMethod = console.error;\n } else if (level === Log.Levels.WARNING && console.warn) {\n logMethod = console.warn;\n } else if (level === Log.Levels.DEBUG && console.debug) {\n // NOTE: for some reason console.debug doesn't work on CAF Receivers.\n if (window.cast == undefined) {\n logMethod = console.debug;\n } else {\n logMethod = console.log;\n }\n } else {\n logMethod = console.log;\n }\n\n // print message\n prefix = \"%c\" + prefix;\n msg.splice(0, 0, prefix, \"color: \" + color);\n logMethod.apply(console, msg);\n }\n }\n}\n\n/**\n * Returns the current time in format hh:mm:ss.mmm (with trailing 0s)\n * @private\n * @return {string} Current time.\n */\nfunction _getCurrentTime() {\n var d = new Date();\n var hh = (\"0\" + d.getDate()).slice(-2);\n var mm = (\"0\" + d.getMinutes()).slice(-2);\n var ss = (\"0\" + d.getSeconds()).slice(-2);\n var mmm = (\"00\" + d.getMilliseconds()).slice(-3);\n return \"[\" + hh + \":\" + mm + \":\" + ss + \".\" + mmm + \"]\";\n}\n\n/**\n * Returns a console message without style\n *\n * @private\n * @param {(string|object|array)} msg Message string, object or array of messages.\n * @param {string} prefix Prefix of the message.\n */\nfunction _plainReport(msg, prefix) {\n if (msg instanceof Array) {\n for (var m in msg) {\n _plainReport(msg[m], prefix);\n }\n } else {\n if (typeof msg === \"string\") {\n console.log(prefix + \" \" + msg);\n } else {\n console.log(prefix + \"↵\");\n console.log(msg);\n }\n }\n}\n\nconst _letters = {\n 4: \"e\", // Error\n 3: \"w\", // Warning\n 2: \"n\", // Notice\n 1: \"d\", // Debug\n};\n\n/**\n * Transforms a level to a letter to identify every message.\n *\n * @private\n * @param {sLog.Level} level Level of the message\n */\nfunction _level2letter(level) {\n return _letters[level];\n}\n\n/**\n * This function is automatically executed at load.\n * Will search inside window.location.search for attribute 'nrvideo-debug=X'.\n * X can have one of these values, that will modify Log.Levels.\n * 5: SILENT,\n * 4: ERROR,\n * 3: WARNING,\n * 2: NOTICE,\n * 1: DEBUG,\n *\n * If nrvideo-colors=false is present, Log.colorful will be set to false.\n *\n * @private\n */\nfunction _loadLevelFromUrl() {\n if (\n typeof window !== \"undefined\" &&\n window.location &&\n window.location.search\n ) {\n var m = /\\?.*&*nrvideo-debug=(.+)/i.exec(window.location.search);\n if (m !== null) {\n if (m[1] === \"true\") {\n Log.level = Log.Levels.ALL;\n } else {\n Log.level = m[1];\n }\n }\n\n var m2 = /\\?.*&*nrvideo-colors=false/i.exec(window.location.search);\n if (m2 !== null) {\n Log.colorful = false;\n }\n }\n}\n\n// Execute load level\n_loadLevelFromUrl();\n\nexport default Log;\n","import pkg from \"../package.json\";\nimport Emitter from \"./emitter\";\nimport Chrono from \"./chrono\";\nimport Constants from \"./constants\";\nimport { videoAnalyticsHarvester } from \"./agent\";\nimport Log from \"./log\";\n\n/**\n * Tracker class provides the basic logic to extend Newrelic's Browser Agent capabilities.\n * Trackers are designed to listen third party elements (like video tags, banners, etc.) and send\n * information over to Browser Agent. Extend this class to create your own tracker, override\n * registerListeners and unregisterListeners for full coverage!\n *\n * @example\n * Tracker instances should be added to Core library to start sending data:\n * nrvideo.Core.addTracker(new Tracker())\n *\n * @extends Emitter\n */\nclass Tracker extends Emitter {\n /**\n * Constructor, receives options. You should call {@see registerListeners} after this.\n *\n * @param {Object} [options] Options for the tracker. See {@link setOptions}.\n */\n constructor(options) {\n super();\n\n /**\n * If you add something to this custom dictionary it will be added to every action. If you set\n * any value, it will always override the values returned by the getters.\n *\n * @example\n * If you define tracker.customData.contentTitle = 'a' and tracker.getTitle() returns 'b'.\n * 'a' will prevail.\n */\n this.customData = {};\n\n /**\n * Set time between hearbeats, in ms.\n */\n this.heartbeat = null;\n\n /**\n * Another Tracker instance. Useful to relate ad Trackers to their parent content Trackers.\n * @type Tracker\n */\n this.parentTracker = null;\n\n /**\n * Chrono that counts time since this class was instantiated.\n * @private\n */\n this._trackerReadyChrono = new Chrono();\n this._trackerReadyChrono.start();\n\n /**\n * Store the initial table of actions with time 0 ms\n */\n this._actionTable = Constants.ACTION_TABLE;\n this._actionAdTable = Constants.ACTION_AD_TABLE;\n\n options = options || {};\n this.setOptions(options);\n }\n\n /**\n * Set options for the Tracker.\n *\n * @param {Object} [options] Options for the tracker.\n * @param {number} [options.heartbeat] Set time between heartbeats. See {@link heartbeat}.\n * @param {Object} [options.customData] Set custom data. See {@link customData}.\n * @param {Tracker} [options.parentTracker] Set parent tracker. See {@link parentTracker}.\n */\n setOptions(options) {\n if (options) {\n if (options.parentTracker) this.parentTracker = options.parentTracker;\n if (options.customData) this.customData = options.customData;\n if (options.heartbeat) this.heartbeat = options.heartbeat;\n }\n }\n\n /**\n * Prepares tracker to dispose. Calls {@see unregisterListeners} and drops references.\n */\n dispose() {\n this.unregisterListeners();\n }\n\n /**\n * Override this method to register listeners to third party elements.\n *\n * @example\n * class SpecificTracker extends Tracker {\n * registerListeners() {\n * this.player.on('play', () => this.playHandler)\n * }\n *\n * playHandler() {\n * this.emit(Tracker.Events.REQUESTED)\n * }\n * }\n */\n registerListeners() {}\n\n /**\n * Override this method to unregister listeners to third party elements created with\n * {@see registerListeners}.\n *\n * @example\n * class SpecificTracker extends Tracker {\n * registerListeners() {\n * this.player.on('play', () => this.playHandler)\n * }\n *\n * unregisterListeners() {\n * this.player.off('play', () => this.playHandler)\n * }\n *\n * playHandler() {\n * this.emit(Tracker.Events.REQUESTED)\n * }\n * }\n */\n unregisterListeners() {}\n\n /**\n * Returns heartbeat time interval. 30000 (30s) if not set. See {@link setOptions}.\n * @return {number} Heartbeat interval in ms.\n * @final\n */\n getHeartbeat() {\n if (this.state._isAd) {\n // modifying heartbeat for Ad Tracker\n return 2000;\n } else {\n if (this.heartbeat) {\n return this.heartbeat;\n } else if (this.parentTracker && this.parentTracker.heartbeat) {\n return this.parentTracker.heartbeat;\n } else {\n return 30000;\n }\n }\n }\n\n /**\n * Starts heartbeating. Interval period set by options.heartbeat. Min 2000 ms.\n * This method is automaticaly called by the tracker once sendRequest is called.\n */\n startHeartbeat() {\n this._heartbeatInterval = setInterval(\n this.sendHeartbeat.bind(this),\n Math.max(this.getHeartbeat(), 2000)\n );\n }\n\n /**\n * Stops heartbeating. This method is automaticaly called by the tracker.\n */\n stopHeartbeat() {\n if (this._heartbeatInterval) {\n clearInterval(this._heartbeatInterval);\n }\n }\n\n /**\n * Heartbeating allows you to call this function each X milliseconds, defined by\n * {@link getHeartbeat}. This is useful to send regular events to track changes.\n *\n * By default it will send {@link Tracker.Events.HEARTBEAT}.\n * To start heartbeating use {@link startHeartbeat} and to stop them use {@link stopHeartbeat}.\n *\n * @example\n * Override this method to define your own Heartbeat reporting.\n *\n * class TrackerChild extends Tracker {\n * sendHeartbeat (att) {\n * this.send('MY_HEARBEAT_EVENT')\n * }\n * }\n *\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendHeartbeat(att) {\n this.sendVideoAction(Tracker.Events.HEARTBEAT, att);\n }\n\n /**\n * Override this method to return attributes for actions.\n *\n * @example\n * class SpecificTracker extends Tracker {\n * getAttributes(att) {\n * att = att || {}\n * att.information = 'something'\n * return att\n * }\n * }\n *\n * @param {object} [att] Collection of key value attributes\n * @return {object} Filled attributes\n * @final\n */\n getAttributes(att, eventType) {\n att = att || {};\n att.trackerName = this.getTrackerName();\n att.trackerVersion = this.getTrackerVersion();\n att.coreVersion = pkg.version;\n att.timeSinceTrackerReady = this._trackerReadyChrono.getDeltaTime();\n\n for (let key in this.customData) {\n att[key] = this.customData[key];\n }\n\n if (document.hidden != undefined) {\n att.isBackgroundEvent = document.hidden;\n }\n\n return att;\n }\n\n /** Override to change of the Version of tracker. ie: '1.0.1' */\n getTrackerVersion() {\n return pkg.version;\n }\n\n /** Override to change of the Name of the tracker. ie: 'custom-html5' */\n getTrackerName() {\n return \"base-tracker\";\n }\n\n /**\n * Send given event. Will automatically call {@see getAttributes} to fill information.\n * Internally, this will call {@see Emitter#emit}, so you could listen any event fired.\n *\n * @example\n * tracker.sendVideoAction('BANNER_CLICK', { url: 'http....' })\n *\n * @param {string} event Event name\n * @param {object} [att] Key:value dictionary filled with attributes.\n */\n\n sendVideoAction(event, att) {\n this.emit(\"VideoAction\", event, this.getAttributes(att));\n }\n\n sendVideoAdAction(event, att) {\n this.emit(\"VideoAdAction\", event, this.getAttributes(att));\n }\n\n sendVideoErrorAction(event, att) {\n let ev = this.isAd() ? \"adError\" : \"videoError\";\n this.emit(\"VideoErrorAction\", event, this.getAttributes(att, ev));\n }\n\n sendVideoCustomAction(event, att) {\n this.emit(\n \"VideoCustomAction\",\n event,\n this.getAttributes(att, \"customAction\")\n );\n }\n\n /**\n * Sets the harvest interval for video tracking.\n * @param {*} interval - The interval in milliseconds.\n * @returns {void}\n */\n\n setHarvestInterval(interval) {\n if (!videoAnalyticsHarvester) {\n Log.error(\"VideoAnalyticsHarvester is not available\");\n return;\n }\n\n try {\n videoAnalyticsHarvester.setHarvestInterval(interval);\n } catch (error) {\n Log.error(\"Failed to set harvest interval:\", error.message);\n return;\n }\n }\n}\n\n/**\n * Enumeration of events fired by this class.\n *\n * @static\n * @memberof Tracker\n * @enum {string}\n */\nTracker.Events = {\n /** The heartbeat event is sent once every 30 seconds while the video is playing. */\n HEARTBEAT: \"HEARTBEAT\",\n};\n\nexport default Tracker;\n","import Chrono from \"./chrono\";\nimport Log from \"./log\";\n\n/**\n * State machine for a VideoTracker and its monitored video.\n */\nclass VideoTrackerState {\n /** Constructor */\n constructor() {\n this.reset();\n\n //this.setupNetworkListeners();\n\n /**\n * Time when the VideoTrackerState was initializated.\n * @private\n */\n this._createdAt = Date.now();\n this._hb = true;\n this._acc = 0;\n this._bufferAcc = 0;\n }\n\n /** Resets all flags and chronos. */\n reset() {\n /**\n * Unique identifier of the view.\n * @private\n */\n this._viewSession = null;\n\n /**\n * Number of views seen.\n * @private\n */\n this._viewCount = 0;\n\n /**\n * True if it is tracking ads.\n * @private\n */\n this._isAd = false;\n\n /**\n * Number of errors fired. 'End' resets it.\n */\n this.numberOfErrors = 0;\n\n /**\n * Number of ads shown.\n */\n this.numberOfAds = 0;\n\n /**\n * Number of videos played.\n */\n this.numberOfVideos = 0;\n\n /**\n * The amount of ms the user has been watching content (not paused, not buffering, not ads...)\n */\n this.totalPlaytime = 0;\n\n /**\n * The amount of ms the user has been watching ads during an ad break.\n */\n this.totalAdPlaytime = 0;\n\n /** True if you are in the middle of an ad break. */\n this.isAdBreak = false;\n\n /** True if initial buffering event already happened. */\n this.initialBufferingHappened = false;\n\n this.resetFlags();\n this.resetChronos();\n }\n\n /** Resets flags. */\n resetFlags() {\n /** True once the player has finished loading. */\n this.isPlayerReady = false;\n\n /** True if the video has been user-requested to play. ie: user cicks play. */\n this.isRequested = false;\n\n /** True if the video has starting playing. ie: actual images/audio showing in screen. */\n this.isStarted = false;\n\n /** True if the video is paused. */\n this.isPaused = false;\n\n /** True if the video is performing a seek action. */\n this.isSeeking = false;\n\n /** True if the video is currently buffering. */\n this.isBuffering = false;\n\n /** True if the video is currently playing (not buffering, not paused...) */\n this.isPlaying = false;\n }\n\n /** Resets chronos. */\n resetChronos() {\n /** Chrono that counts time since last requested event. */\n this.timeSinceRequested = new Chrono();\n\n /** Chrono that counts time since last start event. */\n this.timeSinceStarted = new Chrono();\n\n /** Chrono that counts time since last pause event. */\n this.timeSincePaused = new Chrono();\n\n /** Chrono that counts time since last seeking start event. */\n this.timeSinceSeekBegin = new Chrono();\n\n /** Chrono that counts time since last buffering start event. */\n this.timeSinceBufferBegin = new Chrono();\n\n /** Chrono that counts time since last ad break start event. */\n this.timeSinceAdBreakStart = new Chrono();\n\n /** Chrono that counts time since last download event. */\n this.timeSinceLastDownload = new Chrono();\n\n /** Chrono that counts time since last heartbeat. */\n this.timeSinceLastHeartbeat = new Chrono();\n\n /** Chrono that counts time since last rendition change. */\n this.timeSinceLastRenditionChange = new Chrono();\n\n /** Ads only. Chrono that counts time since last ad quartile. */\n this.timeSinceLastAdQuartile = new Chrono();\n\n /** Content only. Chrono that counts time since last AD_END. */\n this.timeSinceLastAd = new Chrono();\n\n /** Chrono that counts time since last error event. */\n this.timeSinceLastError = new Chrono();\n\n /** Chrono that counts time since last ad error event. */\n this.timeSinceLastAdError = new Chrono();\n\n /** Chrono that counts time since last *_RESUME. Only for buffering events. */\n this.timeSinceResumed = new Chrono();\n\n /** Chrono that counts time since last *_SEEK_END. Only for buffering events. */\n this.timeSinceSeekEnd = new Chrono();\n\n /** Chrono that counts the ammount of time the video have been playing since the last event. */\n this.playtimeSinceLastEvent = new Chrono();\n\n /** A dictionary containing the custom timeSince attributes. */\n this.customTimeSinceAttributes = {};\n\n /** This are used to collect the time of buffred and pause resume between two heartbeats */\n this.elapsedTime = new Chrono();\n this.bufferElapsedTime = new Chrono();\n }\n\n /** Returns true if the tracker is currently on ads. */\n isAd() {\n return this._isAd;\n }\n\n /** Sets if the tracker is currenlty tracking ads */\n setIsAd(isAd) {\n this._isAd = isAd;\n }\n\n /**\n * Set the Chrono for the custom attribute\n *\n * @param {object} name Time since attribute name.\n */\n setTimeSinceAttribute(name) {\n this.customTimeSinceAttributes[name] = new Chrono();\n this.customTimeSinceAttributes[name].start();\n }\n\n /**\n * Delete a time since attribute\n *\n * @param {object} name Time since attribute name.\n */\n removeTimeSinceAttribute(name) {\n delete this.customTimeSinceAttributes[name];\n }\n\n /**\n * Returns a random-generated view Session ID, useful to sort by views.\n */\n getViewSession() {\n if (!this._viewSession) {\n let time = new Date().getTime();\n let random =\n Math.random().toString(36).substring(2) +\n Math.random().toString(36).substring(2);\n\n this._viewSession = time + \"-\" + random;\n }\n\n return this._viewSession;\n }\n\n /**\n * Returns a random-generated view Session ID, plus a view count, allowing you to distinguish\n * between two videos played in the same session.\n */\n getViewId() {\n return this.getViewSession() + \"-\" + this._viewCount;\n }\n\n /**\n * Fills given object with state-based attributes.\n *\n * @param {object} att Collection fo key value attributes\n * @return {object} Filled attributes\n */\n getStateAttributes(att) {\n att = att || {};\n\n if (this.isAd()) {\n // Ads only\n if (this.isRequested) {\n att.timeSinceAdRequested = this.timeSinceRequested.getDeltaTime();\n att.timeSinceLastAdHeartbeat =\n this.timeSinceLastHeartbeat.getDeltaTime();\n }\n if (this.isStarted)\n att.timeSinceAdStarted = this.timeSinceStarted.getDeltaTime();\n if (this.isPaused)\n att.timeSinceAdPaused = this.timeSincePaused.getDeltaTime();\n if (this.isBuffering)\n att.timeSinceAdBufferBegin = this.timeSinceBufferBegin.getDeltaTime();\n if (this.isSeeking)\n att.timeSinceAdSeekBegin = this.timeSinceSeekBegin.getDeltaTime();\n if (this.isAdBreak)\n att.timeSinceAdBreakBegin = this.timeSinceAdBreakStart.getDeltaTime();\n\n // Only include timeSinceLastAdError if an ad error has occurred\n if (this.numberOfErrors > 0 && this.timeSinceLastAdError.startTime > 0) {\n att.timeSinceLastAdError = this.timeSinceLastAdError.getDeltaTime();\n }\n\n att.numberOfAds = this.numberOfAds;\n } else {\n // Content only\n if (this.isRequested) {\n att.timeSinceRequested = this.timeSinceRequested.getDeltaTime();\n att.timeSinceLastHeartbeat = this.timeSinceLastHeartbeat.getDeltaTime();\n }\n if (this.isStarted)\n att.timeSinceStarted = this.timeSinceStarted.getDeltaTime();\n if (this.isPaused)\n att.timeSincePaused = this.timeSincePaused.getDeltaTime();\n if (this.isBuffering)\n att.timeSinceBufferBegin = this.timeSinceBufferBegin.getDeltaTime();\n if (this.isSeeking)\n att.timeSinceSeekBegin = this.timeSinceSeekBegin.getDeltaTime();\n att.timeSinceLastAd = this.timeSinceLastAd.getDeltaTime();\n\n // Only include timeSinceLastError if a content error has occurred\n if (this.numberOfErrors > 0 && this.timeSinceLastError.startTime > 0) {\n att.timeSinceLastError = this.timeSinceLastError.getDeltaTime();\n }\n\n att.numberOfVideos = this.numberOfVideos;\n }\n att.numberOfErrors = this.numberOfErrors;\n\n // Playtime\n if (!this.isAd()) {\n // Content only\n if (this.playtimeSinceLastEvent.startTime > 0) {\n att.playtimeSinceLastEvent = this.playtimeSinceLastEvent.getDeltaTime();\n } else {\n att.playtimeSinceLastEvent = 0;\n }\n if (this.isPlaying) {\n this.playtimeSinceLastEvent.start();\n } else {\n this.playtimeSinceLastEvent.reset();\n }\n this.totalPlaytime += att.playtimeSinceLastEvent;\n att.totalPlaytime = this.totalPlaytime;\n }\n\n for (const [key, value] of Object.entries(this.customTimeSinceAttributes)) {\n att[key] = value.getDeltaTime();\n }\n\n return att;\n }\n\n /**\n * Calculate the bufferType attribute.\n *\n * @param {boolean} isInitialBuffering Is initial buffering event.\n */\n calculateBufferType(isInitialBuffering) {\n let bufferType = \"\";\n if (isInitialBuffering) {\n bufferType = \"initial\";\n } else if (this.isSeeking) {\n bufferType = \"seek\";\n } else if (this.isPaused) {\n bufferType = \"pause\";\n } else {\n // If none of the above is true, it is a connection buffering\n bufferType = \"connection\";\n }\n Log.debug(\"Buffer Type = \" + bufferType);\n\n return bufferType;\n }\n\n /**\n * Augments view count. This will be called with each *_START and *_END.\n */\n goViewCountUp() {\n this._viewCount++;\n }\n\n /**\n * Checks flags and changes state.\n * @returns {boolean} True if the state changed.\n */\n goPlayerReady() {\n if (!this.isPlayerReady) {\n this.isPlayerReady = true;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goRequest() {\n if (!this.isRequested) {\n this.isRequested = true;\n\n this.timeSinceLastAd.reset();\n this.timeSinceRequested.start();\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goStart() {\n if (this.isRequested && !this.isStarted) {\n if (this.isAd()) {\n this.numberOfAds++;\n } else {\n this.numberOfVideos++;\n }\n this.isStarted = true;\n this.isPlaying = true;\n this.timeSinceStarted.start();\n this.playtimeSinceLastEvent.start();\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goEnd() {\n if (this.isRequested) {\n this.numberOfErrors = 0;\n this.resetFlags();\n this.timeSinceRequested.stop();\n this.timeSinceStarted.stop();\n this.playtimeSinceLastEvent.stop();\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goPause() {\n if (this.isStarted && !this.isPaused) {\n this.isPaused = true;\n this.isPlaying = false;\n this.timeSincePaused.start();\n this.playtimeSinceLastEvent.stop();\n this.timeSinceResumed.reset();\n if (this.isBuffering) {\n this._bufferAcc += this.bufferElapsedTime.getDeltaTime();\n }\n this.elapsedTime.start();\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goResume() {\n if (this.isStarted && this.isPaused) {\n this.isPaused = false;\n this.isPlaying = true;\n this.timeSincePaused.stop();\n this.timeSinceResumed.start();\n if (this._hb) {\n this._acc = this.elapsedTime.getDeltaTime();\n this._hb = false;\n } else {\n if (this.isBuffering) {\n this.bufferElapsedTime.start();\n }\n this._acc += this.elapsedTime.getDeltaTime();\n }\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goBufferStart() {\n if (this.isRequested && !this.isBuffering) {\n this.isBuffering = true;\n this.isPlaying = false;\n this.timeSinceBufferBegin.start();\n this.bufferElapsedTime.start();\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goBufferEnd() {\n if (this.isRequested && this.isBuffering) {\n this.isBuffering = false;\n this.isPlaying = true;\n this.timeSinceBufferBegin.stop();\n if (this._hb) {\n this._bufferAcc = this.bufferElapsedTime.getDeltaTime();\n this._hb = false;\n } else {\n this._bufferAcc += this.bufferElapsedTime.getDeltaTime();\n }\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goSeekStart() {\n if (this.isStarted && !this.isSeeking) {\n this.isSeeking = true;\n this.isPlaying = false;\n this.timeSinceSeekBegin.start();\n this.timeSinceSeekEnd.reset();\n\n //new\n // this.seekStartTime = Date.now();\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goSeekEnd() {\n if (this.isStarted && this.isSeeking) {\n this.isSeeking = false;\n this.isPlaying = true;\n this.timeSinceSeekBegin.stop();\n this.timeSinceSeekEnd.start();\n\n //new\n // this.seekEndTime = Date.now();\n // this.seekDuration = this.seekEndTime - this.seekStartTime;\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goAdBreakStart() {\n if (!this.isAdBreak) {\n this.isAdBreak = true;\n this.timeSinceAdBreakStart.start();\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goAdBreakEnd() {\n if (this.isAdBreak) {\n this.isRequested = false;\n this.isAdBreak = false;\n this.totalAdPlaytime = this.timeSinceAdBreakStart.getDeltaTime();\n this.timeSinceAdBreakStart.stop();\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Restarts download chrono.\n */\n goDownload() {\n this.timeSinceLastDownload.start();\n }\n\n /**\n * Restarts heartbeat chrono.\n */\n goHeartbeat() {\n this.timeSinceLastHeartbeat.start();\n }\n\n /**\n * Restarts rendition change chrono.\n */\n goRenditionChange() {\n this.timeSinceLastRenditionChange.start();\n }\n\n /**\n * Restarts ad quartile chrono.\n */\n goAdQuartile() {\n this.timeSinceLastAdQuartile.start();\n }\n\n /**\n * Increments error counter and starts appropriate error timer.\n */\n goError() {\n this.isError = true;\n this.numberOfErrors++;\n\n if (this.isAd()) {\n this.timeSinceLastAdError.start();\n } else {\n this.timeSinceLastError.start();\n }\n }\n\n /**\n * Restarts last ad chrono.\n */\n goLastAd() {\n this.timeSinceLastAd.start();\n }\n}\n\nexport default VideoTrackerState;\n","import pkg from \"../package.json\";\nimport Log from \"./log\";\n\n/**\n * Builds the harvest URL with proper query parameters.\n * @returns {string} Harvest URL\n */\n\nexport function buildUrl(fallbackUrl) {\n try {\n if (!window.NRVIDEO || !window.NRVIDEO.info) {\n throw new Error(\"NRVIDEO info is not available.\");\n }\n\n let { beacon, licenseKey, applicationID } = window.NRVIDEO.info;\n\n if (!beacon || !licenseKey)\n throw new Error(\n \"Options object provided by New Relic is not correctly initialized\"\n );\n\n if (applicationID) {\n return `https://${\n fallbackUrl ? fallbackUrl : beacon\n }/ins/1/${licenseKey}?a=${applicationID}&v=${pkg.version}&ref=${\n window.location.href\n }&ca=VA`;\n }\n\n return `https://${\n fallbackUrl ? fallbackUrl : beacon\n }/ins/1/${licenseKey}?&v=${pkg.version}&ref=${window.location.href}&ca=VA`;\n } catch (error) {\n console.error(error.message);\n return null; // Return null instead of undefined\n }\n}\n\n/**\n * Returns a function for use as a replacer parameter in JSON.stringify() to handle circular references.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value MDN - Cyclical object value}\n * @returns {Function} A function that filters out values it has seen before.\n */\nconst getCircularReplacer = () => {\n const seen = new WeakSet();\n return (key, value) => {\n if (typeof value === \"object\" && value !== null) {\n if (seen.has(value)) {\n return;\n }\n seen.add(value);\n }\n return value;\n };\n};\n\n/**\n * The native JSON.stringify method augmented with a replacer function to handle circular references.\n * Circular references will be excluded from the JSON output rather than triggering errors.\n * @param {*} val - A value to be converted to a JSON string.\n * @returns {string} A JSON string representation of the value, with circular references handled.\n */\nfunction stringify(val) {\n try {\n return JSON.stringify(val, getCircularReplacer()) ?? \"\";\n } catch (e) {\n Log.error(\"Error stringifying value:\", e.message);\n return \"\";\n }\n}\n\nexport function dataSize(data) {\n if (typeof data === \"string\" && data.length) return data.length;\n if (typeof data !== \"object\") return undefined;\n // eslint-disable-next-line\n if (\n typeof ArrayBuffer !== \"undefined\" &&\n data instanceof ArrayBuffer &&\n data.byteLength\n )\n return data.byteLength;\n if (typeof Blob !== \"undefined\" && data instanceof Blob && data.size)\n return data.size;\n if (typeof FormData !== \"undefined\" && data instanceof FormData)\n return undefined;\n\n try {\n return stringify(data).length;\n } catch (e) {\n return undefined;\n }\n}\n\n/**\n * Determines if a request should be retried based on HTTP status code\n * @param {number} status - HTTP status code\n * @returns {boolean} - True if request should be retried\n */\nexport function shouldRetry(status) {\n switch (status) {\n case 408: // Request Timeout\n case 429: // Too Many Requests\n case 500: // Internal Server Error\n return true;\n case 401: // Unauthorized - don't retry\n case 403: // Forbidden - don't retry\n case 404: // Not Found - don't retry\n return false;\n }\n // Retry for 5xx server errors and specific ranges\n return (status >= 502 && status <= 504) || (status >= 512 && status <= 530);\n}\n\n/**\n * Compresses a JSON payload using the Compression Streams API with Gzip.\n * see @description(https://developer.mozilla.org/en-US/docs/Web/API/Compression_Streams_API)\n * @param {object} payload - The JSON object to compress.\n * @returns {Promise<Blob>} A Promise that resolves with a Blob of the Gzipped data.\n */\n\nexport function compressPayload(payload) {\n const stringifiedPayload = JSON.stringify(payload);\n const stream = new Blob([stringifiedPayload]).stream();\n const compressionStream = new CompressionStream(\"gzip\");\n const compressedStream = stream.pipeThrough(compressionStream);\n\n return new Response(compressedStream).blob();\n}\n\n/**\n * Decompresses a gzipped Blob back to a JSON object using the Compression Streams API.\n * @param {Blob|ArrayBuffer|Uint8Array} compressedData - The gzipped data to decompress.\n * @returns {Promise<object>} A Promise that resolves with the decompressed JSON object.\n */\nexport async function decompressPayload(compressedData) {\n try {\n // Convert different input types to a stream\n let stream;\n if (compressedData instanceof Blob) {\n stream = compressedData.stream();\n } else if (compressedData instanceof ArrayBuffer) {\n stream = new Blob([compressedData]).stream();\n } else if (compressedData instanceof Uint8Array) {\n stream = new Blob([compressedData]).stream();\n } else {\n throw new Error(\"Unsupported compressed data type\");\n }\n\n // Decompress using DecompressionStream\n const decompressionStream = new DecompressionStream(\"gzip\");\n const decompressedStream = stream.pipeThrough(decompressionStream);\n\n // Convert back to text\n const response = new Response(decompressedStream);\n const decompressedText = await response.text();\n\n // Parse JSON\n return JSON.parse(decompressedText);\n } catch (error) {\n throw new Error(`Failed to decompress payload: ${error.message}`);\n }\n}\n","import { NrVideoEventAggregator } from \"./eventAggregator\";\nimport { RetryQueueHandler } from \"./retryQueueHandler\";\nimport { OptimizedHttpClient } from \"./optimizedHttpClient\";\nimport { buildUrl, dataSize } from \"./utils\";\nimport Constants from \"./constants\";\nimport Log from \"./log\";\n\n/**\n * Enhanced harvest scheduler that orchestrates the video analytics data collection,\n * processing, and transmission with smart harvesting and performance monitoring.\n */\n\nexport class HarvestScheduler {\n constructor(eventAggregator) {\n // Core components\n this.eventBuffer = eventAggregator;\n this.retryQueueHandler = new RetryQueueHandler();\n this.httpClient = new OptimizedHttpClient();\n this.fallBackUrl = \"\";\n this.retryCount = 0;\n\n // Set up smart harvest callback\n if (this.eventBuffer instanceof NrVideoEventAggregator) {\n this.eventBuffer.setSmartHarvestCallback((type, threshold) =>\n this.triggerSmartHarvest(type, threshold)\n );\n }\n\n // Scheduler state\n this.isStarted = false;\n this.currentTimerId = null;\n this.harvestCycle = Constants.INTERVAL;\n this.isHarvesting = false;\n\n // Page lifecycle handling\n this.setupPageLifecycleHandlers();\n }\n\n /**\n * Starts the harvest scheduler.\n */\n startScheduler() {\n if (this.isStarted) {\n Log.warn(\"Harvest scheduler is already started\");\n return;\n }\n\n this.isStarted = true;\n\n Log.notice(\"Starting harvest scheduler\", {\n harvestCycle: this.harvestCycle,\n eventBufferSize: this.eventBuffer ? this.eventBuffer.size() : 0,\n });\n\n this.scheduleNextHarvest();\n }\n\n /**\n * Stops the harvest scheduler.\n */\n stopScheduler() {\n if (!this.isStarted) {\n return;\n }\n\n this.isStarted = false;\n\n if (this.currentTimerId) {\n clearTimeout(this.currentTimerId);\n this.currentTimerId = null;\n }\n\n Log.notice(\"Harvest scheduler stopped\");\n }\n\n /**\n * Triggers a smart harvest when buffer reaches threshold capacity.\n * @param {string} type - Type of harvest trigger ('smart' or 'overflow')\n * @param {number} threshold - Threshold percentage that triggered the harvest (60 or 90)\n */\n async triggerSmartHarvest(type, threshold) {\n Log.notice(`${type} harvest triggered at ${threshold}% threshold`, {\n type,\n threshold,\n });\n\n // If buffer is empty, abort harvest\n if (!this.eventBuffer || this.eventBuffer.isEmpty()) return;\n\n // Clear existing timer to prevent redundant harvests\n if (this.currentTimerId) {\n clearTimeout(this.currentTimerId);\n this.currentTimerId = null;\n }\n\n try {\n await this.triggerHarvest({});\n } catch (error) {\n Log.error(`${type} harvest failed:`, error.message);\n } finally {\n // Schedule next harvest after smart harvest completes\n if (this.isStarted) {\n this.scheduleNextHarvest();\n }\n }\n }\n\n /**\n * Schedules the next harvest based on current conditions.\n * @private\n */\n scheduleNextHarvest() {\n if (!this.isStarted) return;\n\n const interval = this.harvestCycle;\n this.currentTimerId = setTimeout(() => this.onHarvestInterval(), interval);\n }\n\n /**\n * Handles the harvest interval timer.\n * @private\n */\n async onHarvestInterval() {\n try {\n // Check if there's any data to harvest (buffer or retry queue) before starting the harvest process\n const hasBufferData = this.eventBuffer && !this.eventBuffer.isEmpty();\n const hasRetryData =\n this.retryQueueHandler && this.retryQueueHandler.getQueueSize() > 0;\n\n if (!hasBufferData && !hasRetryData) return;\n await this.triggerHarvest({});\n } catch (error) {\n Log.error(\"Error during scheduled harvest:\", error.message);\n } finally {\n this.scheduleNextHarvest();\n }\n }\n\n /**\n * Triggers a harvest cycle with comprehensive error handling and monitoring.\n * @param {object} options - Harvest options\n * @param {boolean} options.isFinalHarvest - Whether this is a final harvest on page unload\n * @param {boolean} options.force - Force harvest even if buffer is empty\n * @returns {Promise<object>} Harvest result\n */\n async triggerHarvest(options = {}) {\n if (this.isHarvesting) {\n return { success: false, reason: \"harvest_in_progress\" };\n }\n\n this.isHarvesting = true;\n\n try {\n // Drain events from buffer\n let events = this.drainEvents(options);\n\n // For beacon harvests, trim events to fit beacon size if necessary\n if (options.isFinalHarvest) {\n const maxBeaconSize = Constants.MAX_BEACON_SIZE;\n const payloadSize = dataSize(events);\n\n if (payloadSize > maxBeaconSize) {\n // Trim events to fit beacon size (keep most recent events)\n events = this.trimEventsToFit(events, maxBeaconSize);\n }\n }\n\n // Send single payload - buffer limits guarantee it fits API constraints\n const result = await this.sendChunk(events, options, true);\n\n return {\n success: result.success,\n totalChunks: 1,\n results: [result],\n };\n } catch (error) {\n Log.error(\"Harvest cycle failed:\", error.message);\n this.handleHarvestFailure(error);\n\n return {\n success: false,\n error: error.message,\n consecutiveFailures: this.consecutiveFailures,\n };\n } finally {\n this.isHarvesting = false;\n }\n }\n\n /**\n * Trims events to fit within a specified size limit for beacon harvests.\n * Keeps the most recent events and discards older ones.\n * @param {Array} events - Events to trim\n * @param {number} maxSize - Maximum payload size in bytes\n * @returns {Array} Trimmed events that fit within size limit\n * @private\n */\n trimEventsToFit(events, maxSize) {\n if (events.length === 0) return events;\n\n // Start from the most recent events (end of array) and work backwards\n const trimmedEvents = [];\n let currentSize = 0;\n\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i];\n\n // Check if adding this event would exceed the limit\n const testPayloadSize = dataSize({ ins: [event, ...trimmedEvents] });\n\n if (testPayloadSize > maxSize) continue;\n\n // Add event to the beginning to maintain chronological order\n trimmedEvents.unshift(event);\n currentSize = testPayloadSize;\n }\n\n const discardedCount = events.length - trimmedEvents.length;\n if (discardedCount > 0) {\n const discardedEvents = events.slice(0, discardedCount);\n Log.warn(`Discarded ${discardedCount} events to fit beacon size limit`, {\n originalCount: events.length,\n trimmedCount: trimmedEvents.length,\n finalSize: currentSize,\n maxSize,\n });\n\n // send discarded events to retry queue\n if (this.retryQueueHandler) {\n this.retryQueueHandler.addFailedEvents(discardedEvents);\n }\n }\n\n return trimmedEvents;\n }\n\n /**\n * Drains events from the event buffer and optionally includes retry queue data.\n * Uses fresh-events-first approach with payload limits.\n * @param {object} options - Harvest options\n * @returns {Array} Drained events\n * @private\n */\n drainEvents() {\n // Always drain fresh events first (priority approach)\n const freshEvents = this.eventBuffer.drain();\n let events = [...freshEvents];\n let currentPayloadSize = dataSize(freshEvents);\n\n // Always check retry queue if it has data - no flags needed\n if (this.retryQueueHandler && this.retryQueueHandler.getQueueSize() > 0) {\n //const retryQueueSize = this.retryQueueHandler.getQueueSize();\n\n // Calculate available space for retry events\n const availableSpace = Constants.MAX_PAYLOAD_SIZE - currentPayloadSize;\n const availableEventCount =\n Constants.MAX_EVENTS_PER_BATCH - events.length;\n\n if (availableSpace > 0 && availableEventCount > 0) {\n const retryEvents = this.retryQueueHandler.getRetryEventsToFit(\n availableSpace,\n availableEventCount\n );\n\n if (retryEvents.length > 0) {\n events = [...retryEvents, ...events]; // Append retry events before fresh events for maintaining chronoligical order\n }\n }\n }\n return events;\n }\n\n /**\n * Sends a chunk of events using the optimized HTTP client.\n * @param {Array} chunk - Events to send\n * @param {object} options - Harvest options\n * @param {boolean} isLastChunk - Whether this is the last chunk\n * @returns {Promise<object>} Send result\n * @private\n */\n async sendChunk(chunk, options, isLastChunk) {\n const url = buildUrl(this.fallBackUrl); //\n const payload = { body: { ins: chunk } };\n const requestOptions = {\n url,\n payload,\n options: {\n ...options,\n isLastChunk,\n },\n };\n return new Promise((resolve) => {\n this.httpClient.send(requestOptions, (result) => {\n if (result.retry) {\n this.handleRequestFailure(chunk);\n } else {\n // Inline reset logic for successful request\n this.retryCount = 0;\n this.fallBackUrl = \"\";\n }\n resolve({\n success: !result.retry,\n status: result.status,\n error: result.error,\n chunk,\n eventCount: chunk.length,\n });\n });\n });\n }\n\n /**\n * Handles request failure and implements failover logic for US region.\n * @param {Array} chunk - Failed chunk to add to retry queue\n * @private\n */\n handleRequestFailure(chunk) {\n // Add failed events to retry queue\n this.retryQueueHandler.addFailedEvents(chunk);\n // Only apply failover logic for US region\n if (window.NRVIDEO?.info?.region !== \"US\") return;\n this.retryCount++;\n if (this.retryCount > 5) {\n // Reset to primary endpoint after too many failures\n this.retryCount = 0;\n this.fallBackUrl = \"\";\n } else if (this.retryCount >= 2) {\n // Switch to fallback after 2 consecutive failures\n this.fallBackUrl = Constants.COLLECTOR[\"US\"][1];\n }\n }\n\n /**\n * Handles harvest failure scenarios.\n * @param {Error} error - Harvest error\n * @private\n */\n handleHarvestFailure(error) {\n this.consecutiveFailures++;\n\n Log.warn(\"Harvest failure handled\", {\n error: error.message,\n consecutiveFailures: this.consecutiveFailures,\n });\n }\n\n /**\n * Updates the harvest interval and restarts the scheduler to apply the new interval.\n * @param {number} newInterval - The new harvest interval in milliseconds\n * @returns {boolean} - True if interval was updated successfully, false otherwise\n */\n\n updateHarvestInterval(newInterval) {\n if (typeof newInterval !== \"number\" && isNaN(newInterval)) {\n Log.warn(\"Invalid newInterval provided to updateHarvestInterval\");\n return;\n }\n\n if (newInterval < 1000 || newInterval > 300000) {\n Log.warn(\"newInterval out of bounds (1000-300000), ignoring\");\n return;\n }\n\n // Check if the interval has actually changed to avoid unnecessary actions\n if (this.harvestCycle === newInterval) {\n return;\n }\n\n // 1. Update the harvestCycle property with the new interval\n this.harvestCycle = newInterval;\n Log.notice(\"Updated harvestCycle:\", this.harvestCycle);\n\n // 2. Clear the existing timer\n if (this.currentTimerId) {\n clearTimeout(this.currentTimerId);\n this.currentTimerId = null;\n }\n\n // 3. Schedule a new timer with the updated interval\n if (this.isStarted) {\n this.scheduleNextHarvest();\n }\n\n return;\n }\n\n /**\n * Sets up page lifecycle event handlers.\n * @private\n */\n setupPageLifecycleHandlers() {\n let finalHarvestTriggered = false;\n\n const triggerFinalHarvest = () => {\n if (finalHarvestTriggered) return;\n finalHarvestTriggered = true;\n\n this.triggerHarvest({ isFinalHarvest: true, force: true });\n };\n\n // Handle page visibility changes\n document.addEventListener(\"visibilitychange\", () => {\n if (document.hidden) triggerFinalHarvest();\n });\n\n // Handle page unload\n window.addEventListener(\"pagehide\", () => {\n triggerFinalHarvest();\n });\n\n // Handle beforeunload as backup\n window.addEventListener(\"beforeunload\", () => {\n triggerFinalHarvest();\n });\n }\n}\n","import Log from \"./log\";\nimport { recordEvent } from \"./recordEvent\";\nimport { setVideoConfig } from \"./videoConfiguration\";\n\n/**\n * Static class that sums up core functionalities of the library.\n * @static\n */\nclass Core {\n /**\n * Add a tracker to the system. Trackers added will start reporting its events to the video analytics backend.\n *\n * @param {(Emitter|Tracker)} tracker Tracker instance to add.\n * @param {object} options Configuration options including video analytics settings.\n */\n static addTracker(tracker, options) {\n // Set video analytics configuration\n if (options?.info) {\n setVideoConfig(options.info);\n }\n \n if (tracker.on && tracker.emit) {\n trackers.push(tracker);\n tracker.on(\"*\", eventHandler);\n if (typeof tracker.trackerInit == \"function\") {\n tracker.trackerInit();\n }\n } else {\n Log.error(\"Tried to load a non-tracker.\", tracker);\n }\n }\n\n /**\n * Disposes and remove given tracker. Removes its listeners.\n *\n * @param {Tracker} tracker Tracker to remove.\n */\n static removeTracker(tracker) {\n tracker.off(\"*\", eventHandler);\n tracker.dispose();\n let index = trackers.indexOf(tracker);\n if (index !== -1) trackers.splice(index, 1);\n }\n\n /**\n * Returns the array of trackers.\n *\n * @returns {Tracker[]} Array of trackers.\n */\n static getTrackers() {\n return trackers;\n }\n\n /**\n * Enhanced send method with performance timing.\n * @param {string} eventType - Type of event\n * @param {string} actionName - Action name\n * @param {object} data - Event data\n */\n static send(eventType, actionName, data) {\n const enrichedData = {\n actionName,\n ...data,\n \n };\n \n return recordEvent(eventType, enrichedData);\n }\n\n /**\n * Sends an error event.\n * This may be used for external errors launched by the app, the network or\n * any external factor. Note that errors within the player are normally reported with\n * tracker.sendError, so this method should not be used to report those.\n *\n * @param {object} att attributes to be sent along the error.\n */\n static sendError(att) {\n return recordEvent(\"VideoErrorAction\", {\n actionName: \"ERROR\",\n ...att\n });\n }\n\n \n \n\n /**\n * Forces an immediate harvest of all pending events.\n * @returns {Promise<object>} Harvest result\n */\n static async forceHarvest() {\n try {\n const { videoAnalyticsHarvester } = require(\"./agent\"); // lazy loading for dynamic import\n return await videoAnalyticsHarvester.forceHarvest();\n } catch (error) {\n Log.error(\"Failed to force harvest:\", error.message);\n return { success: false, error: error.message };\n }\n }\n}\n\nlet trackers = [];\nlet isErrorShown = false;\n\n/**\n * Enhanced event handler with error handling and performance monitoring.\n *\n * @private\n * @param {Event} e Event\n */\nfunction eventHandler(e) {\n try {\n let data = cleanData(e.data);\n \n if (Log.level <= Log.Levels.DEBUG) {\n Log.notice(\"Sent\", e.type, data);\n } else {\n Log.notice(\"Sent\", e.type);\n }\n\n // Send event without priority discrimination\n Core.send(e.eventType, e.type, data);\n\n } catch (error) {\n Log.error(\"Error in event handler:\", error.message);\n }\n}\n\n/**\n * Cleans given object, removing all items with value === null.\n * @private\n * @param {Object} data Data to clean\n * @returns {Object} Cleaned object\n */\nfunction cleanData(data) {\n let ret = {};\n for (let i in data) {\n if (data[i] !== null && typeof data[i] !== \"undefined\") ret[i] = data[i];\n }\n return ret;\n}\n\nexport default Core;\n","import Log from \"./log\";\nimport { dataSize } from \"./utils\";\nimport Constants from \"./constants\";\n\nconst { MAX_PAYLOAD_SIZE, MAX_EVENTS_PER_BATCH } = Constants;\n\n/**\n * Retry Queue Handler for managing failed events with retry logic,\n * backoff strategies, and persistent storage capabilities.\n */\nexport class RetryQueueHandler {\n constructor() {\n this.retryQueue = [];\n this.maxQueueSize = MAX_EVENTS_PER_BATCH; // Max 1000 events\n this.maxQueueSizeBytes = MAX_PAYLOAD_SIZE; // Max 1MB\n }\n\n /**\n * Adds failed events to the retry queue for retry processing.\n * @param {Array|object} events - Failed event(s) to add to retry queue\n */\n addFailedEvents(events) {\n try {\n const eventsArray = Array.isArray(events) ? events : [events];\n\n Log.notice(`Adding ${eventsArray.length} failed events to retry queue`, {\n queueSizeBefore: this.retryQueue.length,\n });\n\n for (const event of eventsArray) {\n // Check queue size and make room if necessary\n if (this.retryQueue.length >= this.maxQueueSize) {\n this.evictOldestEvent();\n }\n\n // Check queue memory size and make room if necessary\n const eventSize = dataSize(event);\n while (dataSize(this.retryQueue) + eventSize > this.maxQueueSizeBytes) {\n this.evictOldestEvent();\n }\n\n // Store event directly - no wrapper needed\n this.retryQueue.push({ ...event });\n }\n } catch (err) {\n Log.error(\"Failed to add events to retry queue:\", err.message);\n }\n }\n\n /**\n * Discards an event that cannot be retried.\n * @param {object} event - Event to discard\n * @param {string} reason - Reason for discarding\n * @private\n */\n discardEvent(event, reason) {\n Log.warn(`Discarded event`, {\n reason,\n eventType: event.eventType,\n });\n }\n\n /**\n * Evicts the oldest event from the queue to make room.\n * @private\n */\n evictOldestEvent() {\n if (this.retryQueue.length > 0) {\n const oldest = this.retryQueue.shift();\n this.discardEvent(oldest, \"Queue full - evicted oldest\");\n }\n }\n\n /**\n * For unified harvesting - get retry events that fit within payload limits\n * Removes the selected events from the retry queue since they're being retried\n * @param {number} availableSpace - Available payload space in bytes\n * @param {number} availableEventCount - Available event count\n * @returns {Array} Array of events that fit within limits\n */\n getRetryEventsToFit(availableSpace, availableEventCount) {\n const retryEvents = [];\n let usedSpace = 0;\n let eventCount = 0;\n\n // Process retry queue in chronological order (oldest first) by iterating backwards\n // This allows us to remove elements immediately without index shifting issues\n for (let i = this.retryQueue.length - 1; i >= 0; i--) {\n const event = this.retryQueue[i]; // 1000\n\n if (eventCount >= availableEventCount) break;\n\n const eventSize = dataSize(event);\n if (usedSpace + eventSize > availableSpace) break;\n\n // Add to beginning of retryEvents to maintain chronological order (oldest first)\n retryEvents.unshift(event);\n usedSpace += eventSize;\n eventCount++;\n\n // Remove immediately - safe because we're iterating backwards\n this.retryQueue.splice(i, 1);\n }\n\n return retryEvents;\n }\n\n /**\n * Gets the current retry queue size.\n * @returns {number} Queue size\n */\n getQueueSize() {\n return this.retryQueue.length;\n }\n\n /**\n * Clears the retry queue.\n */\n clear() {\n this.retryQueue = [];\n }\n}\n\nexport default RetryQueueHandler;\n","import Log from \"./log\";\nimport Constants from \"./constants\";\nimport { dataSize } from \"./utils\";\n\nconst { MAX_PAYLOAD_SIZE, MAX_EVENTS_PER_BATCH } = Constants;\n\n/**\n * Enhanced event buffer that manages video events with unified priority handling\n * and automatic size management. All events are treated with equal priority\n * unless explicitly specified otherwise.\n */\nexport class NrVideoEventAggregator {\n constructor() {\n // Simplified to single priority queue for equal treatment\n\n this.buffer = [];\n this.maxPayloadSize = MAX_PAYLOAD_SIZE;\n this.maxEventsPerBatch = MAX_EVENTS_PER_BATCH;\n this.currentPayloadSize = 0;\n this.totalEvents = 0;\n\n // Dual threshold system - whichever is reached first triggers harvest\n // Payload size thresholds\n this.smartHarvestPayloadThreshold = Math.floor(this.maxPayloadSize * 0.6); // 60% of 1MB = 600KB\n this.overflowPayloadThreshold = Math.floor(this.maxPayloadSize * 0.9); // 90% of 1MB = 900KB\n\n // Event count thresholds\n this.smartHarvestEventThreshold = Math.floor(this.maxEventsPerBatch * 0.6); // 60% of 1000 = 600 events\n this.overflowEventThreshold = Math.floor(this.maxEventsPerBatch * 0.9); // 90% of 1000 = 900 events\n\n // Callback for triggering harvest\n this.onSmartHarvestTrigger = null;\n }\n\n /**\n * Adds an event to the unified buffer.\n * All events are treated equally in FIFO order.\n * @param {object} eventObject - The event to add\n */\n add(eventObject) {\n try {\n // Calculate event payload size\n const eventSize = dataSize(eventObject);\n\n // Check if we need to make room based on EITHER payload size OR event count limits\n const wouldExceedPayload =\n this.currentPayloadSize + eventSize >= this.maxPayloadSize;\n const wouldExceedEventCount =\n this.totalEvents + 1 >= this.maxEventsPerBatch;\n\n if (wouldExceedPayload || wouldExceedEventCount) {\n this.makeRoom(eventSize);\n }\n\n // Add to unified buffer\n this.buffer.push(eventObject);\n this.totalEvents++;\n this.currentPayloadSize += eventSize;\n\n // Check if smart harvest should be triggered\n this.checkSmartHarvestTrigger();\n\n return true;\n } catch (error) {\n Log.error(\"Failed to add event to buffer:\", error.message);\n return false;\n }\n }\n\n /**\n * Checks if smart harvest should be triggered based on dual threshold system.\n * Triggers when EITHER condition is met first:\n * - 60% of payload size (600KB) OR 60% of event count (600 events)\n * - 90% of payload size (900KB) OR 90% of event count (900 events)\n * @private\n */\n checkSmartHarvestTrigger() {\n const payloadPercentage = this.currentPayloadSize / this.maxPayloadSize;\n const eventPercentage = this.totalEvents / this.maxEventsPerBatch;\n\n // Check 90% emergency thresholds first (either payload OR event count)\n const isPayloadOverflowReached =\n this.currentPayloadSize >= this.overflowPayloadThreshold;\n const isEventOverflowReached =\n this.totalEvents >= this.overflowEventThreshold;\n\n if (isPayloadOverflowReached || isEventOverflowReached) {\n const triggerReason = isPayloadOverflowReached\n ? `payload ${this.currentPayloadSize}/${\n this.maxPayloadSize\n } bytes (${Math.round(payloadPercentage * 100)}%)`\n : `events ${this.totalEvents}/${this.maxEventsPerBatch} (${Math.round(\n eventPercentage * 100\n )}%)`;\n\n Log.warn(\n `OVERFLOW PREVENTION: ${triggerReason} - Emergency harvest triggered`\n );\n\n if (\n this.onSmartHarvestTrigger &&\n typeof this.onSmartHarvestTrigger === \"function\"\n ) {\n // Trigger immediate emergency harvest\n this.onSmartHarvestTrigger(\"overflow\", 90);\n }\n }\n\n // Check 60% smart harvest thresholds (either payload OR event count)\n else {\n const isPayloadSmartReached =\n this.currentPayloadSize >= this.smartHarvestPayloadThreshold;\n const isEventSmartReached =\n this.totalEvents >= this.smartHarvestEventThreshold;\n\n if (isPayloadSmartReached || isEventSmartReached) {\n if (\n this.onSmartHarvestTrigger &&\n typeof this.onSmartHarvestTrigger === \"function\"\n ) {\n // Trigger proactive harvest\n this.onSmartHarvestTrigger(\"smart\", 60);\n }\n }\n }\n }\n\n /**\n * Sets the callback function for smart harvest triggers.\n * @param {Function} callback - Function to call when smart harvest is triggered\n */\n setSmartHarvestCallback(callback) {\n this.onSmartHarvestTrigger = callback;\n }\n\n /**\n * Drains all events from the buffer in FIFO order (first in, first out).\n * No limits needed since buffer already manages size via makeRoom() and smart harvest triggers.\n * @returns {Array} Array of events in order they were added\n */\n drain() {\n try {\n // Drain ALL events - buffer size is already managed by makeRoom() and smart harvest\n const events = this.buffer.splice(0);\n\n // Reset counters since buffer is now empty\n this.totalEvents = 0;\n this.currentPayloadSize = 0;\n\n return events;\n } catch (error) {\n Log.error(\"Failed to drain events from buffer:\", error.message);\n return [];\n }\n }\n\n /**\n * Checks if the buffer is empty.\n * @returns {boolean} True if all buffers are empty\n */\n isEmpty() {\n return this.totalEvents === 0;\n }\n\n /**\n * Gets the total number of events across all buffers.\n * @returns {number} Total event count\n */\n size() {\n return this.totalEvents;\n }\n\n /**\n * Clears the entire buffer.\n */\n clear() {\n this.buffer = [];\n this.totalEvents = 0;\n }\n\n /**\n * Makes room in the buffer by removing the oldest event.\n * Uses FIFO approach - removes the first (oldest) event.\n * @private\n */\n makeRoom(newEventSize) {\n // Before the while loop in makeRoom()\n if (newEventSize > this.maxPayloadSize) {\n Log.error(\"Event dropped: Event size exceeds maximum payload size.\");\n return; // Exit the function to prevent infinite loop\n }\n\n // Keep a loop to evict events until we meet ALL conditions for the new event\n while (\n // Condition 1: Exceeding max event count\n this.totalEvents >= this.maxEventsPerBatch ||\n // Condition 2: Exceeding max payload size\n this.currentPayloadSize + newEventSize >= this.maxPayloadSize\n ) {\n if (this.buffer.length > 0) {\n const removed = this.buffer.shift(); // Remove the oldest event (FIFO)\n\n // Recalculate size and count after removal\n const removedSize = dataSize(removed);\n this.totalEvents--;\n this.currentPayloadSize -= removedSize;\n\n // Optional: Log a warning for a dropped event\n Log.warn(\"Event buffer full, oldest event removed.\");\n } else {\n // Buffer is somehow empty, but conditions were met. Break the loop.\n break;\n }\n }\n }\n}\n\nexport default NrVideoEventAggregator;\n","import { videoAnalyticsHarvester } from \"./agent.js\";\nimport Constants from \"./constants.js\";\nimport Log from \"./log.js\";\n\n/**\n * Enhanced record event function with validation, enrichment, and unified handling.\n * @param {string} eventType - Type of event to record\n * @param {object} attributes - Event attributes\n */\nexport function recordEvent(eventType, attributes = {}) {\n try {\n // Validate event type\n if (!Constants.VALID_EVENT_TYPES.includes(eventType)) {\n Log.warn(\"Invalid event type provided to recordEvent\", { eventType });\n return false;\n }\n\n // Get app configuration\n\n if (!window?.NRVIDEO?.info) return;\n\n const { appName, applicationID } = window.NRVIDEO.info;\n\n const eventObject = {\n ...attributes,\n eventType,\n ...(applicationID ? {} : { appName }), // Only include appName when no applicationID\n timestamp: Date.now(),\n timeSinceLoad: window.performance\n ? window.performance.now() / 1000\n : null,\n };\n\n // Send to video analytics harvester\n const success = videoAnalyticsHarvester.addEvent(eventObject);\n return success;\n } catch (error) {\n Log.error(\"Failed to record event:\", error.message);\n return false;\n }\n}\n","/**\n * This class calculates time lapses between two points on time.\n */\nclass Chrono {\n /**\n * Constructor\n */\n constructor() {\n this.reset();\n }\n\n /** Reset chrono values. */\n reset() {\n /** Start time */\n this.startTime = 0;\n\n /** Stop time */\n this.stopTime = 0;\n\n /**\n * If you set an offset in a chrono, its value will be added getDeltaTime and stop.\n *\n * @example\n * let chrono = new Chrono()\n * chrono.offset = 500\n * chrono.start()\n * process.sleep(500)\n * chrono.stop() // Will return 1000\n *\n * @type {number}\n */\n this.offset = 0;\n }\n\n /**\n * Returns the time between start() and the last stop() in ms. Returns null if start wasn't\n * called.\n * @return {(number|null)} Time lapse in ms.\n */\n getDeltaTime() {\n if (this.startTime) {\n return this.offset + (new Date().getTime() - this.startTime);\n } else {\n return null;\n }\n }\n\n /**\n * Starts the chrono.\n */\n start() {\n this.startTime = new Date().getTime();\n this.stopTime = 0;\n }\n\n /**\n * Stops the timer and returns delta time.\n * @return {(number|null)} Returns the delta time\n */\n stop() {\n this.stopTime = new Date().getTime();\n return this.getDeltaTime();\n }\n\n /**\n * Creates a copy of the chrono.\n * @returns {Chrono} Cloned chrono\n */\n clone() {\n var chrono = new Chrono();\n chrono.startTime = this.startTime;\n chrono.stopTime = this.stopTime;\n chrono.offset = this.offset;\n return chrono;\n }\n}\n\nexport default Chrono;\n","import { HarvestScheduler } from \"./harvestScheduler.js\";\nimport { NrVideoEventAggregator } from \"./eventAggregator.js\";\nimport Log from \"./log.js\";\n\n/**\n * Enhanced video analytics agent with HarvestScheduler only.\n */\nclass VideoAnalyticsAgent {\n constructor() {\n this.isInitialized = false;\n this.harvestScheduler = null;\n this.eventBuffer = null;\n }\n\n /**\n * Initializes the video analytics agent with enhanced HarvestScheduler.\n */\n initialize() {\n if (this.isInitialized) {\n Log.warn(\"Video analytics agent already initialized\");\n return;\n }\n\n try {\n this.eventBuffer = new NrVideoEventAggregator();\n this.harvestScheduler = new HarvestScheduler(this.eventBuffer);\n\n // Start the enhanced harvest scheduler\n this.harvestScheduler.startScheduler();\n\n this.isInitialized = true;\n Log.notice(\"Video analytics agent initialized successfully\");\n } catch (error) {\n Log.error(\"Failed to initialize video analytics agent:\", error.message);\n }\n }\n\n /**\n * Adds an event to the harvesting system.\n * @param {object} eventObject - Event to add\n * @returns {boolean} True if event was added successfully\n */\n addEvent(eventObject) {\n if (!this.isInitialized) {\n Log.warn(\"Video analytics agent not initialized, initializing now\");\n this.initialize();\n }\n\n try {\n return this.eventBuffer.add(eventObject);\n } catch (error) {\n Log.error(\"Failed to add event to harvesting system:\", error.message);\n return false;\n }\n }\n\n /**\n * Sets the harvest interval for the scheduler.\n * @param {number} interval - The harvest interval in milliseconds.\n */\n\n setHarvestInterval(interval) {\n if (!this.isInitialized) {\n this.initialize();\n }\n\n this.harvestScheduler.updateHarvestInterval(interval);\n }\n}\n\n// Create singleton instance\nconst videoAnalyticsAgent = new VideoAnalyticsAgent();\n\n// Enhanced video analytics harvester\nexport const videoAnalyticsHarvester = videoAnalyticsAgent;\n","/**\n * This base class implements a basic behavior of listeners and events. Extend this object to have\n * this feature built-in inside your classes.\n *\n * @class Emitter\n */\nclass Emitter {\n /**\n * Sets a listener to a given event. Use {@link emit} to trigger those events.\n * Pass '*' to listen ALL events.\n *\n * @param {string} event Name of the event.\n * @param {function} callback Callback of the event. Receives event and data.\n * @return this\n */\n on(event, callback) {\n this._listeners = this._listeners || {};\n if (typeof callback === \"function\") {\n this._listeners[event] = this._listeners[event] || [];\n this._listeners[event].push(callback);\n return this;\n }\n }\n\n /**\n * Removes given callback from the listeners of this object.\n *\n * @param {string} event Name of the event.\n * @param {function} callback Callback of the event.\n * @return this\n */\n off(event, callback) {\n this._listeners = this._listeners || {};\n\n if (this._listeners[event]) {\n var index = this._listeners[event].indexOf(callback);\n if (index !== -1) {\n this._listeners[event].splice(index, 1);\n }\n }\n return this;\n }\n\n /**\n * Emits given event, triggering all the associated callbacks.\n *\n * @param {string} event Name of the event.\n * @param {object} [data] Custom data to be sent to the callbacks.\n * @return this\n */\n emit(eventType, event, data) {\n this._listeners = this._listeners || {};\n data = data || {};\n\n if (Array.isArray(this._listeners[event])) {\n this._listeners[event].forEach((callback) => {\n callback.call(this, {\n eventType,\n type: event,\n data: data,\n target: this,\n });\n });\n }\n\n if (Array.isArray(this._listeners[\"*\"])) {\n this._listeners[\"*\"].forEach((callback) => {\n callback.call(this, {\n eventType,\n type: event,\n data: data,\n target: this,\n });\n });\n }\n\n return this;\n }\n}\n\nexport default Emitter;\n","import Log from \"./log\";\nimport Constants from \"./constants\";\n\nconst { COLLECTOR } = Constants;\n\n/**\n * Enhanced video analytics configuration system that extends the existing auth configuration.\n * Provides feature flags, retry policies, and advanced harvesting options.\n */\nclass VideoConfiguration {\n /**\n * Validates and sets the video analytics configuration.\n * @param {object} userConfig - User provided configuration\n * @returns {boolean} True if configuration is valid and set\n */\n\n setConfiguration(userInfo) {\n this.initializeGlobalConfig(userInfo);\n Log.notice(\"Video analytics configuration initialized successfully\");\n return true;\n }\n\n /**\n * Validates required configuration fields.\n * @param {object} config - Configuration to validate\n * @returns {boolean} True if valid\n */\n validateRequiredFields(info) {\n if (!info || typeof info !== \"object\") {\n Log.error(\"Configuration must be an object\");\n return false;\n }\n\n const { licenseKey, appName, region, applicationID, beacon } = info;\n\n if (!licenseKey) {\n Log.error(\"licenseKey is required\");\n return false;\n }\n\n if (applicationID) {\n if (!beacon) {\n Log.error(\"beacon is required when applicationID is provided\");\n return false;\n } else {\n const validBeacons = Object.values(COLLECTOR).flatMap((el) => el);\n if (!validBeacons.includes(beacon)) {\n Log.error(`Invalid beacon: ${beacon}`);\n return false;\n }\n }\n } else {\n if (!appName || !region) {\n Log.error(\n \"appName and region are required when applicationID is not provided\"\n );\n return false;\n }\n\n if (!COLLECTOR[region]) {\n Log.error(\n `Invalid region: ${region}. Valid regions are: ${Object.keys(\n COLLECTOR\n ).join(\", \")}`\n );\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Initializes the global NRVIDEO configuration object.\n */\n initializeGlobalConfig(userInfo) {\n if (!this.validateRequiredFields(userInfo)) return;\n\n let { licenseKey, appName, region, beacon, applicationID } = userInfo;\n\n if (region === \"US\") {\n beacon = Constants.COLLECTOR[\"US\"][0];\n } else {\n beacon = beacon || COLLECTOR[region];\n }\n\n window.NRVIDEO = {\n // Existing format for backward compatibility\n info: {\n ...(region ? { region } : {}), // Only include region if available\n beacon,\n licenseKey,\n applicationID,\n ...(applicationID ? {} : { appName }), // Only include appName when no applicationID\n },\n };\n }\n}\n\n// Create singleton instance\nconst videoConfiguration = new VideoConfiguration();\n\n/**\n * Sets the video analytics configuration.\n * @param {object} config - Configuration object\n * @returns {boolean} True if configuration was set successfully\n */\nexport function setVideoConfig(info) {\n return videoConfiguration.setConfiguration(info);\n}\n\nexport { videoConfiguration };\nexport default VideoConfiguration;\n","import Log from \"./log\";\nimport Tracker from \"./tracker\";\nimport TrackerState from \"./videotrackerstate\";\nimport pkg from \"../package.json\";\n\n/**\n * Base video tracker class provides extensible tracking over video elements. See {@link Tracker}.\n * Extend this class to create your own video tracker class. Override getter methods and\n * registerListeners/unregisterListeners to provide full integration with your video experience.\n *\n * @example\n * Tracker instances should be added to Core library to start sending data:\n * nrvideo.Core.addTracker(new Tracker())\n *\n * @extends Tracker\n */\nclass VideoTracker extends Tracker {\n /**\n * Constructor, receives player and options.\n * Lifecycle: constructor > {@link setOptions} > {@link setPlayer} > {@link registerListeners}.\n *\n * @param {Object} [player] Player to track. See {@link setPlayer}.\n * @param {Object} [options] Options for the tracker. See {@link setOptions}.\n */\n constructor(player, options) {\n super();\n\n /**\n * TrackerState instance. Stores the state of the view. Tracker will automatically update the\n * state of its instance, so there's no need to modify/interact with it manually.\n * @type TrackerState\n */\n this.state = new TrackerState();\n\n /**\n * Another Tracker instance to track ads.\n * @type Tracker\n */\n this.adsTracker = null;\n\n /**\n * Last bufferType value.\n * @private\n */\n this._lastBufferType = null;\n this._userId = null;\n\n options = options || {};\n this.setOptions(options);\n if (player) this.setPlayer(player, options.tag);\n\n Log.notice(\n \"Tracker \" +\n this.getTrackerName() +\n \" v\" +\n this.getTrackerVersion() +\n \" is ready.\"\n );\n }\n\n /* user can set the user Id */\n\n setUserId(userId) {\n this._userId = userId;\n }\n\n /**\n * Set options for the Tracker.\n *\n * @param {Object} [options] Options for the tracker.\n * @param {Boolean} [options.isAd] True if the tracker is tracking ads. See {@link setIsAd}.\n * @param {number} [options.heartbeat] Set time between heartbeats. See {@link heartbeat}.\n * @param {Object} [options.customData] Set custom data. See {@link customData}.\n * @param {Tracker} [options.parentTracker] Set parent tracker. See {@link parentTracker}.\n * @param {Tracker} [options.adsTracker] Set ads tracker. See {@link adsTracker}.\n * @param {Object} [options.tag] DOM element to track. See {@link setPlayer}.\n */\n setOptions(options) {\n if (options) {\n if (options.adsTracker) {\n this.setAdsTracker(options.adsTracker);\n }\n if (typeof options.isAd === \"boolean\") {\n this.setIsAd(options.isAd);\n }\n Tracker.prototype.setOptions.apply(this, arguments);\n }\n }\n\n /**\n * Set a player and/or a tag. If there was one already defined, it will call dispose() first.\n * Will call this.registerListeners() afterwards.\n *\n * @param {Object|string} player New player to save as this.player. If a string is passed,\n * document.getElementById will be called.\n * @param {DOMObject|string} [tag] Optional DOMElement to save as this.tag. If a string is passed,\n * document.getElementById will be called.\n */\n\n setPlayer(player, tag) {\n if (this.player || this.tag) this.dispose();\n\n if (typeof document !== \"undefined\" && document.getElementById) {\n if (typeof player === \"string\") player = document.getElementById(player);\n if (typeof tag === \"string\") tag = document.getElementById(tag);\n }\n\n tag = tag || player; // if no tag is passed, use player as both.\n\n this.player = player;\n this.tag = tag;\n this.registerListeners();\n }\n\n /** Returns true if the tracker is currently on ads. */\n isAd() {\n return this.state.isAd();\n }\n\n /** Sets if the tracker is currenlty tracking ads */\n setIsAd(isAd) {\n this.state.setIsAd(isAd);\n }\n\n /**\n * Use this function to set up a child ad tracker. You will be able to access it using\n * this.adsTracker.\n *\n * @param {Tracker} tracker Ad tracker to add\n */\n setAdsTracker(tracker) {\n this.disposeAdsTracker(); // dispose current one\n if (tracker) {\n this.adsTracker = tracker;\n this.adsTracker.setIsAd(true);\n this.adsTracker.parentTracker = this;\n this.adsTracker.on(\"*\", funnelAdEvents.bind(this));\n }\n }\n\n /**\n * Dispose current adsTracker.\n */\n disposeAdsTracker() {\n if (this.adsTracker) {\n this.adsTracker.off(\"*\", funnelAdEvents);\n this.adsTracker.dispose();\n }\n }\n\n /**\n * Prepares tracker to dispose. Calls unregisterListener and drops references to player and tag.\n */\n dispose() {\n this.stopHeartbeat();\n this.disposeAdsTracker();\n this.unregisterListeners();\n this.player = null;\n this.tag = null;\n }\n\n /**\n * Override this method to register listeners to player/tag.\n * @example\n * class SpecificTracker extends Tracker {\n * registerListeners() {\n * this.player.on('play', () => this.playHandler)\n * }\n *\n * playHandler() {\n * this.send(VideoTracker.Events.REQUESTED)\n * }\n * }\n */\n registerListeners() {}\n\n /**\n * Override this method to unregister listeners to player/tag created in registerListeners\n * @example\n * class SpecificTracker extends Tracker {\n * registerListeners() {\n * this.player.on('play', () => this.playHandler)\n * }\n *\n * unregisterListeners() {\n * this.player.off('play', () => this.playHandler)\n * }\n *\n * playHandler() {\n * this.send(VideoTracker.Events.REQUESTED)\n * }\n * }\n */\n unregisterListeners() {}\n\n /**\n * Trackers will generate unique id's for every new video iteration. If you have your own unique\n * view value, you can override this method to return it.\n * If the tracker has a parentTracker defined, parent viewId will be used.\n */\n getViewId() {\n if (this.parentTracker) {\n return this.parentTracker.getViewId();\n } else {\n return this.state.getViewId();\n }\n }\n\n /**\n * Trackers will generate unique id's for every new video session. If you have your own unique\n * view value, you can override this method to return it.\n * If the tracker has a parentTracker defined, parent viewId will be used.\n */\n getViewSession() {\n if (this.parentTracker) {\n return this.parentTracker.getViewSession();\n } else {\n return this.state.getViewSession();\n }\n }\n\n /** Override to return the Id of the video. */\n getVideoId() {\n return null;\n }\n\n /** Override to return Title of the video. */\n getTitle() {\n return null;\n }\n\n /** Override to return True if the video is live. */\n isLive() {\n return null;\n }\n\n /** Override to return Bitrate (in bits) of the video. */\n getBitrate() {\n return null;\n }\n\n /** Calculates consumed bitrate using webkitVideoDecodedByteCount. */\n getWebkitBitrate() {\n if (this.tag && this.tag.webkitVideoDecodedByteCount) {\n let bitrate;\n if (this._lastWebkitBitrate) {\n bitrate = this.tag.webkitVideoDecodedByteCount;\n let delta = bitrate - this._lastWebkitBitrate;\n let seconds = this.getHeartbeat() / 1000;\n bitrate = Math.round((delta / seconds) * 8);\n }\n this._lastWebkitBitrate = this.tag.webkitVideoDecodedByteCount;\n return bitrate || null;\n }\n }\n\n /** Override to return Name of the rendition (ie: 1080p). */\n getRenditionName() {\n return null;\n }\n\n /** Override to return Target Bitrate of the rendition. */\n getRenditionBitrate() {\n return null;\n }\n\n /**\n * This method will return 'up', 'down' or null depending on if the bitrate of the rendition\n * have changed from the last time it was called.\n *\n * @param {boolean} [saveNewRendition=false] If true, current rendition will be stored to be used\n * the next time this method is called. This allows you to call this.getRenditionShift() without\n * saving the current rendition and thus preventing interferences with RENDITION_CHANGE events.\n */\n getRenditionShift(saveNewRendition) {\n let current = this.getRenditionBitrate();\n let last;\n if (this.isAd()) {\n last = this._lastAdRendition;\n if (saveNewRendition) this._lastAdRendition = current;\n } else {\n last = this._lastRendition;\n if (saveNewRendition) this._lastRendition = current;\n }\n\n if (!current || !last) {\n return null;\n } else {\n if (current > last) {\n return \"up\";\n } else if (current < last) {\n return \"down\";\n } else {\n return null;\n }\n }\n }\n\n /** Override to return renidtion actual Height (before re-scaling). */\n getRenditionHeight() {\n return this.tag ? this.tag.videoHeight : null;\n }\n\n /** Override to return rendition actual Width (before re-scaling). */\n getRenditionWidth() {\n return this.tag ? this.tag.videoWidth : null;\n }\n\n /** Override to return Duration of the video, in ms. */\n getDuration() {\n return this.tag ? this.tag.duration : null;\n }\n\n /** Override to return Playhead (currentTime) of the video, in ms. */\n getPlayhead() {\n return this.tag ? this.tag.currentTime : null;\n }\n\n /**\n * Override to return Language of the video. We recommend using locale notation, ie: en_US.\n * {@see https://gist.github.com/jacobbubu/1836273}\n */\n getLanguage() {\n return null;\n }\n\n /** Override to return URL of the resource being played. */\n getSrc() {\n return this.tag ? this.tag.currentSrc : null;\n }\n\n /** Override to return Playrate (speed) of the video. ie: 1.0, 0.5, 1.25... */\n getPlayrate() {\n return this.tag ? this.tag.playbackRate : null;\n }\n\n /** Override to return True if the video is currently muted. */\n isMuted() {\n return this.tag ? this.tag.muted : null;\n }\n\n /** Override to return True if the video is currently fullscreen. */\n isFullscreen() {\n return null;\n }\n\n /** Override to return the CDN serving the content. */\n getCdn() {\n return null;\n }\n\n /** Override to return the Name of the player. */\n getPlayerName() {\n return this.getTrackerName();\n }\n\n /** Override to return the Version of the player. */\n getPlayerVersion() {\n return pkg.version;\n }\n\n /** Override to return current FPS (Frames per second). */\n getFps() {\n return null;\n }\n\n /**\n * Override to return if the player was autoplayed. By default: this.tag.autoplay\n */\n isAutoplayed() {\n return this.tag ? this.tag.autoplay : null;\n }\n\n /**\n * Override to return the player preload attribute. By default: this.tag.preload\n */\n getPreload() {\n return this.tag ? this.tag.preload : null;\n }\n\n // Only for ads\n /**\n * Override to return Quartile of the ad. 0 before first, 1 after first quartile, 2 after\n * midpoint, 3 after third quartile, 4 when completed.\n */\n getAdQuartile() {\n return null;\n }\n\n /**\n * Override to return the position of the ad. Use {@link Constants.AdPositions} enum\n * to fill this data.\n */\n getAdPosition() {\n if (this.parentTracker) {\n return this.parentTracker.state.isStarted ? \"mid\" : \"pre\";\n } else {\n return null;\n }\n }\n\n /**\n * Override to return the ad partner. ie: ima, freewheel...\n */\n getAdPartner() {\n return null;\n }\n\n /**\n * Override to return the creative id of the ad.\n */\n getAdCreativeId() {\n return null;\n }\n\n /**\n * Override to return the instrumentation of the player.\n */\n\n getInstrumentationProvider() {\n return null;\n }\n\n getInstrumentationName() {\n return null;\n }\n\n getInstrumentationVersion() {\n return null;\n }\n\n /**\n * Do NOT override. This method fills all the appropiate attributes for tracked video.\n *\n * @param {object} [att] Collection of key value attributes\n * @return {object} Filled attributes\n * @final\n */\n getAttributes(att, type) {\n att = Tracker.prototype.getAttributes.apply(this, arguments);\n\n if (typeof att.isAd === \"undefined\") att.isAd = this.isAd();\n\n att.viewSession = this.getViewSession();\n att.viewId = this.getViewId();\n att.playerName = this.getPlayerName();\n att.playerVersion = this.getPlayerVersion();\n att[\"instrumentation.provider\"] = this.getInstrumentationProvider();\n att[\"instrumentation.name\"] = this.getInstrumentationName();\n att[\"instrumentation.version\"] = this.getInstrumentationVersion();\n att[\"enduser.id\"] = this._userId;\n att[\"src\"] = \"Browser\";\n\n if (type === \"customAction\") return att;\n\n try {\n att.pageUrl = window.location.href;\n } catch (err) {\n /* skip */\n }\n\n if (this.isAd()) {\n // Ads\n att.adId = this.getVideoId();\n att.adTitle = this.getTitle();\n att.adSrc = this.getSrc();\n att.adCdn = this.getCdn();\n att.adBitrate =\n this.getBitrate() ||\n this.getWebkitBitrate() ||\n this.getRenditionBitrate();\n att.adRenditionName = this.getRenditionName();\n att.adRenditionBitrate = this.getRenditionBitrate();\n att.adRenditionHeight = this.getRenditionHeight();\n att.adRenditionWidth = this.getRenditionWidth();\n att.adDuration = this.getDuration();\n att.adPlayhead = this.getPlayhead();\n att.adLanguage = this.getLanguage();\n att.adIsMuted = this.isMuted();\n att.adFps = this.getFps();\n // ad exclusives\n //att.adQuartile = this.getAdQuartile();\n att.adPosition = this.getAdPosition();\n att.adCreativeId = this.getAdCreativeId();\n att.adPartner = this.getAdPartner();\n } else {\n // no ads\n att.contentId = this.getVideoId();\n att.contentTitle = this.getTitle();\n att.contentSrc = this.getSrc();\n att.contentCdn = this.getCdn();\n att.contentPlayhead = this.getPlayhead();\n\n att.contentIsLive = this.isLive();\n att.contentBitrate =\n this.getBitrate() ||\n this.getWebkitBitrate() ||\n this.getRenditionBitrate();\n att.contentRenditionName = this.getRenditionName();\n att.contentRenditionBitrate = this.getRenditionBitrate();\n att.contentRenditionHeight = this.getRenditionHeight();\n att.contentRenditionWidth = this.getRenditionWidth();\n att.contentDuration = this.getDuration();\n\n att.contentLanguage = this.getLanguage();\n att.contentPlayrate = this.getPlayrate();\n att.contentIsFullscreen = this.isFullscreen();\n att.contentIsMuted = this.isMuted();\n att.contentIsAutoplayed = this.isAutoplayed();\n att.contentPreload = this.getPreload();\n att.contentFps = this.getFps();\n\n if (\n this.adsTracker != null &&\n this.adsTracker.state.totalAdPlaytime > 0\n ) {\n att.totalAdPlaytime = this.adsTracker.state.totalAdPlaytime;\n }\n }\n\n this.state.getStateAttributes(att);\n\n for (let key in this.customData) {\n att[key] = this.customData[key];\n }\n\n return att;\n }\n\n /**\n * Sends custom event and registers a timeSince attribute.\n * @param {Object} [actionName] Custom action name.\n * @param {Object} [timeSinceAttName] Custom timeSince attribute name.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendCustom(actionName, timeSinceAttName, att) {\n att = att || {};\n this.sendVideoCustomAction(actionName, att);\n this.state.setTimeSinceAttribute(timeSinceAttName);\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendPlayerReady(att) {\n if (this.state.goPlayerReady()) {\n att = att || {};\n this.sendVideoAction(VideoTracker.Events.PLAYER_READY, att);\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners. Calls\n * {@link startHeartbeat}.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendRequest(att) {\n if (this.state.goRequest()) {\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_REQUEST;\n this.sendVideoAdAction(ev, att);\n } else {\n ev = VideoTracker.Events.CONTENT_REQUEST;\n this.sendVideoAction(ev, att);\n }\n\n // this.startHeartbeat();\n // this.state.goHeartbeat();\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendStart(att) {\n if (this.state.goStart()) {\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_START;\n if (this.parentTracker) this.parentTracker.state.isPlaying = false;\n this.sendVideoAdAction(ev, att);\n } else {\n ev = VideoTracker.Events.CONTENT_START;\n this.sendVideoAction(ev, att);\n }\n //this.send(ev, att);\n this.startHeartbeat();\n this.state.goHeartbeat();\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners. Calls\n * {@link stopHeartbeat}.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendEnd(att) {\n if (this.state.goEnd()) {\n att = att || {};\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_END;\n att.timeSinceAdRequested = this.state.timeSinceRequested.getDeltaTime();\n att.timeSinceAdStarted = this.state.timeSinceStarted.getDeltaTime();\n if (this.parentTracker) this.parentTracker.state.isPlaying = true;\n } else {\n ev = VideoTracker.Events.CONTENT_END;\n att.timeSinceRequested = this.state.timeSinceRequested.getDeltaTime();\n att.timeSinceStarted = this.state.timeSinceStarted.getDeltaTime();\n }\n this.stopHeartbeat();\n //this.send(ev, att);\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n\n if (this.parentTracker && this.isAd())\n this.parentTracker.state.goLastAd();\n this.state.goViewCountUp();\n this.state.totalPlaytime = 0;\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendPause(att) {\n if (this.state.goPause()) {\n let ev = this.isAd()\n ? VideoTracker.Events.AD_PAUSE\n : VideoTracker.Events.CONTENT_PAUSE;\n\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n\n //this.send(ev, att);\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendResume(att) {\n if (this.state.goResume()) {\n att = att || {};\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_RESUME;\n att.timeSinceAdPaused = this.state.timeSincePaused.getDeltaTime();\n } else {\n ev = VideoTracker.Events.CONTENT_RESUME;\n att.timeSincePaused = this.state.timeSincePaused.getDeltaTime();\n }\n //this.send(ev, att);\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendBufferStart(att) {\n if (this.state.goBufferStart()) {\n att = att || {};\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_BUFFER_START;\n } else {\n ev = VideoTracker.Events.CONTENT_BUFFER_START;\n }\n\n att = this.buildBufferAttributes(att);\n this._lastBufferType = att.bufferType;\n\n //this.send(ev, att);\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendBufferEnd(att) {\n if (this.state.goBufferEnd()) {\n att = att || {};\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_BUFFER_END;\n att.timeSinceAdBufferBegin =\n this.state.timeSinceBufferBegin.getDeltaTime();\n } else {\n ev = VideoTracker.Events.CONTENT_BUFFER_END;\n att.timeSinceBufferBegin =\n this.state.timeSinceBufferBegin.getDeltaTime();\n }\n\n att = this.buildBufferAttributes(att);\n // Set the bufferType attribute of the last BUFFER_START\n if (this._lastBufferType != null) {\n att.bufferType = this._lastBufferType;\n }\n\n // this.send(ev, att);\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n this.state.initialBufferingHappened = true;\n }\n }\n\n buildBufferAttributes(att) {\n if (att.timeSinceStarted == undefined || att.timeSinceStarted < 100) {\n att.isInitialBuffering = !this.state.initialBufferingHappened;\n } else {\n att.isInitialBuffering = false;\n }\n\n att.bufferType = this.state.calculateBufferType(att.isInitialBuffering);\n\n att.timeSinceResumed = this.state.timeSinceResumed.getDeltaTime();\n att.timeSinceSeekEnd = this.state.timeSinceSeekEnd.getDeltaTime();\n\n return att;\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendSeekStart(att) {\n if (this.state.goSeekStart()) {\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_SEEK_START;\n } else {\n ev = VideoTracker.Events.CONTENT_SEEK_START;\n }\n // this.send(ev, att);\n\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendSeekEnd(att) {\n if (this.state.goSeekEnd()) {\n att = att || {};\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_SEEK_END;\n att.timeSinceAdSeekBegin = this.state.timeSinceSeekBegin.getDeltaTime();\n } else {\n ev = VideoTracker.Events.CONTENT_SEEK_END;\n att.timeSinceSeekBegin = this.state.timeSinceSeekBegin.getDeltaTime();\n }\n // this.send(ev, att);\n\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n * @param {String} att.state Download requires a string to distinguish different states.\n */\n sendDownload(att) {\n att = att || {};\n if (!att.state) Log.warn(\"Called sendDownload without { state: xxxxx }.\");\n this.sendVideoAction(VideoTracker.Events.DOWNLOAD, att);\n this.state.goDownload();\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendError(att) {\n att = att || {};\n\n att.isAd = this.isAd();\n this.state.goError();\n let ev = this.isAd()\n ? VideoTracker.Events.AD_ERROR\n : VideoTracker.Events.CONTENT_ERROR;\n //this.send(ev, att);\n\n this.sendVideoErrorAction(ev, att);\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendRenditionChanged(att) {\n att = att || {};\n att.timeSinceLastRenditionChange =\n this.state.timeSinceLastRenditionChange.getDeltaTime();\n att.shift = this.getRenditionShift(true);\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_RENDITION_CHANGE;\n } else {\n ev = VideoTracker.Events.CONTENT_RENDITION_CHANGE;\n }\n //this.send(ev, att);\n\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n\n this.state.goRenditionChange();\n }\n\n /**\n * Sends associated event and changes view state. Heartbeat will automatically be sent every\n * 10 seconds. There's no need to call this manually.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n * @param {number} att.url Url of the clicked ad.\n *\n */\n sendHeartbeat(att) {\n if (this.state.isRequested) {\n let ev;\n\n let elapsedTime = this.getHeartbeat();\n this.state._hb = true;\n elapsedTime = this.adjustElapsedTimeForPause(elapsedTime);\n\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_HEARTBEAT;\n if (this.getPlayerName() === \"bitmovin-ads\") {\n this.sendVideoAdAction(ev, att);\n } else {\n this.sendVideoAdAction(ev, { elapsedTime, ...att });\n }\n } else {\n ev = VideoTracker.Events.CONTENT_HEARTBEAT;\n this.sendVideoAction(ev, { elapsedTime, ...att });\n }\n this.state.goHeartbeat();\n }\n }\n\n adjustElapsedTimeForPause(elapsedTime) {\n if (this.state._acc) {\n elapsedTime -= this.state._acc;\n this.state._acc = 0;\n }\n\n if (this.state.isPaused) {\n elapsedTime -= this.state.elapsedTime.getDeltaTime();\n if (elapsedTime < 10) elapsedTime = 0;\n this.state.elapsedTime.start();\n }\n\n if (this.state._bufferAcc) {\n elapsedTime -= this.state._bufferAcc;\n this.state._bufferAcc = 0;\n } else if (this.state.isBuffering) {\n elapsedTime -= this.state.bufferElapsedTime.getDeltaTime();\n if (elapsedTime < 5) {\n elapsedTime = 0;\n }\n this.state.bufferElapsedTime.start();\n }\n\n return Math.max(0, elapsedTime);\n }\n\n // Only ads\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendAdBreakStart(att) {\n if (this.isAd() && this.state.goAdBreakStart()) {\n this.state.totalAdPlaytime = 0;\n if (this.parentTracker) this.parentTracker.state.isPlaying = false;\n // this.send(VideoTracker.Events.AD_BREAK_START, att);\n this.sendVideoAdAction(VideoTracker.Events.AD_BREAK_START, att);\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendAdBreakEnd(att) {\n if (this.isAd() && this.state.goAdBreakEnd()) {\n att = att || {};\n att.timeSinceAdBreakBegin =\n this.state.timeSinceAdBreakStart.getDeltaTime();\n //this.send(VideoTracker.Events.AD_BREAK_END, att);\n this.sendVideoAdAction(VideoTracker.Events.AD_BREAK_END, att);\n // Just in case AD_END not arriving, because of an AD_ERROR\n if (this.parentTracker) this.parentTracker.state.isPlaying = true;\n this.stopHeartbeat();\n if (this.parentTracker && this.isAd())\n this.parentTracker.state.goLastAd();\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n * @param {number} att.quartile Number of the quartile.\n */\n sendAdQuartile(att) {\n if (this.isAd()) {\n att = att || {};\n if (!att.quartile)\n Log.warn(\"Called sendAdQuartile without { quartile: xxxxx }.\");\n att.timeSinceLastAdQuartile =\n this.state.timeSinceLastAdQuartile.getDeltaTime();\n //this.send(VideoTracker.Events.AD_QUARTILE, att);\n\n this.sendVideoAdAction(VideoTracker.Events.AD_QUARTILE, att);\n this.state.goAdQuartile();\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n * @param {number} att.url Url of the clicked ad.\n */\n sendAdClick(att) {\n if (this.isAd()) {\n att = att || {};\n if (!att.url) Log.warn(\"Called sendAdClick without { url: xxxxx }.\");\n //this.send(VideoTracker.Events.AD_CLICK, att);\n this.sendVideoAdAction(VideoTracker.Events.AD_CLICK, att);\n }\n }\n}\n\n/**\n * Enumeration of events fired by this class.\n *\n * @static\n * @memberof VideoTracker\n * @enum {String}\n */\nVideoTracker.Events = {\n // Player\n /** The player is ready to start sending events. */\n PLAYER_READY: \"PLAYER_READY\",\n /** Downloading data. */\n DOWNLOAD: \"DOWNLOAD\",\n /** An error happened */\n ERROR: \"ERROR\",\n\n // Video\n /** Content video has been requested. */\n CONTENT_REQUEST: \"CONTENT_REQUEST\",\n /** Content video started (first frame shown). */\n CONTENT_START: \"CONTENT_START\",\n /** Content video ended. */\n CONTENT_END: \"CONTENT_END\",\n /** Content video paused. */\n CONTENT_PAUSE: \"CONTENT_PAUSE\",\n /** Content video resumed. */\n CONTENT_RESUME: \"CONTENT_RESUME\",\n /** Content video seek started */\n CONTENT_SEEK_START: \"CONTENT_SEEK_START\",\n /** Content video seek ended. */\n CONTENT_SEEK_END: \"CONTENT_SEEK_END\",\n /** Content video beffering started */\n CONTENT_BUFFER_START: \"CONTENT_BUFFER_START\",\n /** Content video buffering ended */\n CONTENT_BUFFER_END: \"CONTENT_BUFFER_END\",\n /** Content video heartbeat, en event that happens once every 30 seconds while the video is playing. */\n CONTENT_HEARTBEAT: \"CONTENT_HEARTBEAT\",\n /** Content video stream qwuality changed. */\n CONTENT_RENDITION_CHANGE: \"CONTENT_RENDITION_CHANGE\",\n /** Content video error. */\n CONTENT_ERROR: \"CONTENT_ERROR\",\n\n // Ads only\n /** Ad video has been requested. */\n AD_REQUEST: \"AD_REQUEST\",\n /** Ad video started (first frame shown). */\n AD_START: \"AD_START\",\n /** Ad video ended. */\n AD_END: \"AD_END\",\n /** Ad video paused. */\n AD_PAUSE: \"AD_PAUSE\",\n /** Ad video resumed. */\n AD_RESUME: \"AD_RESUME\",\n /** Ad video seek started */\n AD_SEEK_START: \"AD_SEEK_START\",\n /** Ad video seek ended */\n AD_SEEK_END: \"AD_SEEK_END\",\n /** Ad video beffering started */\n AD_BUFFER_START: \"AD_BUFFER_START\",\n /** Ad video beffering ended */\n AD_BUFFER_END: \"AD_BUFFER_END\",\n /** Ad video heartbeat, en event that happens once every 30 seconds while the video is playing. */\n AD_HEARTBEAT: \"AD_HEARTBEAT\",\n /** Ad video stream qwuality changed. */\n AD_RENDITION_CHANGE: \"AD_RENDITION_CHANGE\",\n /** Ad video error. */\n AD_ERROR: \"AD_ERROR\",\n /** Ad break (a block of ads) started. */\n AD_BREAK_START: \"AD_BREAK_START\",\n /** Ad break ended. */\n AD_BREAK_END: \"AD_BREAK_END\",\n /** Ad quartile happened. */\n AD_QUARTILE: \"AD_QUARTILE\",\n /** Ad has been clicked. */\n AD_CLICK: \"AD_CLICK\",\n};\n\n// Private members\nfunction funnelAdEvents(e) {\n if (e.type === VideoTracker.Events.AD_ERROR) {\n this.sendVideoErrorAction(e.type, e.data);\n return;\n }\n this.sendVideoAdAction(e.type, e.data);\n}\n\nexport default VideoTracker;\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","import Core from \"./core\";\nimport Constants from \"./constants\";\nimport Chrono from \"./chrono\";\nimport Log from \"./log\";\nimport Emitter from \"./emitter\";\nimport Tracker from \"./tracker\";\nimport VideoTracker from \"./videotracker\";\nimport VideoTrackerState from \"./videotrackerstate\";\nimport { NrVideoEventAggregator } from \"./eventAggregator\";\nimport { RetryQueueHandler } from \"./retryQueueHandler\";\nimport { OptimizedHttpClient } from \"./optimizedHttpClient\";\nimport { HarvestScheduler } from \"./harvestScheduler\";\nimport { recordEvent } from \"./recordEvent\";\nimport { version } from \"../package.json\";\n\nconst nrvideo = {\n // Core components (existing)\n Constants,\n Chrono,\n Log,\n Emitter,\n Tracker,\n VideoTracker,\n VideoTrackerState,\n Core,\n version,\n\n // Enhanced video analytics components (new)\n \n NrVideoEventAggregator,\n RetryQueueHandler,\n OptimizedHttpClient,\n HarvestScheduler,\n\n\n\n // Enhanced event recording\n recordEvent,\n\n\n};\n\nexport default nrvideo;\n"],"names":["e","_utils","require","_log","__esModule","default","OptimizedHttpClient","send","requestOptions","callback","url","payload","options","Error","request","this","executeRequest","error","Log","message","retry","status","startTime","Date","now","requestBody","JSON","stringify","body","isFinalHarvest","navigator","sendBeacon","success","sendWithBeacon","result","handleRequestComplete","response","fetchWithTimeout","method","headers","keepalive","ok","statusText","shouldRetry","warn","timeout","controller","AbortController","timeoutId","setTimeout","abort","fetch","signal","clearTimeout","name","exports","Constants","AdPositions","PRE","MID","POST","COLLECTOR","US","EU","Staging","GOV","VALID_EVENT_TYPES","MAX_PAYLOAD_SIZE","MAX_BEACON_SIZE","MAX_EVENTS_PER_BATCH","INTERVAL","msg","_report","Levels","ERROR","WARNING","notice","slice","call","arguments","NOTICE","debug","DEBUG","debugCommonVideoEvents","o","extraEvents","report","level","type","playerEvents","shift","concat","i","length","window","on","addEventListener","addEventHandler","err","color","d","logMethod","prefix","includeTime","getDate","getMinutes","getSeconds","getMilliseconds","_getCurrentTime","_letters","_level2letter","SILENT","colorful","document","documentMode","_plainReport","console","undefined","cast","log","splice","apply","Array","m","ALL","location","search","exec","_loadLevelFromUrl","_package","_interopRequireDefault","_emitter","_chrono","_constants","_agent","Tracker","Emitter","constructor","super","customData","heartbeat","parentTracker","_trackerReadyChrono","Chrono","start","_actionTable","ACTION_TABLE","_actionAdTable","ACTION_AD_TABLE","setOptions","dispose","unregisterListeners","registerListeners","getHeartbeat","state","_isAd","startHeartbeat","_heartbeatInterval","setInterval","sendHeartbeat","bind","Math","max","stopHeartbeat","clearInterval","att","sendVideoAction","Events","HEARTBEAT","getAttributes","eventType","trackerName","getTrackerName","trackerVersion","getTrackerVersion","coreVersion","pkg","version","timeSinceTrackerReady","getDeltaTime","key","hidden","isBackgroundEvent","event","emit","sendVideoAdAction","sendVideoErrorAction","ev","isAd","sendVideoCustomAction","setHarvestInterval","interval","videoAnalyticsHarvester","reset","_createdAt","_hb","_acc","_bufferAcc","_viewSession","_viewCount","numberOfErrors","numberOfAds","numberOfVideos","totalPlaytime","totalAdPlaytime","isAdBreak","initialBufferingHappened","resetFlags","resetChronos","isPlayerReady","isRequested","isStarted","isPaused","isSeeking","isBuffering","isPlaying","timeSinceRequested","timeSinceStarted","timeSincePaused","timeSinceSeekBegin","timeSinceBufferBegin","timeSinceAdBreakStart","timeSinceLastDownload","timeSinceLastHeartbeat","timeSinceLastRenditionChange","timeSinceLastAdQuartile","timeSinceLastAd","timeSinceLastError","timeSinceLastAdError","timeSinceResumed","timeSinceSeekEnd","playtimeSinceLastEvent","customTimeSinceAttributes","elapsedTime","bufferElapsedTime","setIsAd","setTimeSinceAttribute","removeTimeSinceAttribute","getViewSession","time","getTime","random","toString","substring","getViewId","getStateAttributes","timeSinceAdRequested","timeSinceLastAdHeartbeat","timeSinceAdStarted","timeSinceAdPaused","timeSinceAdBufferBegin","timeSinceAdSeekBegin","timeSinceAdBreakBegin","value","Object","entries","calculateBufferType","isInitialBuffering","bufferType","goViewCountUp","goPlayerReady","goRequest","goStart","goEnd","stop","goPause","goResume","goBufferStart","goBufferEnd","goSeekStart","goSeekEnd","goAdBreakStart","goAdBreakEnd","goDownload","goHeartbeat","goRenditionChange","goAdQuartile","goError","isError","goLastAd","fallbackUrl","NRVIDEO","info","beacon","licenseKey","applicationID","href","stringifiedPayload","stream","Blob","compressionStream","CompressionStream","compressedStream","pipeThrough","Response","blob","data","ArrayBuffer","byteLength","size","FormData","val","getCircularReplacer","async","compressedData","Uint8Array","decompressionStream","DecompressionStream","decompressedStream","decompressedText","text","parse","seen","WeakSet","has","add","_eventAggregator","_retryQueueHandler","_optimizedHttpClient","eventAggregator","eventBuffer","retryQueueHandler","RetryQueueHandler","httpClient","fallBackUrl","retryCount","NrVideoEventAggregator","setSmartHarvestCallback","threshold","triggerSmartHarvest","currentTimerId","harvestCycle","isHarvesting","setupPageLifecycleHandlers","startScheduler","eventBufferSize","scheduleNextHarvest","stopScheduler","isEmpty","triggerHarvest","onHarvestInterval","hasBufferData","hasRetryData","getQueueSize","reason","events","drainEvents","maxBeaconSize","dataSize","trimEventsToFit","sendChunk","totalChunks","results","handleHarvestFailure","consecutiveFailures","maxSize","trimmedEvents","currentSize","testPayloadSize","ins","unshift","discardedCount","discardedEvents","originalCount","trimmedCount","finalSize","addFailedEvents","freshEvents","drain","currentPayloadSize","availableSpace","availableEventCount","retryEvents","getRetryEventsToFit","chunk","isLastChunk","buildUrl","Promise","resolve","handleRequestFailure","eventCount","region","updateHarvestInterval","newInterval","isNaN","finalHarvestTriggered","triggerFinalHarvest","force","_recordEvent","_videoConfiguration","Core","addTracker","tracker","setVideoConfig","trackers","push","eventHandler","trackerInit","removeTracker","off","index","indexOf","getTrackers","actionName","enrichedData","recordEvent","sendError","forceHarvest","ret","cleanData","retryQueue","maxQueueSize","maxQueueSizeBytes","eventsArray","isArray","queueSizeBefore","evictOldestEvent","eventSize","discardEvent","oldest","usedSpace","clear","buffer","maxPayloadSize","maxEventsPerBatch","totalEvents","smartHarvestPayloadThreshold","floor","overflowPayloadThreshold","smartHarvestEventThreshold","overflowEventThreshold","onSmartHarvestTrigger","eventObject","wouldExceedPayload","wouldExceedEventCount","makeRoom","checkSmartHarvestTrigger","payloadPercentage","eventPercentage","isPayloadOverflowReached","isEventOverflowReached","triggerReason","round","isPayloadSmartReached","isEventSmartReached","newEventSize","removed","removedSize","attributes","includes","appName","timestamp","timeSinceLoad","performance","addEvent","stopTime","offset","clone","chrono","_harvestScheduler","videoAnalyticsAgent","isInitialized","harvestScheduler","initialize","HarvestScheduler","_listeners","forEach","target","videoConfiguration","setConfiguration","VideoConfiguration","userInfo","initializeGlobalConfig","validateRequiredFields","values","flatMap","el","keys","join","_tracker","_videotrackerstate","VideoTracker","player","TrackerState","adsTracker","_lastBufferType","_userId","setPlayer","tag","setUserId","userId","setAdsTracker","prototype","getElementById","disposeAdsTracker","funnelAdEvents","getVideoId","getTitle","isLive","getBitrate","getWebkitBitrate","webkitVideoDecodedByteCount","bitrate","_lastWebkitBitrate","delta","seconds","getRenditionName","getRenditionBitrate","getRenditionShift","saveNewRendition","last","current","_lastAdRendition","_lastRendition","getRenditionHeight","videoHeight","getRenditionWidth","videoWidth","getDuration","duration","getPlayhead","currentTime","getLanguage","getSrc","currentSrc","getPlayrate","playbackRate","isMuted","muted","isFullscreen","getCdn","getPlayerName","getPlayerVersion","getFps","isAutoplayed","autoplay","getPreload","preload","getAdQuartile","getAdPosition","getAdPartner","getAdCreativeId","getInstrumentationProvider","getInstrumentationName","getInstrumentationVersion","viewSession","viewId","playerName","playerVersion","pageUrl","adId","adTitle","adSrc","adCdn","adBitrate","adRenditionName","adRenditionBitrate","adRenditionHeight","adRenditionWidth","adDuration","adPlayhead","adLanguage","adIsMuted","adFps","adPosition","adCreativeId","adPartner","contentId","contentTitle","contentSrc","contentCdn","contentPlayhead","contentIsLive","contentBitrate","contentRenditionName","contentRenditionBitrate","contentRenditionHeight","contentRenditionWidth","contentDuration","contentLanguage","contentPlayrate","contentIsFullscreen","contentIsMuted","contentIsAutoplayed","contentPreload","contentFps","sendCustom","timeSinceAttName","sendPlayerReady","PLAYER_READY","sendRequest","AD_REQUEST","CONTENT_REQUEST","sendStart","AD_START","CONTENT_START","sendEnd","AD_END","CONTENT_END","sendPause","AD_PAUSE","CONTENT_PAUSE","sendResume","AD_RESUME","CONTENT_RESUME","sendBufferStart","AD_BUFFER_START","CONTENT_BUFFER_START","buildBufferAttributes","sendBufferEnd","AD_BUFFER_END","CONTENT_BUFFER_END","sendSeekStart","AD_SEEK_START","CONTENT_SEEK_START","sendSeekEnd","AD_SEEK_END","CONTENT_SEEK_END","sendDownload","DOWNLOAD","AD_ERROR","CONTENT_ERROR","sendRenditionChanged","AD_RENDITION_CHANGE","CONTENT_RENDITION_CHANGE","adjustElapsedTimeForPause","AD_HEARTBEAT","CONTENT_HEARTBEAT","sendAdBreakStart","AD_BREAK_START","sendAdBreakEnd","AD_BREAK_END","sendAdQuartile","quartile","AD_QUARTILE","sendAdClick","AD_CLICK","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","module","__webpack_modules__","_core","_videotracker","nrvideo","VideoTrackerState"],"sourceRoot":""}
1
+ {"version":3,"file":"index.js","mappings":"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","sources":["webpack://@newrelic/video-core/./src/optimizedHttpClient.js","webpack://@newrelic/video-core/./src/constants.js","webpack://@newrelic/video-core/./src/log.js","webpack://@newrelic/video-core/./src/tracker.js","webpack://@newrelic/video-core/./src/videotrackerstate.js","webpack://@newrelic/video-core/./src/utils.js","webpack://@newrelic/video-core/./src/harvestScheduler.js","webpack://@newrelic/video-core/./src/core.js","webpack://@newrelic/video-core/./src/retryQueueHandler.js","webpack://@newrelic/video-core/./src/eventAggregator.js","webpack://@newrelic/video-core/./src/recordEvent.js","webpack://@newrelic/video-core/./src/chrono.js","webpack://@newrelic/video-core/./src/agent.js","webpack://@newrelic/video-core/./src/emitter.js","webpack://@newrelic/video-core/./src/videoConfiguration.js","webpack://@newrelic/video-core/./src/videotracker.js","webpack://@newrelic/video-core/webpack/bootstrap","webpack://@newrelic/video-core/./src/index.js"],"sourcesContent":["import { dataSize, shouldRetry } from \"./utils\";\nimport Log from \"./log\";\n\n/**\n * Optimized HTTP client for video analytics data transmission with\n * performance monitoring and efficient request handling.\n */\nexport class OptimizedHttpClient {\n /**\n * Sends data to the specified URL with performance monitoring.\n * @param {object} requestOptions - Request configuration\n * @param {string} requestOptions.url - Target URL\n * @param {object} requestOptions.payload - Request payload\n * @param {object} requestOptions.options - Additional options\n * @param {Function} callback - Callback function for handling response\n * @returns {Promise<void>}\n */\n async send(requestOptions, callback) {\n const { url, payload, options = {} } = requestOptions;\n\n try {\n // Validate input\n if (!url || !payload) {\n throw new Error(\"URL and payload are required\");\n }\n\n // Create request object\n const request = {\n url,\n payload,\n options,\n callback,\n };\n\n // Execute request immediately\n await this.executeRequest(request);\n } catch (error) {\n Log.error(\"Failed to send request:\", error.message);\n callback({ retry: false, status: 0, error: error.message });\n }\n }\n\n /**\n * Executes an HTTP request with timeout and error handling.\n * @param {object} request - Request object\n * @private\n */\n async executeRequest(request) {\n const { url, payload, options, callback } = request;\n const startTime = Date.now();\n\n try {\n const requestBody = JSON.stringify(payload.body);\n\n // Handle final harvest with sendBeacon\n if (options.isFinalHarvest && navigator.sendBeacon) {\n const success = await this.sendWithBeacon(url, requestBody);\n const result = { success, status: success ? 204 : 0 };\n this.handleRequestComplete(request, result, startTime);\n return;\n }\n\n // Use fetch with timeout\n const response = await this.fetchWithTimeout(\n url,\n {\n method: \"POST\",\n body: requestBody,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n keepalive: options.isFinalHarvest,\n },\n 10000\n );\n\n const result = {\n success: response.ok,\n status: response.status,\n statusText: response.statusText,\n };\n\n this.handleRequestComplete(request, result, startTime);\n } catch (error) {\n const result = {\n success: false,\n status: 0,\n error: error.message,\n };\n\n this.handleRequestComplete(request, result, startTime);\n }\n }\n\n /**\n * Handles request completion.\n * @param {object} request - Request object\n * @param {object} result - Request result\n * @param {number} startTime - Request start timestamp\n * @param {string} endpoint - The endpoint that was used for the request\n * @private\n */\n handleRequestComplete(request, result) {\n const { callback } = request;\n\n // Use smart retry logic based on HTTP status codes\n const shouldRetryRequest =\n !result.success &&\n (result.status === 0 || // Network/timeout errors\n shouldRetry(result.status)); // Smart status code-based retry\n\n callback({\n retry: shouldRetryRequest,\n status: result.status,\n error: result.error,\n });\n }\n\n /**\n * Sends data using navigator.sendBeacon for final harvests.\n * @param {string} url - Target URL\n * @param {string} body - Request body\n * @returns {Promise<boolean>} True if successful\n * @private\n */\n async sendWithBeacon(url, body) {\n try {\n return navigator.sendBeacon(url, body);\n } catch (error) {\n Log.warn(\"sendBeacon failed, falling back to fetch:\", error.message);\n return false;\n }\n }\n\n /**\n * Fetch with timeout implementation.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/AbortController|MDN AbortController}\n * @param {string} url - Target URL\n * @param {object} options - Fetch options\n * @param {number} timeout - Timeout in milliseconds\n * @returns {Promise<Response>} Fetch response\n * @private\n */\n async fetchWithTimeout(url, options, timeout) {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error.name === \"AbortError\") {\n throw new Error(`Request timeout after ${timeout}ms`);\n }\n throw error;\n }\n }\n}\n\nexport default OptimizedHttpClient;\n","/**\n * Constants for the library.\n * @class Constants\n * @static\n */\nclass Constants {}\n\n/**\n * Enum for types/positions of ads.\n * @example var type = Constants.AdPositions.PRE\n * @enum {String}\n */\nConstants.AdPositions = {\n /** For ads shown before the content. */\n PRE: \"pre\",\n /** For ads shown during the content. */\n MID: \"mid\",\n /** For ads shown after the content. */\n POST: \"post\",\n};\n\n// bam.nr-data.net\n//bam-cell.nr-data.net\n\nConstants.COLLECTOR = {\n US: [\"bam.nr-data.net\", \"bam-cell.nr-data.net\"],\n EU: \"bam.eu01.nr-data.net\",\n Staging: \"staging-bam-cell.nr-data.net\",\n GOV: \"gov-bam.nr-data.net\",\n};\n\n// ====== VALID EVENT TYPES ======\nConstants.VALID_EVENT_TYPES = [\n \"VideoAction\",\n \"VideoAdAction\",\n \"VideoErrorAction\",\n \"VideoCustomAction\",\n];\n\nConstants.MAX_PAYLOAD_SIZE = 1048576; // 1MB = 1024 × 1024 bytes\nConstants.MAX_BEACON_SIZE = 61440; // 60KB = 60 × 1024 bytes\nConstants.MAX_EVENTS_PER_BATCH = 1000;\nConstants.INTERVAL = 10000; //10 seconds\n\nConstants.QOE_AGGREGATE_KEYS = [\n \"coreVersion\", \"instrumentation.name\",\n \"instrumentation.provider\", \"instrumentation.version\", \"isBackgroundEvent\", \"playerName\", \"playerVersion\",\n \"src\", \"viewId\", \"viewSession\", \"contentIsAutoplayed\"\n]\n\nexport default Constants;\n","/**\n * Static Log class\n *\n * @class\n * @static\n */\nclass Log {\n /**\n * Sends an error console log.\n * @param {...any} [msg] Message to show\n * @static\n */\n static error(...msg) {\n _report(msg, Log.Levels.ERROR, \"darkred\");\n }\n\n /**\n * Sends a warning console log.\n * @method Log.warn\n * @static\n * @param {...any} msg Message to show\n */\n static warn(...msg) {\n _report(msg, Log.Levels.WARNING, \"darkorange\");\n }\n\n /**\n * Sends a notice console log.\n * @method Log.notice\n * @static\n * @param {...any} msg Message to show\n */\n static notice(...msg) {\n _report([].slice.call(arguments), Log.Levels.NOTICE, \"darkcyan\");\n }\n\n /**\n * Sends a debug message to console.\n * @method Log.debug\n * @static\n * @param {...any} msg Message to show\n */\n static debug(...msg) {\n _report(msg, Log.Levels.DEBUG, \"indigo\");\n }\n\n /**\n * This utility method will add most of the HTML5 common event listeners to the player sent.\n * Events will be reported as DEBUG level messages.\n *\n * @example\n * // Already included events:\n * ['canplay', 'buffering', 'waiting', 'ended', 'play', 'playing', 'pause', 'resume', 'error',\n * 'abort', 'seek', 'seeking', 'seeked', 'stalled', 'dispose', 'loadeddata', 'loadstart',\n * 'loadedmetadata']\n *\n * @method Log.debugCommonVideoEvents\n * @static\n * @param {object|function} o Object to attach the events.\n * @param {array} [extraEvents]\n * An array of extra events to watch. ie: ['timeupdate', 'progress'].\n * If the first item is null, no common events will be added.\n * @param {function} [report] Callback function called to report events.\n * Default calls Log.debug()\n */\n static debugCommonVideoEvents(o, extraEvents, report) {\n try {\n if (Log.level <= Log.Levels.DEBUG) {\n report =\n report ||\n function (e) {\n Log.debug(\"Event: \" + e.type);\n };\n\n var playerEvents = [\n \"canplay\",\n \"buffering\",\n \"waiting\",\n \"ended\",\n \"play\",\n \"playing\",\n \"pause\",\n \"resume\",\n \"error\",\n \"abort\",\n \"seek\",\n \"seeking\",\n \"seeked\",\n \"stalled\",\n \"dispose\",\n \"loadeddata\",\n \"loadstart\",\n \"loadedmetadata\",\n ];\n if (extraEvents) {\n if (extraEvents[0] === null) {\n extraEvents.shift();\n playerEvents = extraEvents;\n } else {\n playerEvents = playerEvents.concat(extraEvents);\n }\n }\n\n for (var i = 0; i < playerEvents.length; i++) {\n if (typeof o === \"function\") {\n o.call(window, playerEvents[i], report);\n } else if (o.on) {\n o.on(playerEvents[i], report);\n } else if (o.addEventListener) {\n o.addEventListener(playerEvents[i], report);\n } else if (o.addEventHandler) {\n o.addEventHandler(playerEvents[i], report);\n } else {\n Log.warn(\n \"debugCommonVideoEvents: No common listener function found for \",\n o\n );\n }\n }\n }\n } catch (err) {\n Log.warn(err);\n }\n }\n}\n\n/**\n * Enum for log levels\n * @enum {integer}\n * @static\n * @var\n */\nLog.Levels = {\n /** No console outputs */\n SILENT: 5,\n /** Console will show errors */\n ERROR: 4,\n /** Console will show warnings */\n WARNING: 3,\n /** Console will show notices (ie: life-cyrcle logs) */\n NOTICE: 2,\n /** Console will show debug messages. */\n DEBUG: 1,\n /** Show all messages. */\n ALL: 0,\n};\n\n/**\n * Only logs of this imporance or higher will be shown.\n * @example Log.level = Log.Levels.ALL\n * @default Log.Levels.ERROR\n * @static\n */\nLog.level = Log.Levels.ERROR;\n\n/**\n * If true, logs will be outputed with colors.\n * @default true\n * @static\n */\nLog.colorful = true;\n\n/**\n * If true, logs will include the time mark.\n * @default true\n * @static\n */\nLog.includeTime = true;\n\n/**\n * Prefix included at the start of every log.\n * @default '[New Relic]'\n * @static\n */\nLog.prefix = \"[nrvideo]\";\n\n// PRIVATE MEMBERS\n\n/**\n * Returns a console message\n *\n * @private\n * @param {array} msg Message array, error object or array of messages.\n * @param {Log.Level} [level=Log.Levels.NOTICE] Defines the level of the error sent.\n * Only errors with higher or equal level than Log.logLevel will be displayed.\n * @param {string} [color='darkgreen'] Color of the header\n * @see {@link Log.level}\n */\nfunction _report(msg, level, color) {\n level = level || Log.Levels.NOTICE;\n color = color || \"darkcyan\";\n\n var prefix = Log.prefix;\n if (Log.includeTime) prefix += _getCurrentTime() + \" \";\n prefix += _level2letter(level) + \":\";\n\n // Show messages in actual console if level is enought\n if (Log.level <= level && level !== Log.Levels.SILENT) {\n if (\n !Log.colorful ||\n (typeof document !== \"undefined\" && document.documentMode)\n ) {\n // document.documentMode exits only in IE\n _plainReport(msg, prefix);\n } else {\n // choose log method\n var logMethod;\n if (level === Log.Levels.ERROR && console.error) {\n logMethod = console.error;\n } else if (level === Log.Levels.WARNING && console.warn) {\n logMethod = console.warn;\n } else if (level === Log.Levels.DEBUG && console.debug) {\n // NOTE: for some reason console.debug doesn't work on CAF Receivers.\n if (window.cast == undefined) {\n logMethod = console.debug;\n } else {\n logMethod = console.log;\n }\n } else {\n logMethod = console.log;\n }\n\n // print message\n prefix = \"%c\" + prefix;\n msg.splice(0, 0, prefix, \"color: \" + color);\n logMethod.apply(console, msg);\n }\n }\n}\n\n/**\n * Returns the current time in format hh:mm:ss.mmm (with trailing 0s)\n * @private\n * @return {string} Current time.\n */\nfunction _getCurrentTime() {\n var d = new Date();\n var hh = (\"0\" + d.getDate()).slice(-2);\n var mm = (\"0\" + d.getMinutes()).slice(-2);\n var ss = (\"0\" + d.getSeconds()).slice(-2);\n var mmm = (\"00\" + d.getMilliseconds()).slice(-3);\n return \"[\" + hh + \":\" + mm + \":\" + ss + \".\" + mmm + \"]\";\n}\n\n/**\n * Returns a console message without style\n *\n * @private\n * @param {(string|object|array)} msg Message string, object or array of messages.\n * @param {string} prefix Prefix of the message.\n */\nfunction _plainReport(msg, prefix) {\n if (msg instanceof Array) {\n for (var m in msg) {\n _plainReport(msg[m], prefix);\n }\n } else {\n if (typeof msg === \"string\") {\n console.log(prefix + \" \" + msg);\n } else {\n console.log(prefix + \"↵\");\n console.log(msg);\n }\n }\n}\n\nconst _letters = {\n 4: \"e\", // Error\n 3: \"w\", // Warning\n 2: \"n\", // Notice\n 1: \"d\", // Debug\n};\n\n/**\n * Transforms a level to a letter to identify every message.\n *\n * @private\n * @param {sLog.Level} level Level of the message\n */\nfunction _level2letter(level) {\n return _letters[level];\n}\n\n/**\n * This function is automatically executed at load.\n * Will search inside window.location.search for attribute 'nrvideo-debug=X'.\n * X can have one of these values, that will modify Log.Levels.\n * 5: SILENT,\n * 4: ERROR,\n * 3: WARNING,\n * 2: NOTICE,\n * 1: DEBUG,\n *\n * If nrvideo-colors=false is present, Log.colorful will be set to false.\n *\n * @private\n */\nfunction _loadLevelFromUrl() {\n if (\n typeof window !== \"undefined\" &&\n window.location &&\n window.location.search\n ) {\n var m = /\\?.*&*nrvideo-debug=(.+)/i.exec(window.location.search);\n if (m !== null) {\n if (m[1] === \"true\") {\n Log.level = Log.Levels.ALL;\n } else {\n Log.level = m[1];\n }\n }\n\n var m2 = /\\?.*&*nrvideo-colors=false/i.exec(window.location.search);\n if (m2 !== null) {\n Log.colorful = false;\n }\n }\n}\n\n// Execute load level\n_loadLevelFromUrl();\n\nexport default Log;\n","import pkg from \"../package.json\";\nimport Emitter from \"./emitter\";\nimport Chrono from \"./chrono\";\nimport Constants from \"./constants\";\nimport { videoAnalyticsHarvester } from \"./agent\";\nimport Log from \"./log\";\n\n/**\n * Tracker class provides the basic logic to extend Newrelic's Browser Agent capabilities.\n * Trackers are designed to listen third party elements (like video tags, banners, etc.) and send\n * information over to Browser Agent. Extend this class to create your own tracker, override\n * registerListeners and unregisterListeners for full coverage!\n *\n * @example\n * Tracker instances should be added to Core library to start sending data:\n * nrvideo.Core.addTracker(new Tracker())\n *\n * @extends Emitter\n */\nclass Tracker extends Emitter {\n /**\n * Constructor, receives options. You should call {@see registerListeners} after this.\n *\n * @param {Object} [options] Options for the tracker. See {@link setOptions}.\n */\n constructor(options) {\n super();\n\n /**\n * If you add something to this custom dictionary it will be added to every action. If you set\n * any value, it will always override the values returned by the getters.\n *\n * @example\n * If you define tracker.customData.contentTitle = 'a' and tracker.getTitle() returns 'b'.\n * 'a' will prevail.\n */\n this.customData = {};\n\n /**\n * Set time between hearbeats, in ms.\n */\n this.heartbeat = null;\n\n /**\n * Another Tracker instance. Useful to relate ad Trackers to their parent content Trackers.\n * @type Tracker\n */\n this.parentTracker = null;\n\n /**\n * Chrono that counts time since this class was instantiated.\n * @private\n */\n this._trackerReadyChrono = new Chrono();\n this._trackerReadyChrono.start();\n\n /**\n * Store the initial table of actions with time 0 ms\n */\n this._actionTable = Constants.ACTION_TABLE;\n this._actionAdTable = Constants.ACTION_AD_TABLE;\n\n options = options || {};\n this.setOptions(options);\n }\n\n /**\n * Set options for the Tracker.\n *\n * @param {Object} [options] Options for the tracker.\n * @param {number} [options.heartbeat] Set time between heartbeats. See {@link heartbeat}.\n * @param {Object} [options.customData] Set custom data. See {@link customData}.\n * @param {Tracker} [options.parentTracker] Set parent tracker. See {@link parentTracker}.\n */\n setOptions(options) {\n if (options) {\n if (options.parentTracker) this.parentTracker = options.parentTracker;\n if (options.customData) this.customData = options.customData;\n if (options.heartbeat) this.heartbeat = options.heartbeat;\n }\n }\n\n /**\n * Prepares tracker to dispose. Calls {@see unregisterListeners} and drops references.\n */\n dispose() {\n this.unregisterListeners();\n }\n\n /**\n * Override this method to register listeners to third party elements.\n *\n * @example\n * class SpecificTracker extends Tracker {\n * registerListeners() {\n * this.player.on('play', () => this.playHandler)\n * }\n *\n * playHandler() {\n * this.emit(Tracker.Events.REQUESTED)\n * }\n * }\n */\n registerListeners() {}\n\n /**\n * Override this method to unregister listeners to third party elements created with\n * {@see registerListeners}.\n *\n * @example\n * class SpecificTracker extends Tracker {\n * registerListeners() {\n * this.player.on('play', () => this.playHandler)\n * }\n *\n * unregisterListeners() {\n * this.player.off('play', () => this.playHandler)\n * }\n *\n * playHandler() {\n * this.emit(Tracker.Events.REQUESTED)\n * }\n * }\n */\n unregisterListeners() {}\n\n /**\n * Returns heartbeat time interval. 30000 (30s) if not set. See {@link setOptions}.\n * @return {number} Heartbeat interval in ms.\n * @final\n */\n getHeartbeat() {\n if (this.state._isAd) {\n // modifying heartbeat for Ad Tracker\n return 2000;\n } else {\n if (this.heartbeat) {\n return this.heartbeat;\n } else if (this.parentTracker && this.parentTracker.heartbeat) {\n return this.parentTracker.heartbeat;\n } else {\n return 30000;\n }\n }\n }\n\n /**\n * Starts heartbeating. Interval period set by options.heartbeat. Min 2000 ms.\n * This method is automaticaly called by the tracker once sendRequest is called.\n */\n startHeartbeat() {\n this._heartbeatInterval = setInterval(\n this.sendHeartbeat.bind(this),\n Math.max(this.getHeartbeat(), 2000)\n );\n }\n\n /**\n * Stops heartbeating. This method is automaticaly called by the tracker.\n */\n stopHeartbeat() {\n if (this._heartbeatInterval) {\n clearInterval(this._heartbeatInterval);\n }\n }\n\n /**\n * Heartbeating allows you to call this function each X milliseconds, defined by\n * {@link getHeartbeat}. This is useful to send regular events to track changes.\n *\n * By default it will send {@link Tracker.Events.HEARTBEAT}.\n * To start heartbeating use {@link startHeartbeat} and to stop them use {@link stopHeartbeat}.\n *\n * @example\n * Override this method to define your own Heartbeat reporting.\n *\n * class TrackerChild extends Tracker {\n * sendHeartbeat (att) {\n * this.send('MY_HEARBEAT_EVENT')\n * }\n * }\n *\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendHeartbeat(att) {\n this.sendVideoAction(Tracker.Events.HEARTBEAT, att);\n }\n\n /**\n * Override this method to return attributes for actions.\n *\n * @example\n * class SpecificTracker extends Tracker {\n * getAttributes(att) {\n * att = att || {}\n * att.information = 'something'\n * return att\n * }\n * }\n *\n * @param {object} [att] Collection of key value attributes\n * @return {object} Filled attributes\n * @final\n */\n getAttributes(att, eventType) {\n att = att || {};\n att.trackerName = this.getTrackerName();\n att.trackerVersion = this.getTrackerVersion();\n att.coreVersion = pkg.version;\n att.timeSinceTrackerReady = this._trackerReadyChrono.getDeltaTime();\n\n for (let key in this.customData) {\n att[key] = this.customData[key];\n }\n\n if (document.hidden != undefined) {\n att.isBackgroundEvent = document.hidden;\n }\n\n return att;\n }\n\n /** Override to change of the Version of tracker. ie: '1.0.1' */\n getTrackerVersion() {\n return pkg.version;\n }\n\n /** Override to change of the Name of the tracker. ie: 'custom-html5' */\n getTrackerName() {\n return \"base-tracker\";\n }\n\n /**\n * Send given event. Will automatically call {@see getAttributes} to fill information.\n * Internally, this will call {@see Emitter#emit}, so you could listen any event fired.\n *\n * @example\n * tracker.sendVideoAction('BANNER_CLICK', { url: 'http....' })\n *\n * @param {string} event Event name\n * @param {object} [att] Key:value dictionary filled with attributes.\n */\n\n sendVideoAction(event, att) {\n this.emit(\"VideoAction\", event, this.getAttributes(att));\n }\n\n sendVideoAdAction(event, att) {\n this.emit(\"VideoAdAction\", event, this.getAttributes(att));\n }\n\n sendVideoErrorAction(event, att) {\n let ev = this.isAd() ? \"adError\" : \"videoError\";\n this.emit(\"VideoErrorAction\", event, this.getAttributes(att, ev));\n }\n\n sendVideoCustomAction(event, att) {\n this.emit(\n \"VideoCustomAction\",\n event,\n this.getAttributes(att, \"customAction\")\n );\n }\n\n /**\n * Sets the harvest interval for video tracking.\n * @param {*} interval - The interval in milliseconds.\n * @returns {void}\n */\n\n setHarvestInterval(interval) {\n if (!videoAnalyticsHarvester) {\n Log.error(\"VideoAnalyticsHarvester is not available\");\n return;\n }\n\n try {\n videoAnalyticsHarvester.setHarvestInterval(interval);\n } catch (error) {\n Log.error(\"Failed to set harvest interval:\", error.message);\n return;\n }\n }\n}\n\n/**\n * Enumeration of events fired by this class.\n *\n * @static\n * @memberof Tracker\n * @enum {string}\n */\nTracker.Events = {\n /** The heartbeat event is sent once every 30 seconds while the video is playing. */\n HEARTBEAT: \"HEARTBEAT\",\n QOE_AGGREGATE: \"QOE_AGGREGATE\",\n};\n\nexport default Tracker;\n","import Chrono from \"./chrono\";\nimport Log from \"./log\";\n\n/**\n * State machine for a VideoTracker and its monitored video.\n */\nclass VideoTrackerState {\n /** Constructor */\n constructor() {\n this.reset();\n\n //this.setupNetworkListeners();\n\n /**\n * Time when the VideoTrackerState was initializated.\n * @private\n */\n this._createdAt = Date.now();\n this._hb = true;\n this._acc = 0;\n this._bufferAcc = 0;\n }\n\n /** Resets all flags and chronos. */\n reset() {\n /**\n * Unique identifier of the view.\n * @private\n */\n this._viewSession = null;\n\n /**\n * Number of views seen.\n * @private\n */\n this._viewCount = 0;\n\n /**\n * True if it is tracking ads.\n * @private\n */\n this._isAd = false;\n\n /**\n * Number of errors fired. 'End' resets it.\n */\n this.numberOfErrors = 0;\n\n /**\n * Number of ads shown.\n */\n this.numberOfAds = 0;\n\n /**\n * Number of videos played.\n */\n this.numberOfVideos = 0;\n\n /**\n * The amount of ms the user has been watching content (not paused, not buffering, not ads...)\n */\n this.totalPlaytime = 0;\n\n this.weightedAverageBitrate = 0;\n\n /**\n * The amount of ms the user has been watching ads during an ad break.\n */\n this.totalAdPlaytime = 0;\n\n /** True if you are in the middle of an ad break. */\n this.isAdBreak = false;\n\n /** True if initial buffering event already happened. */\n this.initialBufferingHappened = false;\n\n /**\n * New QoE KPIs - Content only\n */\n\n /**\n * Startup Time: Time from CONTENT_REQUEST to CONTENT_START in milliseconds.\n */\n this.startupTime = null;\n\n /**\n * Peak Bitrate: Maximum contentBitrate observed across all content playback.\n */\n this.peakBitrate = 0;\n\n /**\n * Last tracked bitrate\n */\n this._lastBitrate = null;\n\n /**\n * Tracks the last updated timestamp for bitrate\n * */\n this._lastBitrateChangeTimestamp = null;\n\n /**\n * total bitrate partial value for average weighted average bitrate\n */\n this.partialAverageBitrate = 0;\n\n /**\n * Had Startup Failure: TRUE if CONTENT_ERROR occurs before CONTENT_START.\n */\n this.hadStartupFailure = false;\n\n /**\n * Had Playback Failure: TRUE if CONTENT_ERROR occurs during content playback.\n */\n this.hadPlaybackFailure = false;\n\n /**\n * The amount of ms the user has been rebuffering during content playback.\n */\n this.totalRebufferingTime = 0;\n\n this.resetFlags();\n this.resetChronos();\n }\n\n /** Resets flags. */\n resetFlags() {\n /** True once the player has finished loading. */\n this.isPlayerReady = false;\n\n /** True if the video has been user-requested to play. ie: user cicks play. */\n this.isRequested = false;\n\n /** True if the video has starting playing. ie: actual images/audio showing in screen. */\n this.isStarted = false;\n\n /** True if the video is paused. */\n this.isPaused = false;\n\n /** True if the video is performing a seek action. */\n this.isSeeking = false;\n\n /** True if the video is currently buffering. */\n this.isBuffering = false;\n\n /** True if the video is currently playing (not buffering, not paused...) */\n this.isPlaying = false;\n }\n\n /** Resets chronos. */\n resetChronos() {\n /** Chrono that counts time since last requested event. */\n this.timeSinceRequested = new Chrono();\n\n /** Chrono that counts time since last start event. */\n this.timeSinceStarted = new Chrono();\n\n /** Chrono that counts time since last pause event. */\n this.timeSincePaused = new Chrono();\n\n /** Chrono that counts time since last seeking start event. */\n this.timeSinceSeekBegin = new Chrono();\n\n /** Chrono that counts time since last buffering start event. */\n this.timeSinceBufferBegin = new Chrono();\n\n /** Chrono that counts time since last ad break start event. */\n this.timeSinceAdBreakStart = new Chrono();\n\n /** Chrono that counts time since last download event. */\n this.timeSinceLastDownload = new Chrono();\n\n /** Chrono that counts time since last heartbeat. */\n this.timeSinceLastHeartbeat = new Chrono();\n\n /** Chrono that counts time since last rendition change. */\n this.timeSinceLastRenditionChange = new Chrono();\n\n /** Ads only. Chrono that counts time since last ad quartile. */\n this.timeSinceLastAdQuartile = new Chrono();\n\n /** Content only. Chrono that counts time since last AD_END. */\n this.timeSinceLastAd = new Chrono();\n\n /** Chrono that counts time since last error event. */\n this.timeSinceLastError = new Chrono();\n\n /** Chrono that counts time since last ad error event. */\n this.timeSinceLastAdError = new Chrono();\n\n /** Chrono that counts time since last *_RESUME. Only for buffering events. */\n this.timeSinceResumed = new Chrono();\n\n /** Chrono that counts time since last *_SEEK_END. Only for buffering events. */\n this.timeSinceSeekEnd = new Chrono();\n\n /** Chrono that counts the ammount of time the video have been playing since the last event. */\n this.playtimeSinceLastEvent = new Chrono();\n\n /** A dictionary containing the custom timeSince attributes. */\n this.customTimeSinceAttributes = {};\n\n /** This are used to collect the time of buffered and pause resume between two heartbeats */\n this.elapsedTime = new Chrono();\n this.bufferElapsedTime = new Chrono();\n\n /** tracks total ad play time */\n this._totalAdPlaytime = new Chrono();\n }\n\n /** Returns true if the tracker is currently on ads. */\n isAd() {\n return this._isAd;\n }\n\n /** Sets if the tracker is currenlty tracking ads */\n setIsAd(isAd) {\n this._isAd = isAd;\n }\n\n /**\n * Set the Chrono for the custom attribute\n *\n * @param {object} name Time since attribute name.\n */\n setTimeSinceAttribute(name) {\n this.customTimeSinceAttributes[name] = new Chrono();\n this.customTimeSinceAttributes[name].start();\n }\n\n /**\n * Delete a time since attribute\n *\n * @param {object} name Time since attribute name.\n */\n removeTimeSinceAttribute(name) {\n delete this.customTimeSinceAttributes[name];\n }\n\n /**\n * Returns a random-generated view Session ID, useful to sort by views.\n */\n getViewSession() {\n if (!this._viewSession) {\n let time = new Date().getTime();\n let random =\n Math.random().toString(36).substring(2) +\n Math.random().toString(36).substring(2);\n\n this._viewSession = time + \"-\" + random;\n }\n\n return this._viewSession;\n }\n\n /**\n * Returns a random-generated view Session ID, plus a view count, allowing you to distinguish\n * between two videos played in the same session.\n */\n getViewId() {\n return this.getViewSession() + \"-\" + this._viewCount;\n }\n\n /**\n * Fills given object with state-based attributes.\n *\n * @param {object} att Collection fo key value attributes\n * @return {object} Filled attributes\n */\n getStateAttributes(att) {\n att = att || {};\n\n if (this.isAd()) {\n // Ads only\n if (this.isRequested) {\n att.timeSinceAdRequested = this.timeSinceRequested.getDeltaTime();\n att.timeSinceLastAdHeartbeat =\n this.timeSinceLastHeartbeat.getDeltaTime();\n }\n if (this.isStarted)\n att.timeSinceAdStarted = this.timeSinceStarted.getDeltaTime();\n if (this.isPaused)\n att.timeSinceAdPaused = this.timeSincePaused.getDeltaTime();\n if (this.isBuffering)\n att.timeSinceAdBufferBegin = this.timeSinceBufferBegin.getDeltaTime();\n if (this.isSeeking)\n att.timeSinceAdSeekBegin = this.timeSinceSeekBegin.getDeltaTime();\n if (this.isAdBreak)\n att.timeSinceAdBreakBegin = this.timeSinceAdBreakStart.getDeltaTime();\n\n // Only include timeSinceLastAdError if an ad error has occurred\n if (this.numberOfErrors > 0 && this.timeSinceLastAdError.startTime > 0) {\n att.timeSinceLastAdError = this.timeSinceLastAdError.getDeltaTime();\n }\n\n att.numberOfAds = this.numberOfAds;\n } else {\n // Content only\n if (this.isRequested) {\n att.timeSinceRequested = this.timeSinceRequested.getDeltaTime();\n att.timeSinceLastHeartbeat = this.timeSinceLastHeartbeat.getDeltaTime();\n }\n if (this.isStarted)\n att.timeSinceStarted = this.timeSinceStarted.getDeltaTime();\n if (this.isPaused)\n att.timeSincePaused = this.timeSincePaused.getDeltaTime();\n if (this.isBuffering)\n att.timeSinceBufferBegin = this.timeSinceBufferBegin.getDeltaTime();\n if (this.isSeeking)\n att.timeSinceSeekBegin = this.timeSinceSeekBegin.getDeltaTime();\n att.timeSinceLastAd = this.timeSinceLastAd.getDeltaTime();\n\n // Only include timeSinceLastError if a content error has occurred\n if (this.numberOfErrors > 0 && this.timeSinceLastError.startTime > 0) {\n att.timeSinceLastError = this.timeSinceLastError.getDeltaTime();\n }\n\n att.numberOfVideos = this.numberOfVideos;\n }\n att.numberOfErrors = this.numberOfErrors;\n\n // Playtime\n if (!this.isAd()) {\n // Content only\n if (this.playtimeSinceLastEvent.startTime > 0) {\n att.playtimeSinceLastEvent = this.playtimeSinceLastEvent.getDeltaTime();\n } else {\n att.playtimeSinceLastEvent = 0;\n }\n if (this.isPlaying) {\n this.playtimeSinceLastEvent.start();\n } else {\n this.playtimeSinceLastEvent.reset();\n }\n this.totalPlaytime += att.playtimeSinceLastEvent;\n att.totalPlaytime = this.totalPlaytime;\n }\n\n for (const [key, value] of Object.entries(this.customTimeSinceAttributes)) {\n att[key] = value.getDeltaTime();\n }\n\n return att;\n }\n\n getQoeAttributes(att) {\n att = att || {};\n const kpi = {};\n\n try {\n // QoE KPIs - Content only\n if (this.startupTime !== null) {\n kpi[\"startupTime\"] = this.startupTime;\n }\n if (this.peakBitrate > 0) {\n kpi[\"peakBitrate\"] = this.peakBitrate;\n }\n kpi[\"hadStartupFailure\"] = this.hadStartupFailure;\n kpi[\"hadPlaybackFailure\"] = this.hadPlaybackFailure;\n kpi[\"totalRebufferingTime\"] = this.totalRebufferingTime;\n // Calculate rebuffering ratio as percentage (avoid division by zero)\n kpi[\"rebufferingRatio\"] = this.totalPlaytime > 0\n ? (this.totalRebufferingTime / this.totalPlaytime) * 100\n : 0;\n kpi[\"totalPlaytime\"] = this.totalPlaytime;\n kpi[\"averageBitrate\"] = this.weightedBitrate;\n } catch (error) {\n Log.error(\"Failed to add attributes for QOE KPIs\", error.message);\n }\n\n att.qoe = kpi;\n return att;\n }\n\n /**\n * Calculate the bufferType attribute.\n *\n * @param {boolean} isInitialBuffering Is initial buffering event.\n */\n calculateBufferType(isInitialBuffering) {\n let bufferType = \"\";\n if (isInitialBuffering) {\n bufferType = \"initial\";\n } else if (this.isSeeking) {\n bufferType = \"seek\";\n } else if (this.isPaused) {\n bufferType = \"pause\";\n } else {\n // If none of the above is true, it is a connection buffering\n bufferType = \"connection\";\n }\n Log.debug(\"Buffer Type = \" + bufferType);\n\n return bufferType;\n }\n\n /**\n * Augments view count. This will be called with each *_START and *_END.\n */\n goViewCountUp() {\n this._viewCount++;\n }\n\n /**\n * Checks flags and changes state.\n * @returns {boolean} True if the state changed.\n */\n goPlayerReady() {\n if (!this.isPlayerReady) {\n this.isPlayerReady = true;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goRequest() {\n if (!this.isRequested) {\n this.isRequested = true;\n\n this.timeSinceLastAd.reset();\n this.timeSinceRequested.start();\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goStart() {\n if (this.isRequested && !this.isStarted) {\n if (this.isAd()) {\n this.numberOfAds++;\n } else {\n this.numberOfVideos++;\n }\n this.isStarted = true;\n this.isPlaying = true;\n this.timeSinceStarted.start();\n this.playtimeSinceLastEvent.start();\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goEnd() {\n if (this.isRequested) {\n this.numberOfErrors = 0;\n this.resetFlags();\n this.timeSinceRequested.stop();\n this.timeSinceStarted.stop();\n this.playtimeSinceLastEvent.stop();\n this.isPlaying = false;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goPause() {\n if (this.isStarted && !this.isPaused) {\n this.isPaused = true;\n this.isPlaying = false;\n this.timeSincePaused.start();\n this.playtimeSinceLastEvent.stop();\n this.timeSinceResumed.reset();\n if (this.isBuffering) {\n this._bufferAcc += this.bufferElapsedTime.getDeltaTime();\n }\n this.elapsedTime.start();\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goResume() {\n if (this.isStarted && this.isPaused) {\n this.isPaused = false;\n this.isPlaying = true;\n this.timeSincePaused.stop();\n this.timeSinceResumed.start();\n if (this._hb) {\n this._acc = this.elapsedTime.getDeltaTime();\n this._hb = false;\n } else {\n if (this.isBuffering) {\n this.bufferElapsedTime.start();\n }\n this._acc += this.elapsedTime.getDeltaTime();\n }\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goBufferStart() {\n if (this.isRequested && !this.isBuffering) {\n this.isBuffering = true;\n this.isPlaying = false;\n this.timeSinceBufferBegin.start();\n this.bufferElapsedTime.start();\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goBufferEnd() {\n if (this.isRequested && this.isBuffering) {\n this.isBuffering = false;\n this.isPlaying = true;\n this.timeSinceBufferBegin.stop();\n if (this._hb) {\n this._bufferAcc = this.bufferElapsedTime.getDeltaTime();\n this._hb = false;\n } else {\n this._bufferAcc += this.bufferElapsedTime.getDeltaTime();\n }\n\n // Accumulate total rebuffering time for content only\n if (!this.isAd() && this.initialBufferingHappened) {\n this.totalRebufferingTime += this.timeSinceBufferBegin.getDeltaTime();\n }\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goSeekStart() {\n if (this.isStarted && !this.isSeeking) {\n this.isSeeking = true;\n this.isPlaying = false;\n this.timeSinceSeekBegin.start();\n this.timeSinceSeekEnd.reset();\n\n //new\n // this.seekStartTime = Date.now();\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goSeekEnd() {\n if (this.isStarted && this.isSeeking) {\n this.isSeeking = false;\n this.isPlaying = true;\n this.timeSinceSeekBegin.stop();\n this.timeSinceSeekEnd.start();\n\n //new\n // this.seekEndTime = Date.now();\n // this.seekDuration = this.seekEndTime - this.seekStartTime;\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goAdBreakStart() {\n if (!this.isAdBreak) {\n this.isAdBreak = true;\n this.timeSinceAdBreakStart.start();\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Checks flags and changes state\n * @returns {boolean} True if the state changed.\n */\n goAdBreakEnd() {\n if (this.isAdBreak) {\n this.isRequested = false;\n this.isAdBreak = false;\n this.totalAdPlaytime = this.timeSinceAdBreakStart.getDeltaTime();\n this.timeSinceAdBreakStart.stop();\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Restarts download chrono.\n */\n goDownload() {\n this.timeSinceLastDownload.start();\n }\n\n /**\n * Restarts heartbeat chrono.\n */\n goHeartbeat() {\n this.timeSinceLastHeartbeat.start();\n }\n\n /**\n * Restarts rendition change chrono.\n */\n goRenditionChange() {\n this.timeSinceLastRenditionChange.start();\n }\n\n /**\n * Restarts ad quartile chrono.\n */\n goAdQuartile() {\n this.timeSinceLastAdQuartile.start();\n }\n\n /**\n * Increments error counter and starts appropriate error timer.\n */\n goError() {\n this.isError = true;\n this.numberOfErrors++;\n\n if (this.isAd()) {\n this.timeSinceLastAdError.start();\n } else {\n this.timeSinceLastError.start();\n\n // Track failure flags for content errors only\n // Had Startup Failure: error before content started\n if (!this.isStarted) {\n this.hadStartupFailure = true;\n } else {\n // Had Playback Failure: any content error\n this.hadPlaybackFailure = true;\n }\n }\n }\n\n /**\n * Restarts last ad chrono.\n */\n goLastAd() {\n this.timeSinceLastAd.start();\n }\n\n /**\n * Updates peak bitrate with current bitrate value (content only).\n * @param {number} bitrate Current content bitrate in bps.\n */\n trackContentBitrateState(bitrate) {\n if (bitrate && typeof bitrate === \"number\") {\n this.peakBitrate = Math.max(this.peakBitrate, bitrate);\n\n if(this._lastBitrate === null || this._lastBitrate !== bitrate) {\n const deltaPlaytime = this._lastBitrateChangeTimestamp === null ? this.totalPlaytime : Date.now() - this._lastBitrateChangeTimestamp;\n const currentWeightedBitrate = (bitrate * deltaPlaytime);\n this.partialAverageBitrate += currentWeightedBitrate;\n this.weightedBitrate = currentWeightedBitrate / deltaPlaytime;\n this._lastBitrate = bitrate;\n this._lastBitrateChangeTimestamp = Date.now();\n }\n }\n }\n\n /**\n * Resets tracked variable for view id change\n * */\n resetViewIdTrackedState() {\n this.peakBitrate = 0;\n this.partialAverageBitrate = 0;\n this.startupTime = null;\n this._lastBitrate = null;\n this._lastBitrateChangeTimestamp = null;\n }\n\n /** Methods to manage total ads time chrono */\n clearTotalAdsTime() {\n console.log(\"clear total ads time\", this.totalAdTime);\n this._totalAdPlaytime.reset();\n }\n\n totalAdTime() {\n return this._totalAdPlaytime.getDuration();\n }\n\n startAdsTime() {\n console.log(\"startAdsTime\");\n return this._totalAdPlaytime.start();\n }\n\n stopAdsTime() {\n console.log(\"stopAdsTime\");\n return this._totalAdPlaytime.stop();\n }\n\n setStartupTime(totalAdTime) {\n if (this.startupTime === null) {\n this.startupTime = Math.max(this.timeSinceRequested.getDeltaTime() - totalAdTime, 0)\n }\n }\n\n}\n\nexport default VideoTrackerState;\n","import pkg from \"../package.json\";\nimport Log from \"./log\";\n\n/**\n * Builds the harvest URL with proper query parameters.\n * @returns {string} Harvest URL\n */\n\nexport function buildUrl(fallbackUrl) {\n try {\n if (!window.NRVIDEO || !window.NRVIDEO.info) {\n throw new Error(\"NRVIDEO info is not available.\");\n }\n\n let { beacon, licenseKey, applicationID } = window.NRVIDEO.info;\n\n if (!beacon || !licenseKey)\n throw new Error(\n \"Options object provided by New Relic is not correctly initialized\"\n );\n\n if (applicationID) {\n return `https://${\n fallbackUrl ? fallbackUrl : beacon\n }/ins/1/${licenseKey}?a=${applicationID}&v=${pkg.version}&ref=${\n window.location.href\n }&ca=VA`;\n }\n\n return `https://${\n fallbackUrl ? fallbackUrl : beacon\n }/ins/1/${licenseKey}?&v=${pkg.version}&ref=${window.location.href}&ca=VA`;\n } catch (error) {\n console.error(error.message);\n return null; // Return null instead of undefined\n }\n}\n\n/**\n * Returns a function for use as a replacer parameter in JSON.stringify() to handle circular references.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value MDN - Cyclical object value}\n * @returns {Function} A function that filters out values it has seen before.\n */\nconst getCircularReplacer = () => {\n const seen = new WeakSet();\n return (key, value) => {\n if (typeof value === \"object\" && value !== null) {\n if (seen.has(value)) {\n return;\n }\n seen.add(value);\n }\n return value;\n };\n};\n\n/**\n * The native JSON.stringify method augmented with a replacer function to handle circular references.\n * Circular references will be excluded from the JSON output rather than triggering errors.\n * @param {*} val - A value to be converted to a JSON string.\n * @returns {string} A JSON string representation of the value, with circular references handled.\n */\nfunction stringify(val) {\n try {\n return JSON.stringify(val, getCircularReplacer()) ?? \"\";\n } catch (e) {\n Log.error(\"Error stringifying value:\", e.message);\n return \"\";\n }\n}\n\nexport function dataSize(data) {\n if (typeof data === \"string\" && data.length) return data.length;\n if (typeof data !== \"object\") return undefined;\n // eslint-disable-next-line\n if (\n typeof ArrayBuffer !== \"undefined\" &&\n data instanceof ArrayBuffer &&\n data.byteLength\n )\n return data.byteLength;\n if (typeof Blob !== \"undefined\" && data instanceof Blob && data.size)\n return data.size;\n if (typeof FormData !== \"undefined\" && data instanceof FormData)\n return undefined;\n\n try {\n return stringify(data).length;\n } catch (e) {\n return undefined;\n }\n}\n\n/**\n * Determines if a request should be retried based on HTTP status code\n * @param {number} status - HTTP status code\n * @returns {boolean} - True if request should be retried\n */\nexport function shouldRetry(status) {\n switch (status) {\n case 408: // Request Timeout\n case 429: // Too Many Requests\n case 500: // Internal Server Error\n return true;\n case 401: // Unauthorized - don't retry\n case 403: // Forbidden - don't retry\n case 404: // Not Found - don't retry\n return false;\n }\n // Retry for 5xx server errors and specific ranges\n return (status >= 502 && status <= 504) || (status >= 512 && status <= 530);\n}\n\n/**\n * Compresses a JSON payload using the Compression Streams API with Gzip.\n * see @description(https://developer.mozilla.org/en-US/docs/Web/API/Compression_Streams_API)\n * @param {object} payload - The JSON object to compress.\n * @returns {Promise<Blob>} A Promise that resolves with a Blob of the Gzipped data.\n */\n\nexport function compressPayload(payload) {\n const stringifiedPayload = JSON.stringify(payload);\n const stream = new Blob([stringifiedPayload]).stream();\n const compressionStream = new CompressionStream(\"gzip\");\n const compressedStream = stream.pipeThrough(compressionStream);\n\n return new Response(compressedStream).blob();\n}\n\n/**\n * Decompresses a gzipped Blob back to a JSON object using the Compression Streams API.\n * @param {Blob|ArrayBuffer|Uint8Array} compressedData - The gzipped data to decompress.\n * @returns {Promise<object>} A Promise that resolves with the decompressed JSON object.\n */\nexport async function decompressPayload(compressedData) {\n try {\n // Convert different input types to a stream\n let stream;\n if (compressedData instanceof Blob) {\n stream = compressedData.stream();\n } else if (compressedData instanceof ArrayBuffer) {\n stream = new Blob([compressedData]).stream();\n } else if (compressedData instanceof Uint8Array) {\n stream = new Blob([compressedData]).stream();\n } else {\n throw new Error(\"Unsupported compressed data type\");\n }\n\n // Decompress using DecompressionStream\n const decompressionStream = new DecompressionStream(\"gzip\");\n const decompressedStream = stream.pipeThrough(decompressionStream);\n\n // Convert back to text\n const response = new Response(decompressedStream);\n const decompressedText = await response.text();\n\n // Parse JSON\n return JSON.parse(decompressedText);\n } catch (error) {\n throw new Error(`Failed to decompress payload: ${error.message}`);\n }\n}\n\n/**\n * Filters an object to include only the specified keys.\n * Creates a new object containing only the key-value pairs from the source object\n * that match the provided keys array.\n * @param {string[]} keys - Array of keys to extract from the object. If empty, null, or not an array, returns the original object.\n * @param {object} obj - The source object to extract entries from.\n * @returns {object} A new object containing only the entries that match the specified keys. Returns an empty object if obj is invalid.\n * @example\n * const data = { name: 'John', age: 30, city: 'NYC', country: 'USA' };\n * const filtered = getObjectEntriesForKeys(['name', 'city'], data);\n * // Returns: { name: 'John', city: 'NYC' }\n */\nexport function getObjectEntriesForKeys(keys, obj) {\n if(!keys || !Array.isArray(keys) || keys.length === 0) return obj;\n if(!obj || typeof obj !== 'object') return {};\n\n return keys.reduce((result, key) => {\n if(key in obj) {\n result[key] = obj[key];\n }\n return result;\n }, {});\n}","import { NrVideoEventAggregator } from \"./eventAggregator\";\nimport { RetryQueueHandler } from \"./retryQueueHandler\";\nimport { OptimizedHttpClient } from \"./optimizedHttpClient\";\nimport { buildUrl, dataSize } from \"./utils\";\nimport Constants from \"./constants\";\nimport Log from \"./log\";\n\n/**\n * Enhanced harvest scheduler that orchestrates the video analytics data collection,\n * processing, and transmission with smart harvesting and performance monitoring.\n */\n\nexport class HarvestScheduler {\n constructor(eventAggregator) {\n // Core components\n this.eventBuffer = eventAggregator;\n this.retryQueueHandler = new RetryQueueHandler();\n this.httpClient = new OptimizedHttpClient();\n this.fallBackUrl = \"\";\n this.retryCount = 0;\n\n // Set up smart harvest callback\n if (this.eventBuffer instanceof NrVideoEventAggregator) {\n this.eventBuffer.setSmartHarvestCallback((type, threshold) =>\n this.triggerSmartHarvest(type, threshold)\n );\n }\n\n // Scheduler state\n this.isStarted = false;\n this.currentTimerId = null;\n this.harvestCycle = Constants.INTERVAL;\n this.isHarvesting = false;\n\n // Page lifecycle handling\n this.setupPageLifecycleHandlers();\n }\n\n /**\n * Starts the harvest scheduler.\n */\n startScheduler() {\n if (this.isStarted) {\n Log.warn(\"Harvest scheduler is already started\");\n return;\n }\n\n this.isStarted = true;\n\n Log.notice(\"Starting harvest scheduler\", {\n harvestCycle: this.harvestCycle,\n eventBufferSize: this.eventBuffer ? this.eventBuffer.size() : 0,\n });\n\n this.scheduleNextHarvest();\n }\n\n /**\n * Stops the harvest scheduler.\n */\n stopScheduler() {\n if (!this.isStarted) {\n return;\n }\n\n this.isStarted = false;\n\n if (this.currentTimerId) {\n clearTimeout(this.currentTimerId);\n this.currentTimerId = null;\n }\n\n Log.notice(\"Harvest scheduler stopped\");\n }\n\n /**\n * Triggers a smart harvest when buffer reaches threshold capacity.\n * @param {string} type - Type of harvest trigger ('smart' or 'overflow')\n * @param {number} threshold - Threshold percentage that triggered the harvest (60 or 90)\n */\n async triggerSmartHarvest(type, threshold) {\n Log.notice(`${type} harvest triggered at ${threshold}% threshold`, {\n type,\n threshold,\n });\n\n // If buffer is empty, abort harvest\n if (!this.eventBuffer || this.eventBuffer.isEmpty()) return;\n\n // Clear existing timer to prevent redundant harvests\n if (this.currentTimerId) {\n clearTimeout(this.currentTimerId);\n this.currentTimerId = null;\n }\n\n try {\n await this.triggerHarvest({});\n } catch (error) {\n Log.error(`${type} harvest failed:`, error.message);\n } finally {\n // Schedule next harvest after smart harvest completes\n if (this.isStarted) {\n this.scheduleNextHarvest();\n }\n }\n }\n\n /**\n * Schedules the next harvest based on current conditions.\n * @private\n */\n scheduleNextHarvest() {\n if (!this.isStarted) return;\n\n const interval = this.harvestCycle;\n this.currentTimerId = setTimeout(() => this.onHarvestInterval(), interval);\n }\n\n /**\n * Handles the harvest interval timer.\n * @private\n */\n async onHarvestInterval() {\n try {\n // Check if there's any data to harvest (buffer or retry queue) before starting the harvest process\n const hasBufferData = this.eventBuffer && !this.eventBuffer.isEmpty();\n const hasRetryData =\n this.retryQueueHandler && this.retryQueueHandler.getQueueSize() > 0;\n\n if (!hasBufferData && !hasRetryData) return;\n await this.triggerHarvest({});\n } catch (error) {\n Log.error(\"Error during scheduled harvest:\", error.message);\n } finally {\n this.scheduleNextHarvest();\n }\n }\n\n /**\n * Triggers a harvest cycle with comprehensive error handling and monitoring.\n * @param {object} options - Harvest options\n * @param {boolean} options.isFinalHarvest - Whether this is a final harvest on page unload\n * @param {boolean} options.force - Force harvest even if buffer is empty\n * @returns {Promise<object>} Harvest result\n */\n async triggerHarvest(options = {}) {\n if (this.isHarvesting) {\n return { success: false, reason: \"harvest_in_progress\" };\n }\n\n this.isHarvesting = true;\n\n try {\n // Drain events from buffer\n let events = this.drainEvents(options);\n\n // For beacon harvests, trim events to fit beacon size if necessary\n if (options.isFinalHarvest) {\n const maxBeaconSize = Constants.MAX_BEACON_SIZE;\n const payloadSize = dataSize(events);\n\n if (payloadSize > maxBeaconSize) {\n // Trim events to fit beacon size (keep most recent events)\n events = this.trimEventsToFit(events, maxBeaconSize);\n }\n }\n\n // Send single payload - buffer limits guarantee it fits API constraints\n const result = await this.sendChunk(events, options, true);\n\n return {\n success: result.success,\n totalChunks: 1,\n results: [result],\n };\n } catch (error) {\n Log.error(\"Harvest cycle failed:\", error.message);\n this.handleHarvestFailure(error);\n\n return {\n success: false,\n error: error.message,\n consecutiveFailures: this.consecutiveFailures,\n };\n } finally {\n this.isHarvesting = false;\n }\n }\n\n /**\n * Trims events to fit within a specified size limit for beacon harvests.\n * Keeps the most recent events and discards older ones.\n * @param {Array} events - Events to trim\n * @param {number} maxSize - Maximum payload size in bytes\n * @returns {Array} Trimmed events that fit within size limit\n * @private\n */\n trimEventsToFit(events, maxSize) {\n if (events.length === 0) return events;\n\n // Start from the most recent events (end of array) and work backwards\n const trimmedEvents = [];\n let currentSize = 0;\n\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i];\n\n // Check if adding this event would exceed the limit\n const testPayloadSize = dataSize({ ins: [event, ...trimmedEvents] });\n\n if (testPayloadSize > maxSize) continue;\n\n // Add event to the beginning to maintain chronological order\n trimmedEvents.unshift(event);\n currentSize = testPayloadSize;\n }\n\n const discardedCount = events.length - trimmedEvents.length;\n if (discardedCount > 0) {\n const discardedEvents = events.slice(0, discardedCount);\n Log.warn(`Discarded ${discardedCount} events to fit beacon size limit`, {\n originalCount: events.length,\n trimmedCount: trimmedEvents.length,\n finalSize: currentSize,\n maxSize,\n });\n\n // send discarded events to retry queue\n if (this.retryQueueHandler) {\n this.retryQueueHandler.addFailedEvents(discardedEvents);\n }\n }\n\n return trimmedEvents;\n }\n\n /**\n * Drains events from the event buffer and optionally includes retry queue data.\n * Uses fresh-events-first approach with payload limits.\n * @param {object} options - Harvest options\n * @returns {Array} Drained events\n * @private\n */\n drainEvents() {\n // Always drain fresh events first (priority approach)\n const freshEvents = this.eventBuffer.drain();\n let events = [...freshEvents];\n let currentPayloadSize = dataSize(freshEvents);\n\n // Always check retry queue if it has data - no flags needed\n if (this.retryQueueHandler && this.retryQueueHandler.getQueueSize() > 0) {\n //const retryQueueSize = this.retryQueueHandler.getQueueSize();\n\n // Calculate available space for retry events\n const availableSpace = Constants.MAX_PAYLOAD_SIZE - currentPayloadSize;\n const availableEventCount =\n Constants.MAX_EVENTS_PER_BATCH - events.length;\n\n if (availableSpace > 0 && availableEventCount > 0) {\n const retryEvents = this.retryQueueHandler.getRetryEventsToFit(\n availableSpace,\n availableEventCount\n );\n\n if (retryEvents.length > 0) {\n events = [...retryEvents, ...events]; // Append retry events before fresh events for maintaining chronoligical order\n }\n }\n }\n return events;\n }\n\n /**\n * Sends a chunk of events using the optimized HTTP client.\n * @param {Array} chunk - Events to send\n * @param {object} options - Harvest options\n * @param {boolean} isLastChunk - Whether this is the last chunk\n * @returns {Promise<object>} Send result\n * @private\n */\n async sendChunk(chunk, options, isLastChunk) {\n const url = buildUrl(this.fallBackUrl); //\n const payload = { body: { ins: chunk } };\n const requestOptions = {\n url,\n payload,\n options: {\n ...options,\n isLastChunk,\n },\n };\n return new Promise((resolve) => {\n this.httpClient.send(requestOptions, (result) => {\n if (result.retry) {\n this.handleRequestFailure(chunk);\n } else {\n // Inline reset logic for successful request\n this.retryCount = 0;\n this.fallBackUrl = \"\";\n }\n resolve({\n success: !result.retry,\n status: result.status,\n error: result.error,\n chunk,\n eventCount: chunk.length,\n });\n });\n });\n }\n\n /**\n * Handles request failure and implements failover logic for US region.\n * @param {Array} chunk - Failed chunk to add to retry queue\n * @private\n */\n handleRequestFailure(chunk) {\n // Add failed events to retry queue\n this.retryQueueHandler.addFailedEvents(chunk);\n // Only apply failover logic for US region\n if (window.NRVIDEO?.info?.region !== \"US\") return;\n this.retryCount++;\n if (this.retryCount > 5) {\n // Reset to primary endpoint after too many failures\n this.retryCount = 0;\n this.fallBackUrl = \"\";\n } else if (this.retryCount >= 2) {\n // Switch to fallback after 2 consecutive failures\n this.fallBackUrl = Constants.COLLECTOR[\"US\"][1];\n }\n }\n\n /**\n * Handles harvest failure scenarios.\n * @param {Error} error - Harvest error\n * @private\n */\n handleHarvestFailure(error) {\n this.consecutiveFailures++;\n\n Log.warn(\"Harvest failure handled\", {\n error: error.message,\n consecutiveFailures: this.consecutiveFailures,\n });\n }\n\n /**\n * Updates the harvest interval and restarts the scheduler to apply the new interval.\n * @param {number} newInterval - The new harvest interval in milliseconds\n * @returns {boolean} - True if interval was updated successfully, false otherwise\n */\n\n updateHarvestInterval(newInterval) {\n if (typeof newInterval !== \"number\" && isNaN(newInterval)) {\n Log.warn(\"Invalid newInterval provided to updateHarvestInterval\");\n return;\n }\n\n if (newInterval < 1000 || newInterval > 300000) {\n Log.warn(\"newInterval out of bounds (1000-300000), ignoring\");\n return;\n }\n\n // Check if the interval has actually changed to avoid unnecessary actions\n if (this.harvestCycle === newInterval) {\n return;\n }\n\n // 1. Update the harvestCycle property with the new interval\n this.harvestCycle = newInterval;\n Log.notice(\"Updated harvestCycle:\", this.harvestCycle);\n\n // 2. Clear the existing timer\n if (this.currentTimerId) {\n clearTimeout(this.currentTimerId);\n this.currentTimerId = null;\n }\n\n // 3. Schedule a new timer with the updated interval\n if (this.isStarted) {\n this.scheduleNextHarvest();\n }\n\n return;\n }\n\n /**\n * Sets up page lifecycle event handlers.\n * @private\n */\n setupPageLifecycleHandlers() {\n let finalHarvestTriggered = false;\n\n const triggerFinalHarvest = () => {\n if (finalHarvestTriggered) return;\n finalHarvestTriggered = true;\n\n this.triggerHarvest({ isFinalHarvest: true, force: true });\n };\n\n // Handle page visibility changes\n document.addEventListener(\"visibilitychange\", () => {\n if (document.hidden) triggerFinalHarvest();\n });\n\n // Handle page unload\n window.addEventListener(\"pagehide\", () => {\n triggerFinalHarvest();\n });\n\n // Handle beforeunload as backup\n window.addEventListener(\"beforeunload\", () => {\n triggerFinalHarvest();\n });\n }\n}\n","import Log from \"./log\";\nimport { recordEvent } from \"./recordEvent\";\nimport { setVideoConfig } from \"./videoConfiguration\";\n\n/**\n * Static class that sums up core functionalities of the library.\n * @static\n */\nclass Core {\n /**\n * Add a tracker to the system. Trackers added will start reporting its events to the video analytics backend.\n *\n * @param {(Emitter|Tracker)} tracker Tracker instance to add.\n * @param {object} options Configuration options including video analytics settings.\n */\n static addTracker(tracker, options) {\n // Set video analytics configuration\n if (options?.info) {\n setVideoConfig(options.info);\n }\n \n if (tracker.on && tracker.emit) {\n trackers.push(tracker);\n tracker.on(\"*\", eventHandler);\n if (typeof tracker.trackerInit == \"function\") {\n tracker.trackerInit();\n }\n } else {\n Log.error(\"Tried to load a non-tracker.\", tracker);\n }\n }\n\n /**\n * Disposes and remove given tracker. Removes its listeners.\n *\n * @param {Tracker} tracker Tracker to remove.\n */\n static removeTracker(tracker) {\n tracker.off(\"*\", eventHandler);\n tracker.dispose();\n let index = trackers.indexOf(tracker);\n if (index !== -1) trackers.splice(index, 1);\n }\n\n /**\n * Returns the array of trackers.\n *\n * @returns {Tracker[]} Array of trackers.\n */\n static getTrackers() {\n return trackers;\n }\n\n /**\n * Enhanced send method with performance timing.\n * @param {string} eventType - Type of event\n * @param {string} actionName - Action name\n * @param {object} data - Event data\n */\n static send(eventType, actionName, data) {\n const enrichedData = {\n actionName,\n ...data,\n \n };\n \n return recordEvent(eventType, enrichedData);\n }\n\n /**\n * Sends an error event.\n * This may be used for external errors launched by the app, the network or\n * any external factor. Note that errors within the player are normally reported with\n * tracker.sendError, so this method should not be used to report those.\n *\n * @param {object} att attributes to be sent along the error.\n */\n static sendError(att) {\n return recordEvent(\"VideoErrorAction\", {\n actionName: \"ERROR\",\n ...att\n });\n }\n\n \n \n\n /**\n * Forces an immediate harvest of all pending events.\n * @returns {Promise<object>} Harvest result\n */\n static async forceHarvest() {\n try {\n const { videoAnalyticsHarvester } = require(\"./agent\"); // lazy loading for dynamic import\n return await videoAnalyticsHarvester.forceHarvest();\n } catch (error) {\n Log.error(\"Failed to force harvest:\", error.message);\n return { success: false, error: error.message };\n }\n }\n}\n\nlet trackers = [];\nlet isErrorShown = false;\n\n/**\n * Enhanced event handler with error handling and performance monitoring.\n *\n * @private\n * @param {Event} e Event\n */\nfunction eventHandler(e) {\n try {\n let data = cleanData(e.data);\n \n if (Log.level <= Log.Levels.DEBUG) {\n Log.notice(\"Sent\", e.type, data);\n } else {\n Log.notice(\"Sent\", e.type);\n }\n\n // Send event without priority discrimination\n Core.send(e.eventType, e.type, data);\n\n } catch (error) {\n Log.error(\"Error in event handler:\", error.message);\n }\n}\n\n/**\n * Cleans given object, removing all items with value === null.\n * @private\n * @param {Object} data Data to clean\n * @returns {Object} Cleaned object\n */\nfunction cleanData(data) {\n let ret = {};\n for (let i in data) {\n if (data[i] !== null && typeof data[i] !== \"undefined\") ret[i] = data[i];\n }\n return ret;\n}\n\nexport default Core;\n","import Log from \"./log\";\nimport { dataSize } from \"./utils\";\nimport Constants from \"./constants\";\n\nconst { MAX_PAYLOAD_SIZE, MAX_EVENTS_PER_BATCH } = Constants;\n\n/**\n * Retry Queue Handler for managing failed events with retry logic,\n * backoff strategies, and persistent storage capabilities.\n */\nexport class RetryQueueHandler {\n constructor() {\n this.retryQueue = [];\n this.maxQueueSize = MAX_EVENTS_PER_BATCH; // Max 1000 events\n this.maxQueueSizeBytes = MAX_PAYLOAD_SIZE; // Max 1MB\n }\n\n /**\n * Adds failed events to the retry queue for retry processing.\n * @param {Array|object} events - Failed event(s) to add to retry queue\n */\n addFailedEvents(events) {\n try {\n const eventsArray = Array.isArray(events) ? events : [events];\n\n Log.notice(`Adding ${eventsArray.length} failed events to retry queue`, {\n queueSizeBefore: this.retryQueue.length,\n });\n\n for (const event of eventsArray) {\n // Check queue size and make room if necessary\n if (this.retryQueue.length >= this.maxQueueSize) {\n this.evictOldestEvent();\n }\n\n // Check queue memory size and make room if necessary\n const eventSize = dataSize(event);\n while (dataSize(this.retryQueue) + eventSize > this.maxQueueSizeBytes) {\n this.evictOldestEvent();\n }\n\n // Store event directly - no wrapper needed\n this.retryQueue.push({ ...event });\n }\n } catch (err) {\n Log.error(\"Failed to add events to retry queue:\", err.message);\n }\n }\n\n /**\n * Discards an event that cannot be retried.\n * @param {object} event - Event to discard\n * @param {string} reason - Reason for discarding\n * @private\n */\n discardEvent(event, reason) {\n Log.warn(`Discarded event`, {\n reason,\n eventType: event.eventType,\n });\n }\n\n /**\n * Evicts the oldest event from the queue to make room.\n * @private\n */\n evictOldestEvent() {\n if (this.retryQueue.length > 0) {\n const oldest = this.retryQueue.shift();\n this.discardEvent(oldest, \"Queue full - evicted oldest\");\n }\n }\n\n /**\n * For unified harvesting - get retry events that fit within payload limits\n * Removes the selected events from the retry queue since they're being retried\n * @param {number} availableSpace - Available payload space in bytes\n * @param {number} availableEventCount - Available event count\n * @returns {Array} Array of events that fit within limits\n */\n getRetryEventsToFit(availableSpace, availableEventCount) {\n const retryEvents = [];\n let usedSpace = 0;\n let eventCount = 0;\n\n // Process retry queue in chronological order (oldest first) by iterating backwards\n // This allows us to remove elements immediately without index shifting issues\n for (let i = this.retryQueue.length - 1; i >= 0; i--) {\n const event = this.retryQueue[i]; // 1000\n\n if (eventCount >= availableEventCount) break;\n\n const eventSize = dataSize(event);\n if (usedSpace + eventSize > availableSpace) break;\n\n // Add to beginning of retryEvents to maintain chronological order (oldest first)\n retryEvents.unshift(event);\n usedSpace += eventSize;\n eventCount++;\n\n // Remove immediately - safe because we're iterating backwards\n this.retryQueue.splice(i, 1);\n }\n\n return retryEvents;\n }\n\n /**\n * Gets the current retry queue size.\n * @returns {number} Queue size\n */\n getQueueSize() {\n return this.retryQueue.length;\n }\n\n /**\n * Clears the retry queue.\n */\n clear() {\n this.retryQueue = [];\n }\n}\n\nexport default RetryQueueHandler;\n","import Log from \"./log\";\nimport Constants from \"./constants\";\nimport { dataSize } from \"./utils\";\n\nconst { MAX_PAYLOAD_SIZE, MAX_EVENTS_PER_BATCH } = Constants;\n\n/**\n * Enhanced event buffer that manages video events with unified priority handling\n * and automatic size management. All events are treated with equal priority\n * unless explicitly specified otherwise.\n */\nexport class NrVideoEventAggregator {\n constructor() {\n // Simplified to single priority queue for equal treatment\n\n this.buffer = [];\n this.maxPayloadSize = MAX_PAYLOAD_SIZE;\n this.maxEventsPerBatch = MAX_EVENTS_PER_BATCH;\n this.currentPayloadSize = 0;\n this.totalEvents = 0;\n\n // Dual threshold system - whichever is reached first triggers harvest\n // Payload size thresholds\n this.smartHarvestPayloadThreshold = Math.floor(this.maxPayloadSize * 0.6); // 60% of 1MB = 600KB\n this.overflowPayloadThreshold = Math.floor(this.maxPayloadSize * 0.9); // 90% of 1MB = 900KB\n\n // Event count thresholds\n this.smartHarvestEventThreshold = Math.floor(this.maxEventsPerBatch * 0.6); // 60% of 1000 = 600 events\n this.overflowEventThreshold = Math.floor(this.maxEventsPerBatch * 0.9); // 90% of 1000 = 900 events\n\n // Callback for triggering harvest\n this.onSmartHarvestTrigger = null;\n }\n\n /**\n * If an event with the specified actionName already exists in the buffer, it will be replaced.\n * Otherwise, the event will be added as a new entry.\n * @param {string} actionName - The actionName to search for in the buffer\n * @param {object} eventObject - The event object to add or use as replacement. Should contain an actionName property.\n * @returns {boolean} True if the operation succeeded, false if an error occurred\n */\n addOrReplaceByActionName(actionName, eventObject) {\n const i = this.buffer.findIndex(e => e.actionName === actionName);\n\n try {\n if(i === -1) {\n this.add(eventObject);\n } else {\n this.add(eventObject, i);\n }\n return true;\n } catch (error) {\n Log.error(\"Failed to set or replace the event to buffer:\", error.message);\n return false;\n }\n return false;\n }\n\n /**\n * Adds an event to the unified buffer.\n * All events are treated equally in FIFO order.\n * @param {object} eventObject - The event to add\n * @param {number} index - index at which the event should be replaced with\n */\n add(eventObject, index) {\n try {\n // Calculate event payload size\n const eventSize = dataSize(eventObject);\n\n // Check if we need to make room based on EITHER payload size OR event count limits\n const wouldExceedPayload =\n this.currentPayloadSize + eventSize >= this.maxPayloadSize;\n const wouldExceedEventCount =\n this.totalEvents + 1 >= this.maxEventsPerBatch;\n\n if (wouldExceedPayload || wouldExceedEventCount) {\n this.makeRoom(eventSize);\n }\n\n if(index !== undefined && index !== null && index > -1) {\n // replace in unified buffer\n const previousPayloadSize = dataSize(this.buffer[index]);\n this.buffer[index] = eventObject;\n // Updating the payload size for the replaced event\n this.currentPayloadSize += eventSize - previousPayloadSize;\n } else {\n // Add to unified buffer\n this.buffer.push(eventObject);\n this.totalEvents++;\n this.currentPayloadSize += eventSize;\n }\n\n // Check if smart harvest should be triggered\n this.checkSmartHarvestTrigger();\n\n return true;\n } catch (error) {\n Log.error(\"Failed to add event to buffer:\", error.message);\n return false;\n }\n }\n\n /**\n * Checks if smart harvest should be triggered based on dual threshold system.\n * Triggers when EITHER condition is met first:\n * - 60% of payload size (600KB) OR 60% of event count (600 events)\n * - 90% of payload size (900KB) OR 90% of event count (900 events)\n * @private\n */\n checkSmartHarvestTrigger() {\n const payloadPercentage = this.currentPayloadSize / this.maxPayloadSize;\n const eventPercentage = this.totalEvents / this.maxEventsPerBatch;\n\n // Check 90% emergency thresholds first (either payload OR event count)\n const isPayloadOverflowReached =\n this.currentPayloadSize >= this.overflowPayloadThreshold;\n const isEventOverflowReached =\n this.totalEvents >= this.overflowEventThreshold;\n\n if (isPayloadOverflowReached || isEventOverflowReached) {\n const triggerReason = isPayloadOverflowReached\n ? `payload ${this.currentPayloadSize}/${\n this.maxPayloadSize\n } bytes (${Math.round(payloadPercentage * 100)}%)`\n : `events ${this.totalEvents}/${this.maxEventsPerBatch} (${Math.round(\n eventPercentage * 100\n )}%)`;\n\n Log.warn(\n `OVERFLOW PREVENTION: ${triggerReason} - Emergency harvest triggered`\n );\n\n if (\n this.onSmartHarvestTrigger &&\n typeof this.onSmartHarvestTrigger === \"function\"\n ) {\n // Trigger immediate emergency harvest\n this.onSmartHarvestTrigger(\"overflow\", 90);\n }\n }\n\n // Check 60% smart harvest thresholds (either payload OR event count)\n else {\n const isPayloadSmartReached =\n this.currentPayloadSize >= this.smartHarvestPayloadThreshold;\n const isEventSmartReached =\n this.totalEvents >= this.smartHarvestEventThreshold;\n\n if (isPayloadSmartReached || isEventSmartReached) {\n if (\n this.onSmartHarvestTrigger &&\n typeof this.onSmartHarvestTrigger === \"function\"\n ) {\n // Trigger proactive harvest\n this.onSmartHarvestTrigger(\"smart\", 60);\n }\n }\n }\n }\n\n /**\n * Sets the callback function for smart harvest triggers.\n * @param {Function} callback - Function to call when smart harvest is triggered\n */\n setSmartHarvestCallback(callback) {\n this.onSmartHarvestTrigger = callback;\n }\n\n /**\n * Drains all events from the buffer in FIFO order (first in, first out).\n * No limits needed since buffer already manages size via makeRoom() and smart harvest triggers.\n * @returns {Array} Array of events in order they were added\n */\n drain() {\n try {\n // Drain ALL events - buffer size is already managed by makeRoom() and smart harvest\n const events = this.buffer.splice(0);\n\n // Reset counters since buffer is now empty\n this.totalEvents = 0;\n this.currentPayloadSize = 0;\n\n return events;\n } catch (error) {\n Log.error(\"Failed to drain events from buffer:\", error.message);\n return [];\n }\n }\n\n /**\n * Checks if the buffer is empty.\n * @returns {boolean} True if all buffers are empty\n */\n isEmpty() {\n return this.totalEvents === 0;\n }\n\n /**\n * Gets the total number of events across all buffers.\n * @returns {number} Total event count\n */\n size() {\n return this.totalEvents;\n }\n\n /**\n * Clears the entire buffer.\n */\n clear() {\n this.buffer = [];\n this.totalEvents = 0;\n }\n\n /**\n * Makes room in the buffer by removing the oldest event.\n * Uses FIFO approach - removes the first (oldest) event.\n * @private\n */\n makeRoom(newEventSize) {\n // Before the while loop in makeRoom()\n if (newEventSize > this.maxPayloadSize) {\n Log.error(\"Event dropped: Event size exceeds maximum payload size.\");\n return; // Exit the function to prevent infinite loop\n }\n\n // Keep a loop to evict events until we meet ALL conditions for the new event\n while (\n // Condition 1: Exceeding max event count\n this.totalEvents >= this.maxEventsPerBatch ||\n // Condition 2: Exceeding max payload size\n this.currentPayloadSize + newEventSize >= this.maxPayloadSize\n ) {\n if (this.buffer.length > 0) {\n const removed = this.buffer.shift(); // Remove the oldest event (FIFO)\n\n // Recalculate size and count after removal\n const removedSize = dataSize(removed);\n this.totalEvents--;\n this.currentPayloadSize -= removedSize;\n\n // Optional: Log a warning for a dropped event\n Log.warn(\"Event buffer full, oldest event removed.\");\n } else {\n // Buffer is somehow empty, but conditions were met. Break the loop.\n break;\n }\n }\n }\n}\n\nexport default NrVideoEventAggregator;\n","import { videoAnalyticsHarvester } from \"./agent.js\";\nimport Constants from \"./constants.js\";\nimport Log from \"./log.js\";\nimport Tracker from \"./tracker\";\nimport {getObjectEntriesForKeys} from \"./utils\";\n\n/**\n * Enhanced record event function with validation, enrichment, and unified handling.\n * @param {string} eventType - Type of event to record\n * @param {object} attributes - Event attributes\n */\nexport function recordEvent(eventType, attributes = {}) {\n try {\n // Validate event type\n if (!Constants.VALID_EVENT_TYPES.includes(eventType)) {\n Log.warn(\"Invalid event type provided to recordEvent\", { eventType });\n return false;\n }\n\n // Get app configuration\n\n if (!window?.NRVIDEO?.info) return;\n\n const { appName, applicationID } = window.NRVIDEO.info;\n\n const { qoe, ...eventAttributes } = attributes;\n const qoeAttrs = qoe ? { ...qoe } : {};\n\n const otherAttrs = {\n ...(applicationID ? {} : { appName }), // Only include appName when no applicationID\n timestamp: Date.now(),\n timeSinceLoad: window.performance\n ? window.performance.now() / 1000\n : null,\n }\n\n const eventObject = {\n ...eventAttributes,\n eventType,\n ...otherAttrs,\n };\n\n const metadataAttributes = getObjectEntriesForKeys(Constants.QOE_AGGREGATE_KEYS, attributes)\n\n let qoeEventObject = null;\n if(eventType === \"VideoAction\") {\n qoeEventObject = {\n eventType: \"VideoAction\",\n actionName: Tracker.Events.QOE_AGGREGATE,\n qoeAggregateVersion: '1.0.0',\n ...qoeAttrs,\n ...metadataAttributes,\n ...otherAttrs,\n }\n }\n\n // Send to video analytics harvester\n const success = videoAnalyticsHarvester.addEvent(eventObject);\n\n if(qoeEventObject) {\n const successQoe = videoAnalyticsHarvester.addEvent(qoeEventObject);\n return success && successQoe;\n }\n\n return success;\n } catch (error) {\n Log.error(\"Failed to record event:\", error.message);\n return false;\n }\n}\n","/**\n * This class calculates time lapses between two points on time.\n */\nclass Chrono {\n /**\n * Constructor\n */\n constructor() {\n this.reset();\n }\n\n /** Reset chrono values. */\n reset() {\n /** Start time */\n this.startTime = 0;\n\n /** Stop time */\n this.stopTime = 0;\n\n /** accumulation of all the start and stop intervals */\n this.accumulator = 0;\n\n /**\n * If you set an offset in a chrono, its value will be added getDeltaTime and stop.\n *\n * @example\n * let chrono = new Chrono()\n * chrono.offset = 500\n * chrono.start()\n * process.sleep(500)\n * chrono.stop() // Will return 1000\n *\n * @type {number}\n */\n this.offset = 0;\n }\n\n /**\n * Returns the time between start() and the last stop() in ms. Returns null if start wasn't\n * called.\n * @return {(number|null)} Time lapse in ms.\n */\n getDeltaTime() {\n if (this.startTime) {\n return this.offset + (new Date().getTime() - this.startTime);\n } else {\n return null;\n }\n }\n\n /**\n * Starts the chrono.\n */\n start() {\n this.startTime = new Date().getTime();\n this.stopTime = 0;\n }\n\n /**\n * Stops the timer and returns delta time.\n * @return {(number|null)} Returns the delta time\n */\n stop() {\n this.stopTime = new Date().getTime();\n if(this.startTime < this.stopTime) {\n this.accumulator += (this.stopTime - this.startTime);\n }\n return this.getDeltaTime();\n }\n\n getDuration() {\n if(this.stopTime) {\n return this.accumulator + this.offset;\n } else {\n return this.accumulator + (this.getDeltaTime() ?? 0)\n }\n }\n\n /**\n * Creates a copy of the chrono.\n * @returns {Chrono} Cloned chrono\n */\n clone() {\n var chrono = new Chrono();\n chrono.startTime = this.startTime;\n chrono.stopTime = this.stopTime;\n chrono.offset = this.offset;\n chrono.accumulator = this.accumulator;\n return chrono;\n }\n}\n\nexport default Chrono;\n","import { HarvestScheduler } from \"./harvestScheduler.js\";\nimport { NrVideoEventAggregator } from \"./eventAggregator.js\";\nimport Log from \"./log.js\";\nimport Tracker from \"./tracker\";\n\n/**\n * Enhanced video analytics agent with HarvestScheduler only.\n */\nclass VideoAnalyticsAgent {\n constructor() {\n this.isInitialized = false;\n this.harvestScheduler = null;\n this.eventBuffer = null;\n }\n\n /**\n * Initializes the video analytics agent with enhanced HarvestScheduler.\n */\n initialize() {\n if (this.isInitialized) {\n Log.warn(\"Video analytics agent already initialized\");\n return;\n }\n\n try {\n this.eventBuffer = new NrVideoEventAggregator();\n this.harvestScheduler = new HarvestScheduler(this.eventBuffer);\n\n // Start the enhanced harvest scheduler\n this.harvestScheduler.startScheduler();\n\n this.isInitialized = true;\n Log.notice(\"Video analytics agent initialized successfully\");\n } catch (error) {\n Log.error(\"Failed to initialize video analytics agent:\", error.message);\n }\n }\n\n /**\n * Adds an event to the harvesting system.\n * @param {object} eventObject - Event to add\n * @returns {boolean} True if event was added successfully\n */\n addEvent(eventObject) {\n if (!this.isInitialized) {\n Log.warn(\"Video analytics agent not initialized, initializing now\");\n this.initialize();\n }\n\n try {\n if(eventObject.actionName && eventObject.actionName === Tracker.Events.QOE_AGGREGATE) {\n // This makes sure that there is only one QOE aggregate event for a harvest cycle\n return this.eventBuffer.addOrReplaceByActionName(Tracker.Events.QOE_AGGREGATE, eventObject);\n }\n return this.eventBuffer.add(eventObject);\n } catch (error) {\n Log.error(\"Failed to add event to harvesting system:\", error.message);\n return false;\n }\n }\n\n /**\n * Sets the harvest interval for the scheduler.\n * @param {number} interval - The harvest interval in milliseconds.\n */\n\n setHarvestInterval(interval) {\n if (!this.isInitialized) {\n this.initialize();\n }\n\n this.harvestScheduler.updateHarvestInterval(interval);\n }\n}\n\n// Create singleton instance\nconst videoAnalyticsAgent = new VideoAnalyticsAgent();\n\n// Enhanced video analytics harvester\nexport const videoAnalyticsHarvester = videoAnalyticsAgent;\n","/**\n * This base class implements a basic behavior of listeners and events. Extend this object to have\n * this feature built-in inside your classes.\n *\n * @class Emitter\n */\nclass Emitter {\n /**\n * Sets a listener to a given event. Use {@link emit} to trigger those events.\n * Pass '*' to listen ALL events.\n *\n * @param {string} event Name of the event.\n * @param {function} callback Callback of the event. Receives event and data.\n * @return this\n */\n on(event, callback) {\n this._listeners = this._listeners || {};\n if (typeof callback === \"function\") {\n this._listeners[event] = this._listeners[event] || [];\n this._listeners[event].push(callback);\n return this;\n }\n }\n\n /**\n * Removes given callback from the listeners of this object.\n *\n * @param {string} event Name of the event.\n * @param {function} callback Callback of the event.\n * @return this\n */\n off(event, callback) {\n this._listeners = this._listeners || {};\n\n if (this._listeners[event]) {\n var index = this._listeners[event].indexOf(callback);\n if (index !== -1) {\n this._listeners[event].splice(index, 1);\n }\n }\n return this;\n }\n\n /**\n * Emits given event, triggering all the associated callbacks.\n *\n * @param {string} event Name of the event.\n * @param {object} [data] Custom data to be sent to the callbacks.\n * @return this\n */\n emit(eventType, event, data) {\n this._listeners = this._listeners || {};\n data = data || {};\n\n if (Array.isArray(this._listeners[event])) {\n this._listeners[event].forEach((callback) => {\n callback.call(this, {\n eventType,\n type: event,\n data: data,\n target: this,\n });\n });\n }\n\n if (Array.isArray(this._listeners[\"*\"])) {\n this._listeners[\"*\"].forEach((callback) => {\n callback.call(this, {\n eventType,\n type: event,\n data: data,\n target: this,\n });\n });\n }\n\n return this;\n }\n}\n\nexport default Emitter;\n","import Log from \"./log\";\nimport Constants from \"./constants\";\n\nconst { COLLECTOR } = Constants;\n\n/**\n * Enhanced video analytics configuration system that extends the existing auth configuration.\n * Provides feature flags, retry policies, and advanced harvesting options.\n */\nclass VideoConfiguration {\n /**\n * Validates and sets the video analytics configuration.\n * @param {object} userConfig - User provided configuration\n * @returns {boolean} True if configuration is valid and set\n */\n\n setConfiguration(userInfo) {\n this.initializeGlobalConfig(userInfo);\n Log.notice(\"Video analytics configuration initialized successfully\");\n return true;\n }\n\n /**\n * Validates required configuration fields.\n * @param {object} config - Configuration to validate\n * @returns {boolean} True if valid\n */\n validateRequiredFields(info) {\n if (!info || typeof info !== \"object\") {\n Log.error(\"Configuration must be an object\");\n return false;\n }\n\n const { licenseKey, appName, region, applicationID, beacon } = info;\n\n if (!licenseKey) {\n Log.error(\"licenseKey is required\");\n return false;\n }\n\n if (applicationID) {\n if (!beacon) {\n Log.error(\"beacon is required when applicationID is provided\");\n return false;\n } else {\n const validBeacons = Object.values(COLLECTOR).flatMap((el) => el);\n if (!validBeacons.includes(beacon)) {\n Log.error(`Invalid beacon: ${beacon}`);\n return false;\n }\n }\n } else {\n if (!appName || !region) {\n Log.error(\n \"appName and region are required when applicationID is not provided\"\n );\n return false;\n }\n\n if (!COLLECTOR[region]) {\n Log.error(\n `Invalid region: ${region}. Valid regions are: ${Object.keys(\n COLLECTOR\n ).join(\", \")}`\n );\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Initializes the global NRVIDEO configuration object.\n */\n initializeGlobalConfig(userInfo) {\n if (!this.validateRequiredFields(userInfo)) return;\n\n let { licenseKey, appName, region, beacon, applicationID } = userInfo;\n\n if (region === \"US\") {\n beacon = Constants.COLLECTOR[\"US\"][0];\n } else {\n beacon = beacon || COLLECTOR[region];\n }\n\n window.NRVIDEO = {\n // Existing format for backward compatibility\n info: {\n ...(region ? { region } : {}), // Only include region if available\n beacon,\n licenseKey,\n applicationID,\n ...(applicationID ? {} : { appName }), // Only include appName when no applicationID\n },\n };\n }\n}\n\n// Create singleton instance\nconst videoConfiguration = new VideoConfiguration();\n\n/**\n * Sets the video analytics configuration.\n * @param {object} config - Configuration object\n * @returns {boolean} True if configuration was set successfully\n */\nexport function setVideoConfig(info) {\n return videoConfiguration.setConfiguration(info);\n}\n\nexport { videoConfiguration };\nexport default VideoConfiguration;\n","import Log from \"./log\";\nimport Tracker from \"./tracker\";\nimport TrackerState from \"./videotrackerstate\";\nimport pkg from \"../package.json\";\n\n/**\n * Base video tracker class provides extensible tracking over video elements. See {@link Tracker}.\n * Extend this class to create your own video tracker class. Override getter methods and\n * registerListeners/unregisterListeners to provide full integration with your video experience.\n *\n * @example\n * Tracker instances should be added to Core library to start sending data:\n * nrvideo.Core.addTracker(new Tracker())\n *\n * @extends Tracker\n */\nclass VideoTracker extends Tracker {\n /**\n * Constructor, receives player and options.\n * Lifecycle: constructor > {@link setOptions} > {@link setPlayer} > {@link registerListeners}.\n *\n * @param {Object} [player] Player to track. See {@link setPlayer}.\n * @param {Object} [options] Options for the tracker. See {@link setOptions}.\n */\n constructor(player, options) {\n super();\n\n /**\n * TrackerState instance. Stores the state of the view. Tracker will automatically update the\n * state of its instance, so there's no need to modify/interact with it manually.\n * @type TrackerState\n */\n this.state = new TrackerState();\n\n /**\n * Another Tracker instance to track ads.\n * @type Tracker\n */\n this.adsTracker = null;\n\n /**\n * Last bufferType value.\n * @private\n */\n this._lastBufferType = null;\n this._userId = null;\n\n options = options || {};\n this.setOptions(options);\n if (player) this.setPlayer(player, options.tag);\n\n Log.notice(\n \"Tracker \" +\n this.getTrackerName() +\n \" v\" +\n this.getTrackerVersion() +\n \" is ready.\"\n );\n }\n\n /* user can set the user Id */\n\n setUserId(userId) {\n this._userId = userId;\n }\n\n /**\n * Set options for the Tracker.\n *\n * @param {Object} [options] Options for the tracker.\n * @param {Boolean} [options.isAd] True if the tracker is tracking ads. See {@link setIsAd}.\n * @param {number} [options.heartbeat] Set time between heartbeats. See {@link heartbeat}.\n * @param {Object} [options.customData] Set custom data. See {@link customData}.\n * @param {Tracker} [options.parentTracker] Set parent tracker. See {@link parentTracker}.\n * @param {Tracker} [options.adsTracker] Set ads tracker. See {@link adsTracker}.\n * @param {Object} [options.tag] DOM element to track. See {@link setPlayer}.\n */\n setOptions(options) {\n if (options) {\n if (options.adsTracker) {\n this.setAdsTracker(options.adsTracker);\n }\n if (typeof options.isAd === \"boolean\") {\n this.setIsAd(options.isAd);\n }\n Tracker.prototype.setOptions.apply(this, arguments);\n }\n }\n\n /**\n * Set a player and/or a tag. If there was one already defined, it will call dispose() first.\n * Will call this.registerListeners() afterwards.\n *\n * @param {Object|string} player New player to save as this.player. If a string is passed,\n * document.getElementById will be called.\n * @param {DOMObject|string} [tag] Optional DOMElement to save as this.tag. If a string is passed,\n * document.getElementById will be called.\n */\n\n setPlayer(player, tag) {\n if (this.player || this.tag) this.dispose();\n\n if (typeof document !== \"undefined\" && document.getElementById) {\n if (typeof player === \"string\") player = document.getElementById(player);\n if (typeof tag === \"string\") tag = document.getElementById(tag);\n }\n\n tag = tag || player; // if no tag is passed, use player as both.\n\n this.player = player;\n this.tag = tag;\n this.registerListeners();\n }\n\n /** Returns true if the tracker is currently on ads. */\n isAd() {\n return this.state.isAd();\n }\n\n /** Sets if the tracker is currenlty tracking ads */\n setIsAd(isAd) {\n this.state.setIsAd(isAd);\n }\n\n /**\n * Use this function to set up a child ad tracker. You will be able to access it using\n * this.adsTracker.\n *\n * @param {Tracker} tracker Ad tracker to add\n */\n setAdsTracker(tracker) {\n this.disposeAdsTracker(); // dispose current one\n if (tracker) {\n this.adsTracker = tracker;\n this.adsTracker.setIsAd(true);\n this.adsTracker.parentTracker = this;\n this.adsTracker.on(\"*\", funnelAdEvents.bind(this));\n }\n }\n\n /**\n * Dispose current adsTracker.\n */\n disposeAdsTracker() {\n if (this.adsTracker) {\n this.adsTracker.off(\"*\", funnelAdEvents);\n this.adsTracker.dispose();\n }\n }\n\n /**\n * Prepares tracker to dispose. Calls unregisterListener and drops references to player and tag.\n */\n dispose() {\n this.stopHeartbeat();\n this.disposeAdsTracker();\n this.unregisterListeners();\n this.player = null;\n this.tag = null;\n }\n\n /**\n * Override this method to register listeners to player/tag.\n * @example\n * class SpecificTracker extends Tracker {\n * registerListeners() {\n * this.player.on('play', () => this.playHandler)\n * }\n *\n * playHandler() {\n * this.send(VideoTracker.Events.REQUESTED)\n * }\n * }\n */\n registerListeners() {}\n\n /**\n * Override this method to unregister listeners to player/tag created in registerListeners\n * @example\n * class SpecificTracker extends Tracker {\n * registerListeners() {\n * this.player.on('play', () => this.playHandler)\n * }\n *\n * unregisterListeners() {\n * this.player.off('play', () => this.playHandler)\n * }\n *\n * playHandler() {\n * this.send(VideoTracker.Events.REQUESTED)\n * }\n * }\n */\n unregisterListeners() {}\n\n /**\n * Trackers will generate unique id's for every new video iteration. If you have your own unique\n * view value, you can override this method to return it.\n * If the tracker has a parentTracker defined, parent viewId will be used.\n */\n getViewId() {\n if (this.parentTracker) {\n return this.parentTracker.getViewId();\n } else {\n return this.state.getViewId();\n }\n }\n\n /**\n * Trackers will generate unique id's for every new video session. If you have your own unique\n * view value, you can override this method to return it.\n * If the tracker has a parentTracker defined, parent viewId will be used.\n */\n getViewSession() {\n if (this.parentTracker) {\n return this.parentTracker.getViewSession();\n } else {\n return this.state.getViewSession();\n }\n }\n\n /** Override to return the Id of the video. */\n getVideoId() {\n return null;\n }\n\n /** Override to return Title of the video. */\n getTitle() {\n return null;\n }\n\n /** Override to return True if the video is live. */\n isLive() {\n return null;\n }\n\n /** Override to return Bitrate (in bits) of the video. */\n getBitrate() {\n return null;\n }\n\n /** Calculates consumed bitrate using webkitVideoDecodedByteCount. */\n getWebkitBitrate() {\n if (this.tag && this.tag.webkitVideoDecodedByteCount) {\n let bitrate;\n if (this._lastWebkitBitrate) {\n bitrate = this.tag.webkitVideoDecodedByteCount;\n let delta = bitrate - this._lastWebkitBitrate;\n let seconds = this.getHeartbeat() / 1000;\n bitrate = Math.round((delta / seconds) * 8);\n }\n this._lastWebkitBitrate = this.tag.webkitVideoDecodedByteCount;\n return bitrate || null;\n }\n }\n\n /** Override to return Name of the rendition (ie: 1080p). */\n getRenditionName() {\n return null;\n }\n\n /** Override to return Target Bitrate of the rendition. */\n getRenditionBitrate() {\n return null;\n }\n\n /**\n * This method will return 'up', 'down' or null depending on if the bitrate of the rendition\n * have changed from the last time it was called.\n *\n * @param {boolean} [saveNewRendition=false] If true, current rendition will be stored to be used\n * the next time this method is called. This allows you to call this.getRenditionShift() without\n * saving the current rendition and thus preventing interferences with RENDITION_CHANGE events.\n */\n getRenditionShift(saveNewRendition) {\n let current = this.getRenditionBitrate();\n let last;\n if (this.isAd()) {\n last = this._lastAdRendition;\n if (saveNewRendition) this._lastAdRendition = current;\n } else {\n last = this._lastRendition;\n if (saveNewRendition) this._lastRendition = current;\n }\n\n if (!current || !last) {\n return null;\n } else {\n if (current > last) {\n return \"up\";\n } else if (current < last) {\n return \"down\";\n } else {\n return null;\n }\n }\n }\n\n /** Override to return renidtion actual Height (before re-scaling). */\n getRenditionHeight() {\n return this.tag ? this.tag.videoHeight : null;\n }\n\n /** Override to return rendition actual Width (before re-scaling). */\n getRenditionWidth() {\n return this.tag ? this.tag.videoWidth : null;\n }\n\n /** Override to return Duration of the video, in ms. */\n getDuration() {\n return this.tag ? this.tag.duration : null;\n }\n\n /** Override to return Playhead (currentTime) of the video, in ms. */\n getPlayhead() {\n return this.tag ? this.tag.currentTime : null;\n }\n\n /**\n * Override to return Language of the video. We recommend using locale notation, ie: en_US.\n * {@see https://gist.github.com/jacobbubu/1836273}\n */\n getLanguage() {\n return null;\n }\n\n /** Override to return URL of the resource being played. */\n getSrc() {\n return this.tag ? this.tag.currentSrc : null;\n }\n\n /** Override to return Playrate (speed) of the video. ie: 1.0, 0.5, 1.25... */\n getPlayrate() {\n return this.tag ? this.tag.playbackRate : null;\n }\n\n /** Override to return True if the video is currently muted. */\n isMuted() {\n return this.tag ? this.tag.muted : null;\n }\n\n /** Override to return True if the video is currently fullscreen. */\n isFullscreen() {\n return null;\n }\n\n /** Override to return the CDN serving the content. */\n getCdn() {\n return null;\n }\n\n /** Override to return the Name of the player. */\n getPlayerName() {\n return this.getTrackerName();\n }\n\n /** Override to return the Version of the player. */\n getPlayerVersion() {\n return pkg.version;\n }\n\n /** Override to return current FPS (Frames per second). */\n getFps() {\n return null;\n }\n\n /**\n * Override to return if the player was autoplayed. By default: this.tag.autoplay\n */\n isAutoplayed() {\n return this.tag ? this.tag.autoplay : null;\n }\n\n /**\n * Override to return the player preload attribute. By default: this.tag.preload\n */\n getPreload() {\n return this.tag ? this.tag.preload : null;\n }\n\n // Only for ads\n /**\n * Override to return Quartile of the ad. 0 before first, 1 after first quartile, 2 after\n * midpoint, 3 after third quartile, 4 when completed.\n */\n getAdQuartile() {\n return null;\n }\n\n /**\n * Override to return the position of the ad. Use {@link Constants.AdPositions} enum\n * to fill this data.\n */\n getAdPosition() {\n if (this.parentTracker) {\n return this.parentTracker.state.isStarted ? \"mid\" : \"pre\";\n } else {\n return null;\n }\n }\n\n /**\n * Override to return the ad partner. ie: ima, freewheel...\n */\n getAdPartner() {\n return null;\n }\n\n /**\n * Override to return the creative id of the ad.\n */\n getAdCreativeId() {\n return null;\n }\n\n /**\n * Override to return the instrumentation of the player.\n */\n\n getInstrumentationProvider() {\n return null;\n }\n\n getInstrumentationName() {\n return null;\n }\n\n getInstrumentationVersion() {\n return null;\n }\n\n /**\n * Do NOT override. This method fills all the appropiate attributes for tracked video.\n *\n * @param {object} [att] Collection of key value attributes\n * @return {object} Filled attributes\n * @final\n */\n getAttributes(att, type) {\n att = Tracker.prototype.getAttributes.apply(this, arguments);\n\n if (typeof att.isAd === \"undefined\") att.isAd = this.isAd();\n\n att.viewSession = this.getViewSession();\n att.viewId = this.getViewId();\n att.playerName = this.getPlayerName();\n att.playerVersion = this.getPlayerVersion();\n att[\"instrumentation.provider\"] = this.getInstrumentationProvider();\n att[\"instrumentation.name\"] = this.getInstrumentationName();\n att[\"instrumentation.version\"] = this.getInstrumentationVersion();\n att[\"enduser.id\"] = this._userId;\n att[\"src\"] = \"Browser\";\n\n if (type === \"customAction\") return att;\n\n try {\n att.pageUrl = window.location.href;\n } catch (err) {\n /* skip */\n }\n\n if (this.isAd()) {\n // Ads\n att.adId = this.getVideoId();\n att.adTitle = this.getTitle();\n att.adSrc = this.getSrc();\n att.adCdn = this.getCdn();\n att.adBitrate =\n this.getBitrate() ||\n this.getWebkitBitrate() ||\n this.getRenditionBitrate();\n att.adRenditionName = this.getRenditionName();\n att.adRenditionBitrate = this.getRenditionBitrate();\n att.adRenditionHeight = this.getRenditionHeight();\n att.adRenditionWidth = this.getRenditionWidth();\n att.adDuration = this.getDuration();\n att.adPlayhead = this.getPlayhead();\n att.adLanguage = this.getLanguage();\n att.adIsMuted = this.isMuted();\n att.adFps = this.getFps();\n // ad exclusives\n //att.adQuartile = this.getAdQuartile();\n att.adPosition = this.getAdPosition();\n att.adCreativeId = this.getAdCreativeId();\n att.adPartner = this.getAdPartner();\n } else {\n // no ads\n att.contentId = this.getVideoId();\n att.contentTitle = this.getTitle();\n att.contentSrc = this.getSrc();\n att.contentCdn = this.getCdn();\n att.contentPlayhead = this.getPlayhead();\n\n att.contentIsLive = this.isLive();\n att.contentBitrate =\n this.getBitrate() ||\n this.getWebkitBitrate() ||\n this.getRenditionBitrate();\n\n att.contentRenditionName = this.getRenditionName();\n att.contentRenditionBitrate = this.getRenditionBitrate();\n att.contentRenditionHeight = this.getRenditionHeight();\n att.contentRenditionWidth = this.getRenditionWidth();\n att.contentDuration = this.getDuration();\n\n att.contentLanguage = this.getLanguage();\n att.contentPlayrate = this.getPlayrate();\n att.contentIsFullscreen = this.isFullscreen();\n att.contentIsMuted = this.isMuted();\n att.contentIsAutoplayed = this.isAutoplayed();\n att.contentPreload = this.getPreload();\n att.contentFps = this.getFps();\n\n if (\n this.adsTracker != null &&\n this.adsTracker.state.totalAdPlaytime > 0\n ) {\n att.totalAdPlaytime = this.adsTracker.state.totalAdPlaytime;\n }\n }\n\n this.state.getStateAttributes(att);\n\n if(this.state.isStarted && !this.isAd()) {\n this.state.trackContentBitrateState(att.contentBitrate);\n }\n\n for (let key in this.customData) {\n att[key] = this.customData[key];\n }\n\n /**\n * Adds all the attributes and custom attributes for qoe event\n */\n this.addQoeAttributes(att);\n\n return att;\n }\n\n addQoeAttributes(att) {\n att = this.state.getQoeAttributes(att);\n const qoe = att.qoe;\n for (let key in this.customData) {\n qoe[key] = this.customData[key];\n }\n }\n\n /**\n * Sends custom event and registers a timeSince attribute.\n * @param {Object} [actionName] Custom action name.\n * @param {Object} [timeSinceAttName] Custom timeSince attribute name.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendCustom(actionName, timeSinceAttName, att) {\n att = att || {};\n this.sendVideoCustomAction(actionName, att);\n this.state.setTimeSinceAttribute(timeSinceAttName);\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendPlayerReady(att) {\n if (this.state.goPlayerReady()) {\n att = att || {};\n this.sendVideoAction(VideoTracker.Events.PLAYER_READY, att);\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners. Calls\n * {@link startHeartbeat}.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendRequest(att) {\n if (this.state.goRequest()) {\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_REQUEST;\n this.sendVideoAdAction(ev, att);\n } else {\n ev = VideoTracker.Events.CONTENT_REQUEST;\n this.sendVideoAction(ev, att);\n }\n\n // this.startHeartbeat();\n // this.state.goHeartbeat();\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendStart(att) {\n if (this.state.goStart()) {\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_START;\n if (this.parentTracker) this.parentTracker.state.isPlaying = false;\n this.sendVideoAdAction(ev, att);\n this.state.startAdsTime();\n } else {\n ev = VideoTracker.Events.CONTENT_START;\n let totalAdsTime = 0;\n if(this.adsTracker) {\n // If ads state is set to playing (ad error) after content start, reset the ad state.\n if(this.adsTracker.state.isPlaying || this.adsTracker.state.isBuffering) {\n totalAdsTime = this.adsTracker.state.stopAdsTime();\n this.adsTracker.state.isPlaying = false;\n this.adsTracker.state.isBuffering = false;\n } else {\n totalAdsTime = this.adsTracker.state.totalAdTime() ?? 0;\n }\n }\n this.state.setStartupTime(totalAdsTime)\n this.sendVideoAction(ev, att);\n }\n //this.send(ev, att);\n this.startHeartbeat();\n this.state.goHeartbeat();\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners. Calls\n * {@link stopHeartbeat}.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendEnd(att) {\n if (this.state.goEnd()) {\n att = att || {};\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_END;\n att.timeSinceAdRequested = this.state.timeSinceRequested.getDeltaTime();\n att.timeSinceAdStarted = this.state.timeSinceStarted.getDeltaTime();\n if (this.parentTracker) this.parentTracker.state.isPlaying = true;\n this.state.stopAdsTime();\n } else {\n ev = VideoTracker.Events.CONTENT_END;\n att.timeSinceRequested = this.state.timeSinceRequested.getDeltaTime();\n att.timeSinceStarted = this.state.timeSinceStarted.getDeltaTime();\n }\n this.stopHeartbeat();\n //this.send(ev, att);\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n\n if (this.parentTracker && this.isAd())\n this.parentTracker.state.goLastAd();\n this.state.goViewCountUp();\n this.state.totalPlaytime = 0;\n if(!this.isAd()) {\n // reset the states after the view count is up\n if(this.adsTracker) this.adsTracker.state.clearTotalAdsTime();\n this.state.resetViewIdTrackedState();\n }\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendPause(att) {\n if (this.state.goPause()) {\n let ev = this.isAd()\n ? VideoTracker.Events.AD_PAUSE\n : VideoTracker.Events.CONTENT_PAUSE;\n\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n\n //this.send(ev, att);\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendResume(att) {\n if (this.state.goResume()) {\n att = att || {};\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_RESUME;\n att.timeSinceAdPaused = this.state.timeSincePaused.getDeltaTime();\n } else {\n ev = VideoTracker.Events.CONTENT_RESUME;\n att.timeSincePaused = this.state.timeSincePaused.getDeltaTime();\n }\n //this.send(ev, att);\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendBufferStart(att) {\n if (this.state.goBufferStart()) {\n att = att || {};\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_BUFFER_START;\n } else {\n ev = VideoTracker.Events.CONTENT_BUFFER_START;\n }\n\n att = this.buildBufferAttributes(att);\n this._lastBufferType = att.bufferType;\n\n //this.send(ev, att);\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendBufferEnd(att) {\n if (this.state.goBufferEnd()) {\n att = att || {};\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_BUFFER_END;\n att.timeSinceAdBufferBegin =\n this.state.timeSinceBufferBegin.getDeltaTime();\n } else {\n ev = VideoTracker.Events.CONTENT_BUFFER_END;\n att.timeSinceBufferBegin =\n this.state.timeSinceBufferBegin.getDeltaTime();\n }\n\n att = this.buildBufferAttributes(att);\n // Set the bufferType attribute of the last BUFFER_START\n if (this._lastBufferType != null) {\n att.bufferType = this._lastBufferType;\n }\n\n // this.send(ev, att);\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n this.state.initialBufferingHappened = true;\n }\n }\n\n buildBufferAttributes(att) {\n if (att.timeSinceStarted == undefined || att.timeSinceStarted < 100) {\n att.isInitialBuffering = !this.state.initialBufferingHappened;\n } else {\n att.isInitialBuffering = false;\n }\n\n att.bufferType = this.state.calculateBufferType(att.isInitialBuffering);\n\n att.timeSinceResumed = this.state.timeSinceResumed.getDeltaTime();\n att.timeSinceSeekEnd = this.state.timeSinceSeekEnd.getDeltaTime();\n\n return att;\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendSeekStart(att) {\n if (this.state.goSeekStart()) {\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_SEEK_START;\n } else {\n ev = VideoTracker.Events.CONTENT_SEEK_START;\n }\n // this.send(ev, att);\n\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendSeekEnd(att) {\n if (this.state.goSeekEnd()) {\n att = att || {};\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_SEEK_END;\n att.timeSinceAdSeekBegin = this.state.timeSinceSeekBegin.getDeltaTime();\n } else {\n ev = VideoTracker.Events.CONTENT_SEEK_END;\n att.timeSinceSeekBegin = this.state.timeSinceSeekBegin.getDeltaTime();\n }\n // this.send(ev, att);\n\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n * @param {String} att.state Download requires a string to distinguish different states.\n */\n sendDownload(att) {\n att = att || {};\n if (!att.state) Log.warn(\"Called sendDownload without { state: xxxxx }.\");\n this.sendVideoAction(VideoTracker.Events.DOWNLOAD, att);\n this.state.goDownload();\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendError(att) {\n att = att || {};\n\n att.isAd = this.isAd();\n this.state.goError();\n let ev = this.isAd()\n ? VideoTracker.Events.AD_ERROR\n : VideoTracker.Events.CONTENT_ERROR;\n //this.send(ev, att);\n\n this.sendVideoErrorAction(ev, att);\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendRenditionChanged(att) {\n att = att || {};\n att.timeSinceLastRenditionChange =\n this.state.timeSinceLastRenditionChange.getDeltaTime();\n att.shift = this.getRenditionShift(true);\n let ev;\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_RENDITION_CHANGE;\n } else {\n ev = VideoTracker.Events.CONTENT_RENDITION_CHANGE;\n }\n //this.send(ev, att);\n\n this.isAd()\n ? this.sendVideoAdAction(ev, att)\n : this.sendVideoAction(ev, att);\n\n this.state.goRenditionChange();\n }\n\n /**\n * Sends associated event and changes view state. Heartbeat will automatically be sent every\n * 10 seconds. There's no need to call this manually.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n * @param {number} att.url Url of the clicked ad.\n *\n */\n sendHeartbeat(att) {\n if (this.state.isRequested) {\n let ev;\n\n let elapsedTime = this.getHeartbeat();\n this.state._hb = true;\n elapsedTime = this.adjustElapsedTimeForPause(elapsedTime);\n\n if (this.isAd()) {\n ev = VideoTracker.Events.AD_HEARTBEAT;\n if (this.getPlayerName() === \"bitmovin-ads\") {\n this.sendVideoAdAction(ev, att);\n } else {\n this.sendVideoAdAction(ev, { elapsedTime, ...att });\n }\n } else {\n ev = VideoTracker.Events.CONTENT_HEARTBEAT;\n this.sendVideoAction(ev, { elapsedTime, ...att });\n }\n this.state.goHeartbeat();\n }\n }\n\n adjustElapsedTimeForPause(elapsedTime) {\n if (this.state._acc) {\n elapsedTime -= this.state._acc;\n this.state._acc = 0;\n }\n\n if (this.state.isPaused) {\n elapsedTime -= this.state.elapsedTime.getDeltaTime();\n if (elapsedTime < 10) elapsedTime = 0;\n this.state.elapsedTime.start();\n }\n\n if (this.state._bufferAcc) {\n elapsedTime -= this.state._bufferAcc;\n this.state._bufferAcc = 0;\n } else if (this.state.isBuffering) {\n elapsedTime -= this.state.bufferElapsedTime.getDeltaTime();\n if (elapsedTime < 5) {\n elapsedTime = 0;\n }\n this.state.bufferElapsedTime.start();\n }\n\n return Math.max(0, elapsedTime);\n }\n\n // Only ads\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendAdBreakStart(att) {\n if (this.isAd() && this.state.goAdBreakStart()) {\n this.state.totalAdPlaytime = 0;\n if (this.parentTracker) this.parentTracker.state.isPlaying = false;\n // this.send(VideoTracker.Events.AD_BREAK_START, att);\n this.sendVideoAdAction(VideoTracker.Events.AD_BREAK_START, att);\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n */\n sendAdBreakEnd(att) {\n if (this.isAd() && this.state.goAdBreakEnd()) {\n att = att || {};\n att.timeSinceAdBreakBegin =\n this.state.timeSinceAdBreakStart.getDeltaTime();\n //this.send(VideoTracker.Events.AD_BREAK_END, att);\n this.sendVideoAdAction(VideoTracker.Events.AD_BREAK_END, att);\n // Just in case AD_END not arriving, because of an AD_ERROR\n if (this.parentTracker) this.parentTracker.state.isPlaying = true;\n this.stopHeartbeat();\n if (this.parentTracker && this.isAd())\n this.parentTracker.state.goLastAd();\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n * @param {number} att.quartile Number of the quartile.\n */\n sendAdQuartile(att) {\n if (this.isAd()) {\n att = att || {};\n if (!att.quartile)\n Log.warn(\"Called sendAdQuartile without { quartile: xxxxx }.\");\n att.timeSinceLastAdQuartile =\n this.state.timeSinceLastAdQuartile.getDeltaTime();\n //this.send(VideoTracker.Events.AD_QUARTILE, att);\n\n this.sendVideoAdAction(VideoTracker.Events.AD_QUARTILE, att);\n this.state.goAdQuartile();\n }\n }\n\n /**\n * Sends associated event and changes view state. An internal state machine will prevent\n * duplicated events. Should be associated to an event using registerListeners.\n * @param {Object} [att] Collection of key:value attributes to send with the request.\n * @param {number} att.url Url of the clicked ad.\n */\n sendAdClick(att) {\n if (this.isAd()) {\n att = att || {};\n if (!att.url) Log.warn(\"Called sendAdClick without { url: xxxxx }.\");\n //this.send(VideoTracker.Events.AD_CLICK, att);\n this.sendVideoAdAction(VideoTracker.Events.AD_CLICK, att);\n }\n }\n}\n\n/**\n * Enumeration of events fired by this class.\n *\n * @static\n * @memberof VideoTracker\n * @enum {String}\n */\nVideoTracker.Events = {\n // Player\n /** The player is ready to start sending events. */\n PLAYER_READY: \"PLAYER_READY\",\n /** Downloading data. */\n DOWNLOAD: \"DOWNLOAD\",\n /** An error happened */\n ERROR: \"ERROR\",\n\n // Video\n /** Content video has been requested. */\n CONTENT_REQUEST: \"CONTENT_REQUEST\",\n /** Content video started (first frame shown). */\n CONTENT_START: \"CONTENT_START\",\n /** Content video ended. */\n CONTENT_END: \"CONTENT_END\",\n /** Content video paused. */\n CONTENT_PAUSE: \"CONTENT_PAUSE\",\n /** Content video resumed. */\n CONTENT_RESUME: \"CONTENT_RESUME\",\n /** Content video seek started */\n CONTENT_SEEK_START: \"CONTENT_SEEK_START\",\n /** Content video seek ended. */\n CONTENT_SEEK_END: \"CONTENT_SEEK_END\",\n /** Content video beffering started */\n CONTENT_BUFFER_START: \"CONTENT_BUFFER_START\",\n /** Content video buffering ended */\n CONTENT_BUFFER_END: \"CONTENT_BUFFER_END\",\n /** Content video heartbeat, en event that happens once every 30 seconds while the video is playing. */\n CONTENT_HEARTBEAT: \"CONTENT_HEARTBEAT\",\n /** Content video stream qwuality changed. */\n CONTENT_RENDITION_CHANGE: \"CONTENT_RENDITION_CHANGE\",\n /** Content video error. */\n CONTENT_ERROR: \"CONTENT_ERROR\",\n\n // Ads only\n /** Ad video has been requested. */\n AD_REQUEST: \"AD_REQUEST\",\n /** Ad video started (first frame shown). */\n AD_START: \"AD_START\",\n /** Ad video ended. */\n AD_END: \"AD_END\",\n /** Ad video paused. */\n AD_PAUSE: \"AD_PAUSE\",\n /** Ad video resumed. */\n AD_RESUME: \"AD_RESUME\",\n /** Ad video seek started */\n AD_SEEK_START: \"AD_SEEK_START\",\n /** Ad video seek ended */\n AD_SEEK_END: \"AD_SEEK_END\",\n /** Ad video beffering started */\n AD_BUFFER_START: \"AD_BUFFER_START\",\n /** Ad video beffering ended */\n AD_BUFFER_END: \"AD_BUFFER_END\",\n /** Ad video heartbeat, en event that happens once every 30 seconds while the video is playing. */\n AD_HEARTBEAT: \"AD_HEARTBEAT\",\n /** Ad video stream qwuality changed. */\n AD_RENDITION_CHANGE: \"AD_RENDITION_CHANGE\",\n /** Ad video error. */\n AD_ERROR: \"AD_ERROR\",\n /** Ad break (a block of ads) started. */\n AD_BREAK_START: \"AD_BREAK_START\",\n /** Ad break ended. */\n AD_BREAK_END: \"AD_BREAK_END\",\n /** Ad quartile happened. */\n AD_QUARTILE: \"AD_QUARTILE\",\n /** Ad has been clicked. */\n AD_CLICK: \"AD_CLICK\",\n};\n\n// Private members\nfunction funnelAdEvents(e) {\n if (e.type === VideoTracker.Events.AD_ERROR) {\n this.sendVideoErrorAction(e.type, e.data);\n return;\n }\n this.sendVideoAdAction(e.type, e.data);\n}\n\nexport default VideoTracker;\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","import Core from \"./core\";\nimport Constants from \"./constants\";\nimport Chrono from \"./chrono\";\nimport Log from \"./log\";\nimport Emitter from \"./emitter\";\nimport Tracker from \"./tracker\";\nimport VideoTracker from \"./videotracker\";\nimport VideoTrackerState from \"./videotrackerstate\";\nimport { NrVideoEventAggregator } from \"./eventAggregator\";\nimport { RetryQueueHandler } from \"./retryQueueHandler\";\nimport { OptimizedHttpClient } from \"./optimizedHttpClient\";\nimport { HarvestScheduler } from \"./harvestScheduler\";\nimport { recordEvent } from \"./recordEvent\";\nimport { version } from \"../package.json\";\n\nconst nrvideo = {\n // Core components (existing)\n Constants,\n Chrono,\n Log,\n Emitter,\n Tracker,\n VideoTracker,\n VideoTrackerState,\n Core,\n version,\n\n // Enhanced video analytics components (new)\n \n NrVideoEventAggregator,\n RetryQueueHandler,\n OptimizedHttpClient,\n HarvestScheduler,\n\n\n\n // Enhanced event recording\n recordEvent,\n\n\n};\n\nexport default nrvideo;\n"],"names":["e","_utils","require","_log","__esModule","default","OptimizedHttpClient","send","requestOptions","callback","url","payload","options","Error","request","this","executeRequest","error","Log","message","retry","status","startTime","Date","now","requestBody","JSON","stringify","body","isFinalHarvest","navigator","sendBeacon","success","sendWithBeacon","result","handleRequestComplete","response","fetchWithTimeout","method","headers","keepalive","ok","statusText","shouldRetry","warn","timeout","controller","AbortController","timeoutId","setTimeout","abort","fetch","signal","clearTimeout","name","exports","Constants","AdPositions","PRE","MID","POST","COLLECTOR","US","EU","Staging","GOV","VALID_EVENT_TYPES","MAX_PAYLOAD_SIZE","MAX_BEACON_SIZE","MAX_EVENTS_PER_BATCH","INTERVAL","QOE_AGGREGATE_KEYS","msg","_report","Levels","ERROR","WARNING","notice","slice","call","arguments","NOTICE","debug","DEBUG","debugCommonVideoEvents","o","extraEvents","report","level","type","playerEvents","shift","concat","i","length","window","on","addEventListener","addEventHandler","err","color","d","logMethod","prefix","includeTime","getDate","getMinutes","getSeconds","getMilliseconds","_getCurrentTime","_letters","_level2letter","SILENT","colorful","document","documentMode","_plainReport","console","undefined","cast","log","splice","apply","Array","m","ALL","location","search","exec","_loadLevelFromUrl","_package","_interopRequireDefault","_emitter","_chrono","_constants","_agent","Tracker","Emitter","constructor","super","customData","heartbeat","parentTracker","_trackerReadyChrono","Chrono","start","_actionTable","ACTION_TABLE","_actionAdTable","ACTION_AD_TABLE","setOptions","dispose","unregisterListeners","registerListeners","getHeartbeat","state","_isAd","startHeartbeat","_heartbeatInterval","setInterval","sendHeartbeat","bind","Math","max","stopHeartbeat","clearInterval","att","sendVideoAction","Events","HEARTBEAT","getAttributes","eventType","trackerName","getTrackerName","trackerVersion","getTrackerVersion","coreVersion","pkg","version","timeSinceTrackerReady","getDeltaTime","key","hidden","isBackgroundEvent","event","emit","sendVideoAdAction","sendVideoErrorAction","ev","isAd","sendVideoCustomAction","setHarvestInterval","interval","videoAnalyticsHarvester","QOE_AGGREGATE","reset","_createdAt","_hb","_acc","_bufferAcc","_viewSession","_viewCount","numberOfErrors","numberOfAds","numberOfVideos","totalPlaytime","weightedAverageBitrate","totalAdPlaytime","isAdBreak","initialBufferingHappened","startupTime","peakBitrate","_lastBitrate","_lastBitrateChangeTimestamp","partialAverageBitrate","hadStartupFailure","hadPlaybackFailure","totalRebufferingTime","resetFlags","resetChronos","isPlayerReady","isRequested","isStarted","isPaused","isSeeking","isBuffering","isPlaying","timeSinceRequested","timeSinceStarted","timeSincePaused","timeSinceSeekBegin","timeSinceBufferBegin","timeSinceAdBreakStart","timeSinceLastDownload","timeSinceLastHeartbeat","timeSinceLastRenditionChange","timeSinceLastAdQuartile","timeSinceLastAd","timeSinceLastError","timeSinceLastAdError","timeSinceResumed","timeSinceSeekEnd","playtimeSinceLastEvent","customTimeSinceAttributes","elapsedTime","bufferElapsedTime","_totalAdPlaytime","setIsAd","setTimeSinceAttribute","removeTimeSinceAttribute","getViewSession","time","getTime","random","toString","substring","getViewId","getStateAttributes","timeSinceAdRequested","timeSinceLastAdHeartbeat","timeSinceAdStarted","timeSinceAdPaused","timeSinceAdBufferBegin","timeSinceAdSeekBegin","timeSinceAdBreakBegin","value","Object","entries","getQoeAttributes","kpi","weightedBitrate","qoe","calculateBufferType","isInitialBuffering","bufferType","goViewCountUp","goPlayerReady","goRequest","goStart","goEnd","stop","goPause","goResume","goBufferStart","goBufferEnd","goSeekStart","goSeekEnd","goAdBreakStart","goAdBreakEnd","goDownload","goHeartbeat","goRenditionChange","goAdQuartile","goError","isError","goLastAd","trackContentBitrateState","bitrate","deltaPlaytime","currentWeightedBitrate","resetViewIdTrackedState","clearTotalAdsTime","totalAdTime","getDuration","startAdsTime","stopAdsTime","setStartupTime","fallbackUrl","NRVIDEO","info","beacon","licenseKey","applicationID","href","stringifiedPayload","stream","Blob","compressionStream","CompressionStream","compressedStream","pipeThrough","Response","blob","data","ArrayBuffer","byteLength","size","FormData","val","getCircularReplacer","async","compressedData","Uint8Array","decompressionStream","DecompressionStream","decompressedStream","decompressedText","text","parse","keys","obj","isArray","reduce","seen","WeakSet","has","add","_eventAggregator","_retryQueueHandler","_optimizedHttpClient","eventAggregator","eventBuffer","retryQueueHandler","RetryQueueHandler","httpClient","fallBackUrl","retryCount","NrVideoEventAggregator","setSmartHarvestCallback","threshold","triggerSmartHarvest","currentTimerId","harvestCycle","isHarvesting","setupPageLifecycleHandlers","startScheduler","eventBufferSize","scheduleNextHarvest","stopScheduler","isEmpty","triggerHarvest","onHarvestInterval","hasBufferData","hasRetryData","getQueueSize","reason","events","drainEvents","maxBeaconSize","dataSize","trimEventsToFit","sendChunk","totalChunks","results","handleHarvestFailure","consecutiveFailures","maxSize","trimmedEvents","currentSize","testPayloadSize","ins","unshift","discardedCount","discardedEvents","originalCount","trimmedCount","finalSize","addFailedEvents","freshEvents","drain","currentPayloadSize","availableSpace","availableEventCount","retryEvents","getRetryEventsToFit","chunk","isLastChunk","buildUrl","Promise","resolve","handleRequestFailure","eventCount","region","updateHarvestInterval","newInterval","isNaN","finalHarvestTriggered","triggerFinalHarvest","force","_recordEvent","_videoConfiguration","Core","addTracker","tracker","setVideoConfig","trackers","push","eventHandler","trackerInit","removeTracker","off","index","indexOf","getTrackers","actionName","enrichedData","recordEvent","sendError","forceHarvest","ret","cleanData","retryQueue","maxQueueSize","maxQueueSizeBytes","eventsArray","queueSizeBefore","evictOldestEvent","eventSize","discardEvent","oldest","usedSpace","clear","buffer","maxPayloadSize","maxEventsPerBatch","totalEvents","smartHarvestPayloadThreshold","floor","overflowPayloadThreshold","smartHarvestEventThreshold","overflowEventThreshold","onSmartHarvestTrigger","addOrReplaceByActionName","eventObject","findIndex","wouldExceedPayload","wouldExceedEventCount","makeRoom","previousPayloadSize","checkSmartHarvestTrigger","payloadPercentage","eventPercentage","isPayloadOverflowReached","isEventOverflowReached","triggerReason","round","isPayloadSmartReached","isEventSmartReached","newEventSize","removed","removedSize","attributes","includes","appName","eventAttributes","qoeAttrs","otherAttrs","timestamp","timeSinceLoad","performance","metadataAttributes","getObjectEntriesForKeys","qoeEventObject","qoeAggregateVersion","addEvent","successQoe","_tracker","stopTime","accumulator","offset","clone","chrono","_harvestScheduler","videoAnalyticsAgent","isInitialized","harvestScheduler","initialize","HarvestScheduler","_listeners","forEach","target","videoConfiguration","setConfiguration","VideoConfiguration","userInfo","initializeGlobalConfig","validateRequiredFields","values","flatMap","el","join","_videotrackerstate","VideoTracker","player","TrackerState","adsTracker","_lastBufferType","_userId","setPlayer","tag","setUserId","userId","setAdsTracker","prototype","getElementById","disposeAdsTracker","funnelAdEvents","getVideoId","getTitle","isLive","getBitrate","getWebkitBitrate","webkitVideoDecodedByteCount","_lastWebkitBitrate","delta","seconds","getRenditionName","getRenditionBitrate","getRenditionShift","saveNewRendition","last","current","_lastAdRendition","_lastRendition","getRenditionHeight","videoHeight","getRenditionWidth","videoWidth","duration","getPlayhead","currentTime","getLanguage","getSrc","currentSrc","getPlayrate","playbackRate","isMuted","muted","isFullscreen","getCdn","getPlayerName","getPlayerVersion","getFps","isAutoplayed","autoplay","getPreload","preload","getAdQuartile","getAdPosition","getAdPartner","getAdCreativeId","getInstrumentationProvider","getInstrumentationName","getInstrumentationVersion","viewSession","viewId","playerName","playerVersion","pageUrl","adId","adTitle","adSrc","adCdn","adBitrate","adRenditionName","adRenditionBitrate","adRenditionHeight","adRenditionWidth","adDuration","adPlayhead","adLanguage","adIsMuted","adFps","adPosition","adCreativeId","adPartner","contentId","contentTitle","contentSrc","contentCdn","contentPlayhead","contentIsLive","contentBitrate","contentRenditionName","contentRenditionBitrate","contentRenditionHeight","contentRenditionWidth","contentDuration","contentLanguage","contentPlayrate","contentIsFullscreen","contentIsMuted","contentIsAutoplayed","contentPreload","contentFps","addQoeAttributes","sendCustom","timeSinceAttName","sendPlayerReady","PLAYER_READY","sendRequest","AD_REQUEST","CONTENT_REQUEST","sendStart","AD_START","CONTENT_START","totalAdsTime","sendEnd","AD_END","CONTENT_END","sendPause","AD_PAUSE","CONTENT_PAUSE","sendResume","AD_RESUME","CONTENT_RESUME","sendBufferStart","AD_BUFFER_START","CONTENT_BUFFER_START","buildBufferAttributes","sendBufferEnd","AD_BUFFER_END","CONTENT_BUFFER_END","sendSeekStart","AD_SEEK_START","CONTENT_SEEK_START","sendSeekEnd","AD_SEEK_END","CONTENT_SEEK_END","sendDownload","DOWNLOAD","AD_ERROR","CONTENT_ERROR","sendRenditionChanged","AD_RENDITION_CHANGE","CONTENT_RENDITION_CHANGE","adjustElapsedTimeForPause","AD_HEARTBEAT","CONTENT_HEARTBEAT","sendAdBreakStart","AD_BREAK_START","sendAdBreakEnd","AD_BREAK_END","sendAdQuartile","quartile","AD_QUARTILE","sendAdClick","AD_CLICK","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","module","__webpack_modules__","_core","_videotracker","nrvideo","VideoTrackerState"],"sourceRoot":""}