@newrelic/video-core 4.1.8-beta → 5.0.0
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.
- package/CHANGELOG.md +65 -15
- package/README.md +628 -45
- package/dist/cjs/browser/index.js +3 -0
- package/dist/cjs/browser/index.js.LICENSE.txt +6 -0
- package/dist/cjs/browser/index.js.map +1 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.LICENSE.txt +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/vega/index.js +3 -0
- package/dist/cjs/vega/index.js.LICENSE.txt +6 -0
- package/dist/cjs/vega/index.js.map +1 -0
- package/dist/esm/browser/index.js +3 -0
- package/dist/esm/browser/index.js.LICENSE.txt +6 -0
- package/dist/esm/browser/index.js.map +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.LICENSE.txt +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/vega/index.js +3 -0
- package/dist/esm/vega/index.js.LICENSE.txt +6 -0
- package/dist/esm/vega/index.js.map +1 -0
- package/dist/umd/nrvideo.min.js +1 -1
- package/dist/umd/nrvideo.min.js.LICENSE.txt +1 -1
- package/dist/umd/nrvideo.min.js.map +1 -1
- package/package.json +31 -6
- package/src/{agent.js → browser/agent.js} +43 -8
- package/src/{harvestScheduler.js → browser/harvestScheduler.js} +87 -86
- package/src/browser/index.js +58 -0
- package/src/connectedDevice/connectedDeviceAgent.js +116 -0
- package/src/connectedDevice/connectedDeviceConstants.js +121 -0
- package/src/connectedDevice/connectedDeviceHarvester.js +522 -0
- package/src/connectedDevice/index.js +49 -0
- package/src/constants.js +8 -0
- package/src/core.js +4 -18
- package/src/eventAggregator.js +48 -0
- package/src/index.js +9 -10
- package/src/obfuscate.js +33 -0
- package/src/optimizedHttpClient.js +6 -2
- package/src/recordEvent.js +56 -49
- package/src/tracker.js +14 -4
- package/src/utils/eventBuilder.js +126 -0
- package/src/utils/harvestTimer.js +109 -0
- package/src/{utils.js → utils/index.js} +2 -2
- package/src/utils/qoeFilters.js +149 -0
- package/src/videoConfiguration.js +90 -7
- package/src/videotracker.js +100 -32
- package/src/videotrackerstate.js +156 -31
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/*! For license information please see index.js.LICENSE.txt */
|
|
2
|
+
(()=>{"use strict";const t={d:(e,i)=>{if(Array.isArray(i))for(var s=0;s<i.length;){var r=i[s++],a=i[s++];t.o(e,r)?0===a&&s++:0===a?Object.defineProperty(e,r,{enumerable:!0,value:i[s++]}):Object.defineProperty(e,r,{enumerable:!0,get:a})}else for(var r in i)t.o(i,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:i[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}};let e={};t.r(e),t.d(e,{Chrono:()=>u,Constants:()=>h,Core:()=>w,Emitter:()=>l,HarvestScheduler:()=>q,Log:()=>n,NrVideoEventAggregator:()=>P,OptimizedHttpClient:()=>F,RetryQueueHandler:()=>H,Tracker:()=>m,VideoTracker:()=>C,VideoTrackerState:()=>D,default:()=>M,getRegisteredHarvester:()=>p,recordEvent:()=>v,version:()=>d.rE,videoAnalyticsHarvester:()=>G});class i{static error(...t){s(t,i.Levels.ERROR,"darkred")}static warn(...t){s(t,i.Levels.WARNING,"darkorange")}static notice(...t){s([].slice.call(arguments),i.Levels.NOTICE,"darkcyan")}static debug(...t){s(t,i.Levels.DEBUG,"indigo")}static debugCommonVideoEvents(t,e,s){try{if(i.level<=i.Levels.DEBUG){s=s||function(t){i.debug("Event: "+t.type)};var r=["canplay","buffering","waiting","ended","play","playing","pause","resume","error","abort","seek","seeking","seeked","stalled","dispose","loadeddata","loadstart","loadedmetadata"];e&&(null===e[0]?(e.shift(),r=e):r=r.concat(e));for(var a=0;a<r.length;a++)"function"==typeof t?t.call(window,r[a],s):t.on?t.on(r[a],s):t.addEventListener?t.addEventListener(r[a],s):t.addEventHandler?t.addEventHandler(r[a],s):i.warn("debugCommonVideoEvents: No common listener function found for ",t)}}catch(t){i.warn(t)}}}function s(t,e,s){e=e||i.Levels.NOTICE,s=s||"darkcyan";var n,o,h,d,l,c,u=i.prefix;(i.includeTime&&(u+=(n=new Date,o=("0"+n.getDate()).slice(-2),h=("0"+n.getMinutes()).slice(-2),d=("0"+n.getSeconds()).slice(-2),l=("00"+n.getMilliseconds()).slice(-3),"["+o+":"+h+":"+d+"."+l+"] ")),u+=function(t){return a[t]}(e)+":",i.level<=e&&e!==i.Levels.SILENT)&&(!i.colorful||"undefined"!=typeof document&&document.documentMode?r(t,u):(c=e===i.Levels.ERROR&&console.error?console.error:e===i.Levels.WARNING&&console.warn?console.warn:e===i.Levels.DEBUG&&console.debug&&null==window.cast?console.debug:console.log,u="%c"+u,t.splice(0,0,u,"color: "+s),c.apply(console,t)))}function r(t,e){if(t instanceof Array)for(var i in t)r(t[i],e);else"string"==typeof t?console.log(e+" "+t):(console.log(e+"↵"),console.log(t))}i.Levels={SILENT:5,ERROR:4,WARNING:3,NOTICE:2,DEBUG:1,ALL:0},i.level=i.Levels.ERROR,i.colorful=!0,i.includeTime=!0,i.prefix="[nrvideo]";const a={4:"e",3:"w",2:"n",1:"d"};!function(){if("undefined"!=typeof window&&window.location&&window.location.search){var t=/\?.*&*nrvideo-debug=(.+)/i.exec(window.location.search);null!==t&&("true"===t[1]?i.level=i.Levels.ALL:i.level=t[1]),null!==/\?.*&*nrvideo-colors=false/i.exec(window.location.search)&&(i.colorful=!1)}}();const n=i;class o{}o.AdPositions={PRE:"pre",MID:"mid",POST:"post"},o.COLLECTOR={US:["bam.nr-data.net","bam-cell.nr-data.net"],EU:"bam.eu01.nr-data.net",JP:"bam.jp.nr-data.net",Staging:"staging-bam-cell.nr-data.net",GOV:"gov-bam.nr-data.net"},o.VALID_EVENT_TYPES=["VideoAction","VideoAdAction","VideoErrorAction","VideoCustomAction"],o.MAX_PAYLOAD_SIZE=1048576,o.MAX_BEACON_SIZE=61440,o.MAX_EVENTS_PER_BATCH=1e3,o.INTERVAL=1e4,o.DEFAULT_QOE_INTERVAL_FACTOR=2,o.QOE_KPI_KEYS=["startupTime","peakBitrate","averageBitrate","totalPlaytime","totalRebufferingTime","rebufferingRatio","hadStartupError","hadPlaybackError","numberOfErrors"],o.QOE_AGGREGATE_KEYS=["coreVersion","instrumentation.name","instrumentation.provider","instrumentation.version","isBackgroundEvent","playerName","playerVersion","src","viewId","viewSession","contentIsAutoplayed","contentIsMuted","contentRenditionHeight","contentRenditionWidth","contentSrc","numberOfVideos","pageUrl","trackerName","trackerVersion","contentDuration","contentPlayrate","contentPlayhead","contentPreload","elapsedTime","contentTitle","contentId","contentIsLive","deviceType","deviceGroup","deviceManufacturer","deviceModel","deviceName","deviceSize","deviceUuid","contentRenditionName","contentIsFullscreen","contentCdn","contentFps","asnOrganization","asnLongitude","asnLatitude","asn","timeSinceRequested","timeSinceStarted"];const h=o,d={rE:"5.0.0"};const l=class{on(t,e){if(this._listeners=this._listeners||{},"function"==typeof e)return this._listeners[t]=this._listeners[t]||[],this._listeners[t].push(e),this}off(t,e){if(this._listeners=this._listeners||{},this._listeners[t]){var i=this._listeners[t].indexOf(e);-1!==i&&this._listeners[t].splice(i,1)}return this}emit(t,e,i){return this._listeners=this._listeners||{},i=i||{},Array.isArray(this._listeners[e])&&this._listeners[e].forEach(s=>{s.call(this,{eventType:t,type:e,data:i,target:this})}),Array.isArray(this._listeners["*"])&&this._listeners["*"].forEach(s=>{s.call(this,{eventType:t,type:e,data:i,target:this})}),this}};class c{constructor(){this.reset()}reset(){this.startTime=0,this.stopTime=0,this.accumulator=0,this.offset=0}getDeltaTime(){return this.startTime?this.offset+((new Date).getTime()-this.startTime):null}start(){this.startTime=(new Date).getTime(),this.stopTime=0}stop(){return this.stopTime=(new Date).getTime(),this.startTime<this.stopTime&&(this.accumulator+=this.stopTime-this.startTime),this.getDeltaTime()}getDuration(){return this.stopTime?this.accumulator+this.offset:this.accumulator+(this.getDeltaTime()??0)}clone(){var t=new c;return t.startTime=this.startTime,t.stopTime=this.stopTime,t.offset=this.offset,t.accumulator=this.accumulator,t}}const u=c;class g extends l{constructor(t){super(),this.customData={},this.heartbeat=null,this.parentTracker=null,this._trackerReadyChrono=new u,this._trackerReadyChrono.start(),this._actionTable=h.ACTION_TABLE,this._actionAdTable=h.ACTION_AD_TABLE,t=t||{},this.setOptions(t)}setOptions(t){t&&(t.parentTracker&&(this.parentTracker=t.parentTracker),t.customData&&(this.customData=t.customData),t.heartbeat&&(this.heartbeat=t.heartbeat))}dispose(){this.unregisterListeners()}registerListeners(){}unregisterListeners(){}getHeartbeat(){return this.state._isAd?2e3:this.heartbeat?this.heartbeat:this.parentTracker&&this.parentTracker.heartbeat?this.parentTracker.heartbeat:3e4}startHeartbeat(){this._heartbeatInterval=setInterval(this.sendHeartbeat.bind(this),Math.max(this.getHeartbeat(),2e3))}stopHeartbeat(){this._heartbeatInterval&&clearInterval(this._heartbeatInterval)}sendHeartbeat(t){this.sendVideoAction(g.Events.HEARTBEAT,t)}getAttributes(t,e){(t=t||{}).trackerName=this.getTrackerName(),t.trackerVersion=this.getTrackerVersion(),t.coreVersion=d.rE,t.timeSinceTrackerReady=this._trackerReadyChrono.getDeltaTime();for(let e in this.customData)t[e]=this.customData[e];return null!=document.hidden&&(t.isBackgroundEvent=document.hidden),t}getTrackerVersion(){return d.rE}getTrackerName(){return"base-tracker"}sendVideoAction(t,e){this.emit("VideoAction",t,this.getAttributes(e))}sendVideoAdAction(t,e){this.emit("VideoAdAction",t,this.getAttributes(e))}sendVideoErrorAction(t,e){let i=this.isAd()?"adError":"videoError";this.emit("VideoErrorAction",t,this.getAttributes(e,i))}sendVideoCustomAction(t,e){this.emit("VideoCustomAction",t,this.getAttributes(e,"customAction"))}setHarvestInterval(t){const e=this.getHarvester?.();if(e)try{e.setHarvestInterval(t)}catch(t){return void n.error("Failed to set harvest interval:",t.message)}else n.error("Tracker has no harvester; setHarvestInterval ignored")}getHarvester(){return null}}g.Events={HEARTBEAT:"HEARTBEAT",QOE_AGGREGATE:"QOE_AGGREGATE"};const m=g;function f(t){try{return JSON.stringify(t,(()=>{const t=new WeakSet;return(e,i)=>{if("object"==typeof i&&null!==i){if(t.has(i))return;t.add(i)}return i}})())??""}catch(t){return n.error("Error stringifying value:",t.message),""}}function E(t){if("string"==typeof t&&t.length)return t.length;if("object"==typeof t){if("undefined"!=typeof ArrayBuffer&&t instanceof ArrayBuffer&&t.byteLength)return t.byteLength;if("undefined"!=typeof Blob&&t instanceof Blob&&t.size)return t.size;if(!("undefined"!=typeof FormData&&t instanceof FormData))try{return f(t).length}catch(t){return}}}function A(t,e,i,{addTimeSinceLoad:s=!1}={}){const{appName:r,applicationID:a}=i,{qoe:n,...o}=e,d=n?{...n}:{},l={...a?{}:{appName:r},timestamp:Date.now(),...s?{timeSinceLoad:"undefined"!=typeof window&&window.performance?window.performance.now()/1e3:null}:{}},c={...o,eventType:t,...l};let u=null;if("VideoAction"===t){const t=(g=h.QOE_AGGREGATE_KEYS,f=e,g&&Array.isArray(g)&&0!==g.length?f&&"object"==typeof f?g.reduce((t,e)=>(e in f&&(t[e]=f[e]),t),{}):{}:f);u={eventType:"VideoAction",actionName:m.Events.QOE_AGGREGATE,qoeAggregateVersion:"1.0.0",...d,...t,...l}}var g,f;return{eventObject:c,qoeEventObject:u}}const T=Object.create(null);function p(t){return T[t]}function v(t,e={}){try{if(!h.VALID_EVENT_TYPES.includes(t))return n.warn("Invalid event type provided to recordEvent",{eventType:t}),!1;const i="Vega"===e.src,s=i?"Vega":"Browser",r="undefined"!=typeof window?window:void 0,a=i?globalThis.__NRVIDEO_CD__?.info:r?.NRVIDEO?.info;if(!a)return;const o=T[s];if(!o)return n.warn("No harvester registered for routing key",{routingKey:s}),!1;return function(t,e,i,s,r,{addTimeSinceLoad:a=!1}={}){if(!s)return!1;const{eventObject:n,qoeEventObject:o}=A(t,e,i,{addTimeSinceLoad:a}),h=s.addEvent(n);return o&&r?h&&s.addEvent(o):h}(t,e,a,o,i?globalThis.__NRVIDEO_CD__?.config?.qoeAggregate:r?.NRVIDEO?.config?.qoeAggregate,{addTimeSinceLoad:!i})}catch(t){return n.error("Failed to record event:",t.message),!1}}const{COLLECTOR:S}=h;class y{setConfiguration(t,e,i){return!!("Vega"===i?this.validateVegaFields(t):this.validateRequiredFields(t))&&(!!this.validateConfigFields(e)&&(this.initializeGlobalConfig(t,e,i),n.notice("Video analytics configuration initialized successfully"),!0))}validateVegaFields(t){return t&&"object"==typeof t?t.applicationToken?!!["US","EU","staging","GOV"].includes(t.endpoint)||(n.error("Invalid endpoint (must be US, EU, staging, or GOV)"),!1):(n.error("applicationToken is required"),!1):(n.error("Configuration must be an object"),!1)}validateRequiredFields(t){if(!t||"object"!=typeof t)return n.error("Configuration must be an object"),!1;const{licenseKey:e,appName:i,region:s,applicationID:r,beacon:a}=t;if(!e)return n.error("licenseKey is required"),!1;if(r){if(!a)return n.error("beacon is required when applicationID is provided"),!1;if(!Object.values(S).flatMap(t=>t).includes(a))return n.error(`Invalid beacon: ${a}`),!1}else{if(!i||!s)return n.error("appName and region are required when applicationID is not provided"),!1;if(!S[s])return n.error(`Invalid region: ${s}. Valid regions are: ${Object.keys(S).join(", ")}`),!1}return!0}validateConfigFields(t){if(null==t)return!0;if("object"!=typeof t||Array.isArray(t))return n.error("config must be an object"),!1;const{qoeAggregate:e,obfuscate:i}=t;return void 0!==e&&"boolean"!=typeof e?(n.error("qoeAggregate must be a boolean"),!1):!(void 0!==i&&!Array.isArray(i))||(n.error("obfuscate must be an array"),!1)}filterObfuscateRules(t){return t?t.filter(t=>{const e=void 0!==t.regex&&("string"==typeof t.regex||t.regex instanceof RegExp),i=void 0!==t.replacement&&"string"==typeof t.replacement;return!(!e||!i)||(n.warn("obfuscate rule missing required 'regex' (string|RegExp) and/or 'replacement' (string), skipping:",t),!1)}):[]}sanitizeQoeIntervalFactor(t){return null==t?h.DEFAULT_QOE_INTERVAL_FACTOR:"number"==typeof t&&Number.isInteger(t)&&t>=1?t:(n.warn(`Invalid qoeIntervalFactor "${t}" — must be a positive integer. Defaulting to ${h.DEFAULT_QOE_INTERVAL_FACTOR}.`),h.DEFAULT_QOE_INTERVAL_FACTOR)}initializeGlobalConfig(t,e,i){if("Vega"===i)return void(globalThis.__NRVIDEO_CD__={info:{accountId:t.accountId,applicationToken:t.applicationToken,endpoint:t.endpoint,...t.appName?{appName:t.appName}:{},...t.applicationID?{applicationID:t.applicationID}:{},...t.deviceInfo?{deviceInfo:t.deviceInfo}:{}},config:{qoeAggregate:e?.qoeAggregate??!0,qoeIntervalFactor:this.sanitizeQoeIntervalFactor(e?.qoeIntervalFactor),obfuscate:this.filterObfuscateRules(e?.obfuscate)}});let{licenseKey:s,appName:r,region:a,beacon:n,applicationID:o}=t;n="US"===a?h.COLLECTOR.US[0]:n||S[a],window.NRVIDEO={info:{...a?{region:a}:{},beacon:n,licenseKey:s,applicationID:o,...o?{}:{appName:r}},config:{qoeAggregate:e?.qoeAggregate??!0,qoeIntervalFactor:this.sanitizeQoeIntervalFactor(e?.qoeIntervalFactor),obfuscate:this.filterObfuscateRules(e?.obfuscate)}}}}const _=new y;class R{static addTracker(t,e){var i,s,r;e?.info&&(i=e.info,s=e?.config,r=e?.src,_.setConfiguration(i,s,r)),t.on&&t.emit?(B.push(t),t.on("*",b),"function"==typeof t.trackerInit&&t.trackerInit()):n.error("Tried to load a non-tracker.",t)}static removeTracker(t){t.off("*",b),t.dispose();let e=B.indexOf(t);-1!==e&&B.splice(e,1)}static getTrackers(){return B}static send(t,e,i){return v(t,{actionName:e,...i})}static sendError(t){return v("VideoErrorAction",{actionName:"ERROR",...t})}}let B=[];function b(t){try{let e=function(t){let e={};for(let i in t)null!==t[i]&&void 0!==t[i]&&(e[i]=t[i]);return e}(t.data);n.level<=n.Levels.DEBUG?n.notice("Sent",t.type,e):n.notice("Sent",t.type),R.send(t.eventType,t.type,e)}catch(t){n.error("Error in event handler:",t.message)}}const w=R;const D=class{constructor(){this.reset(),this._createdAt=Date.now(),this._hb=!0,this._acc=0,this._bufferAcc=0}reset(){this._viewSession=null,this._viewCount=0,this._isAd=!1,this.numberOfErrors=0,this.numberOfAds=0,this.numberOfVideos=0,this.totalPlaytime=0,this.weightedAverageBitrate=0,this.totalAdPlaytime=0,this.isAdBreak=!1,this.initialBufferingHappened=!1,this.startupTime=null,this.peakBitrate=0,this.partialAverageBitrate=0,this._totalBitrateDuration=0,this.weightedBitrate=0,this._lastBitrate=null,this._lastBitrateChangeTimestamp=null,this._downloadBitrates=[],this._lastDownloadBitrate=null,this.totalSwitchUps=0,this.totalSwitchDowns=0,this.totalPauseTime=0,this._playedRenditions=new Set,this.hadStartupError=!1,this.hadPlaybackError=!1,this.totalRebufferingTime=0,this.resetFlags(),this.resetChronos()}resetFlags(){this.isPlayerReady=!1,this.isRequested=!1,this.isStarted=!1,this.isPaused=!1,this.isSeeking=!1,this.isBuffering=!1,this.isPlaying=!1}resetChronos(){this.timeSinceRequested=new u,this.timeSinceStarted=new u,this.timeSincePaused=new u,this.timeSinceSeekBegin=new u,this.timeSinceBufferBegin=new u,this.timeSinceAdBreakStart=new u,this.timeSinceLastDownload=new u,this.timeSinceLastHeartbeat=new u,this.timeSinceLastRenditionChange=new u,this.timeSinceLastAdQuartile=new u,this.timeSinceLastAd=new u,this.timeSinceLastError=new u,this.timeSinceLastAdError=new u,this.timeSinceResumed=new u,this.timeSinceSeekEnd=new u,this.playtimeSinceLastEvent=new u,this.customTimeSinceAttributes={},this.elapsedTime=new u,this.bufferElapsedTime=new u,this._totalAdPlaytime=new u}isAd(){return this._isAd}setIsAd(t){this._isAd=t}setTimeSinceAttribute(t){this.customTimeSinceAttributes[t]=new u,this.customTimeSinceAttributes[t].start()}removeTimeSinceAttribute(t){delete this.customTimeSinceAttributes[t]}getViewSession(){if(!this._viewSession){let t=(new Date).getTime(),e=Math.random().toString(36).substring(2)+Math.random().toString(36).substring(2);this._viewSession=t+"-"+e}return this._viewSession}getViewId(){return this.getViewSession()+"-"+this._viewCount}getStateAttributes(t){t=t||{},this.isAd()?(this.isRequested&&(t.timeSinceAdRequested=this.timeSinceRequested.getDeltaTime(),t.timeSinceLastAdHeartbeat=this.timeSinceLastHeartbeat.getDeltaTime()),this.isStarted&&(t.timeSinceAdStarted=this.timeSinceStarted.getDeltaTime()),this.isPaused&&(t.timeSinceAdPaused=this.timeSincePaused.getDeltaTime()),this.isBuffering&&(t.timeSinceAdBufferBegin=this.timeSinceBufferBegin.getDeltaTime()),this.isSeeking&&(t.timeSinceAdSeekBegin=this.timeSinceSeekBegin.getDeltaTime()),this.isAdBreak&&(t.timeSinceAdBreakBegin=this.timeSinceAdBreakStart.getDeltaTime()),this.numberOfErrors>0&&this.timeSinceLastAdError.startTime>0&&(t.timeSinceLastAdError=this.timeSinceLastAdError.getDeltaTime()),t.numberOfAds=this.numberOfAds):(this.isRequested&&(t.timeSinceRequested=this.timeSinceRequested.getDeltaTime(),t.timeSinceLastHeartbeat=this.timeSinceLastHeartbeat.getDeltaTime()),this.isStarted&&(t.timeSinceStarted=this.timeSinceStarted.getDeltaTime()),this.isPaused&&(t.timeSincePaused=this.timeSincePaused.getDeltaTime()),this.isBuffering&&(t.timeSinceBufferBegin=this.timeSinceBufferBegin.getDeltaTime()),this.isSeeking&&(t.timeSinceSeekBegin=this.timeSinceSeekBegin.getDeltaTime()),t.timeSinceLastAd=this.timeSinceLastAd.getDeltaTime(),this.numberOfErrors>0&&this.timeSinceLastError.startTime>0&&(t.timeSinceLastError=this.timeSinceLastError.getDeltaTime()),t.numberOfVideos=this.numberOfVideos),t.numberOfErrors=this.numberOfErrors,this.isAd()||(this.playtimeSinceLastEvent.startTime>0?t.playtimeSinceLastEvent=this.playtimeSinceLastEvent.getDeltaTime():t.playtimeSinceLastEvent=0,this.isPlaying?this.playtimeSinceLastEvent.start():this.playtimeSinceLastEvent.reset(),this.totalPlaytime+=t.playtimeSinceLastEvent,t.totalPlaytime=this.totalPlaytime);for(const[e,i]of Object.entries(this.customTimeSinceAttributes))t[e]=i.getDeltaTime();return t}getQoeAttributes(t){t=t||{};const e={};try{if(null!==this.startupTime&&(e.startupTime=this.startupTime),this.peakBitrate>0&&(e.peakBitrate=this.peakBitrate),e.hadStartupError=this.hadStartupError,e.hadPlaybackError=this.hadPlaybackError,e.totalRebufferingTime=this.totalRebufferingTime,e.rebufferingRatio=this.totalPlaytime>0?this.totalRebufferingTime/this.totalPlaytime*100:0,e.totalPlaytime=this.totalPlaytime,e.averageBitrate=this.weightedBitrate,e.numberOfErrors=this.numberOfErrors,this._downloadBitrates.length>0){const t=this._downloadBitrates.reduce((t,e)=>t+e,0);e.avgDownloadRate=Math.round(t/this._downloadBitrates.length),e.minDownloadRate=Math.min(...this._downloadBitrates),e.maxDownloadRate=Math.max(...this._downloadBitrates)}e.totalSwitchUps=this.totalSwitchUps,e.totalSwitchDowns=this.totalSwitchDowns,e.totalPauseTime=this.timeSincePaused.getDuration(),e.totalViewSessionTime=this.totalPlaytime,e.totalRenditions=this._playedRenditions.size,e.qoeAggregateVersion="1.1.0"}catch(t){n.error("Failed to add attributes for QOE KPIs",t.message)}return t.qoe=e,t}calculateBufferType(t){let e="";return e=t?"initial":this.isSeeking?"seek":this.isPaused?"pause":"connection",n.debug("Buffer Type = "+e),e}goViewCountUp(){this._viewCount++}goPlayerReady(){return!this.isPlayerReady&&(this.isPlayerReady=!0,!0)}goRequest(){return!this.isRequested&&(this.isRequested=!0,this.timeSinceLastAd.reset(),this.timeSinceRequested.start(),!0)}goStart(){return!(!this.isRequested||this.isStarted)&&(this.isAd()?this.numberOfAds++:this.numberOfVideos++,this.isStarted=!0,this.isPlaying=!0,this.timeSinceStarted.start(),this.playtimeSinceLastEvent.start(),!0)}goEnd(){return!!this.isRequested&&(this.numberOfErrors=0,this.resetFlags(),this.timeSinceRequested.stop(),this.timeSinceStarted.stop(),this.playtimeSinceLastEvent.stop(),this.isPlaying=!1,!0)}goPause(){return!(!this.isStarted||this.isPaused)&&(this.isPaused=!0,this.isPlaying=!1,this.timeSincePaused.start(),this.playtimeSinceLastEvent.stop(),this.timeSinceResumed.reset(),this.isBuffering&&(this._bufferAcc+=this.bufferElapsedTime.getDeltaTime()),this.elapsedTime.start(),!0)}goResume(){return!(!this.isStarted||!this.isPaused)&&(this.isPaused=!1,this.isPlaying=!0,this.timeSincePaused.stop(),this.timeSinceResumed.start(),this._hb?(this._acc=this.elapsedTime.getDeltaTime(),this._hb=!1):(this.isBuffering&&this.bufferElapsedTime.start(),this._acc+=this.elapsedTime.getDeltaTime()),!0)}goBufferStart(){return!(!this.isRequested||this.isBuffering)&&(this.isBuffering=!0,this.isPlaying=!1,this.timeSinceBufferBegin.start(),this.bufferElapsedTime.start(),!0)}goBufferEnd(){return!(!this.isRequested||!this.isBuffering)&&(this.isBuffering=!1,this.isPlaying=!0,this.timeSinceBufferBegin.stop(),this._hb?(this._bufferAcc=this.bufferElapsedTime.getDeltaTime(),this._hb=!1):this._bufferAcc+=this.bufferElapsedTime.getDeltaTime(),!this.isAd()&&this.initialBufferingHappened&&(this.totalRebufferingTime+=this.timeSinceBufferBegin.stopTime-this.timeSinceBufferBegin.startTime),!0)}goSeekStart(){return!(!this.isStarted||this.isSeeking)&&(this.isSeeking=!0,this.isPlaying=!1,this.timeSinceSeekBegin.start(),this.timeSinceSeekEnd.reset(),!0)}goSeekEnd(){return!(!this.isStarted||!this.isSeeking)&&(this.isSeeking=!1,this.isPlaying=!0,this.timeSinceSeekBegin.stop(),this.timeSinceSeekEnd.start(),!0)}goAdBreakStart(){return!this.isAdBreak&&(this.isAdBreak=!0,this.timeSinceAdBreakStart.start(),!0)}goAdBreakEnd(){return!!this.isAdBreak&&(this.isRequested=!1,this.isAdBreak=!1,this.totalAdPlaytime=this.timeSinceAdBreakStart.getDeltaTime(),this.timeSinceAdBreakStart.stop(),!0)}goDownload(){this.timeSinceLastDownload.start()}goHeartbeat(){this.timeSinceLastHeartbeat.start()}goRenditionChange(){this.timeSinceLastRenditionChange.start()}goAdQuartile(){this.timeSinceLastAdQuartile.start()}goError(){this.isError=!0,this.numberOfErrors++,this.isAd()?this.timeSinceLastAdError.start():(this.timeSinceLastError.start(),this.isStarted?this.hadPlaybackError=!0:this.hadStartupError=!0)}goLastAd(){this.timeSinceLastAd.start()}trackContentBitrateState(t){if(t&&"number"==typeof t){this.peakBitrate=Math.max(this.peakBitrate,t);const e=Date.now();if(!this.isPlaying){if(null!==this._lastBitrate&&null!==this._lastBitrateChangeTimestamp){const t=e-this._lastBitrateChangeTimestamp;t>0&&(this.partialAverageBitrate+=this._lastBitrate*t,this._totalBitrateDuration+=t),this._lastBitrateChangeTimestamp=null}return void(this._lastBitrate=t)}if(null===this._lastBitrateChangeTimestamp&&null!==this._lastBitrate&&(this._lastBitrateChangeTimestamp=e),null!==this._lastBitrate&&this._lastBitrate!==t&&null!==this._lastBitrateChangeTimestamp){const t=e-this._lastBitrateChangeTimestamp;t>0&&(this.partialAverageBitrate+=this._lastBitrate*t,this._totalBitrateDuration+=t),this._lastBitrateChangeTimestamp=e}null===this._lastBitrateChangeTimestamp&&(this._lastBitrateChangeTimestamp=e),this._lastBitrate=t;let i=this.partialAverageBitrate,s=this._totalBitrateDuration;const r=e-this._lastBitrateChangeTimestamp;r>0&&(i+=t*r,s+=r),this.weightedBitrate=s>0?Math.round(i/s):t}}trackDownloadRate(t){!t||"number"!=typeof t||t<=0||t!==this._lastDownloadBitrate&&(this._downloadBitrates.push(t),this._lastDownloadBitrate=t)}addPlayedRendition(t,e){t&&e&&this._playedRenditions.add(`${t}x${e}`)}resetViewIdTrackedState(){this.peakBitrate=0,this.startupTime=null,this.partialAverageBitrate=0,this._totalBitrateDuration=0,this.weightedBitrate=0,this._lastBitrate=null,this._lastBitrateChangeTimestamp=null,this._downloadBitrates=[],this._lastDownloadBitrate=null,this.totalSwitchUps=0,this.totalSwitchDowns=0,this.timeSincePaused.reset(),this._playedRenditions=new Set}clearTotalAdsTime(){n.debug("clear total ads time",this.totalAdTime),this._totalAdPlaytime.reset()}totalAdTime(){return this._totalAdPlaytime.getDuration()}startAdsTime(){return n.debug("startAdsTime"),this._totalAdPlaytime.start()}stopAdsTime(){return n.debug("stopAdsTime"),this._totalAdPlaytime.stop()}setStartupTime(t){null===this.startupTime&&(this.startupTime=Math.max(this.timeSinceRequested.getDeltaTime()-t,0))}};class k extends m{constructor(t,e){super(),this.state=new D,this.adsTracker=null,this._lastBufferType=null,this._userId=null,this._src=null,e=e||{},this.setOptions(e),t&&this.setPlayer(t,e.tag),n.notice("Tracker "+this.getTrackerName()+" v"+this.getTrackerVersion()+" is ready.")}setUserId(t){this._userId=t}setOptions(t){t&&(t.adsTracker&&this.setAdsTracker(t.adsTracker),"boolean"==typeof t.isAd&&this.setIsAd(t.isAd),void 0!==t.src&&(null!==this._src&&this._src!==t.src?n.warn(`setOptions: src is locked to '${this._src}'. Ignoring override '${t.src}'.`):(this._src=t.src,this.adsTracker&&null==this.adsTracker._src&&(this.adsTracker._src=this._src))),m.prototype.setOptions.apply(this,arguments))}setPlayer(t,e){(this.player||this.tag)&&this.dispose(),"undefined"!=typeof document&&document.getElementById&&("string"==typeof t&&(t=document.getElementById(t)),"string"==typeof e&&(e=document.getElementById(e))),e=e||t,this.player=t,this.tag=e,this.registerListeners()}isAd(){return this.state.isAd()}setIsAd(t){this.state.setIsAd(t)}setAdsTracker(t){this.disposeAdsTracker(),t&&(this.adsTracker=t,this.adsTracker.setIsAd(!0),this.adsTracker.parentTracker=this,null!=this._src&&null==t._src&&(t._src=this._src),this.adsTracker.on("*",N.bind(this)))}disposeAdsTracker(){this.adsTracker&&(this.adsTracker.off("*",N),this.adsTracker.dispose())}dispose(){this.stopHeartbeat(),this.disposeAdsTracker(),this.unregisterListeners(),this.player=null,this.tag=null}registerListeners(){}unregisterListeners(){}getViewId(){return this.parentTracker?this.parentTracker.getViewId():this.state.getViewId()}getViewSession(){return this.parentTracker?this.parentTracker.getViewSession():this.state.getViewSession()}getVideoId(){return null}getTitle(){return null}isLive(){return null}getBitrate(){return null}getManifestBitrate(){return null}getSegmentDownloadBitrate(){return null}getNetworkDownloadBitrate(){return null}getWebkitBitrate(){if(this.tag&&this.tag.webkitVideoDecodedByteCount){let t;if(this._lastWebkitBitrate){t=this.tag.webkitVideoDecodedByteCount;let e=t-this._lastWebkitBitrate,i=this.getHeartbeat()/1e3;t=Math.round(e/i*8)}return this._lastWebkitBitrate=this.tag.webkitVideoDecodedByteCount,t||null}}getRenditionName(){return null}getRenditionBitrate(){return null}getRenditionShift(t){let e,i=this.getManifestBitrate();return this.isAd()?(e=this._lastAdRendition,t&&(this._lastAdRendition=i)):(e=this._lastRendition,t&&(this._lastRendition=i)),i&&e?i>e?"up":i<e?"down":null:null}getRenditionHeight(){return this.tag?this.tag.videoHeight:null}getRenditionWidth(){return this.tag?this.tag.videoWidth:null}getDuration(){return this.tag?this.tag.duration:null}getPlayhead(){return this.tag?this.tag.currentTime:null}getLanguage(){return null}getSrc(){return this.tag?this.tag.currentSrc:null}getPlayrate(){return this.tag?this.tag.playbackRate:null}isMuted(){return this.tag?this.tag.muted:null}isFullscreen(){return null}getCdn(){return null}getPlayerName(){return this.getTrackerName()}getPlayerVersion(){return d.rE}getFps(){return null}isAutoplayed(){return this.tag?this.tag.autoplay:null}getPreload(){return this.tag?this.tag.preload:null}getAdQuartile(){return null}getAdPosition(){return this.parentTracker?this.parentTracker.state.isStarted?"mid":"pre":null}getAdPartner(){return null}getAdCreativeId(){return null}getInstrumentationProvider(){return null}getInstrumentationName(){return null}getInstrumentationVersion(){return null}getAttributes(t,e){if(void 0===(t=m.prototype.getAttributes.apply(this,arguments)).isAd&&(t.isAd=this.isAd()),t.viewSession=this.getViewSession(),t.viewId=this.getViewId(),t.playerName=this.getPlayerName(),t.playerVersion=this.getPlayerVersion(),t["instrumentation.provider"]=this.getInstrumentationProvider(),t["instrumentation.name"]=this.getInstrumentationName(),t["instrumentation.version"]=this.getInstrumentationVersion(),t["enduser.id"]=this._userId,t.src=this._src||"Browser","customAction"===e)return t;try{t.pageUrl=window.location.href}catch(t){}this.isAd()?(t.adId=this.getVideoId(),t.adTitle=this.getTitle(),t.adSrc=this.getSrc(),t.adCdn=this.getCdn(),this.state.isStarted&&(t.adBitrate=this.getBitrate()||0),t.adRenditionName=this.getRenditionName(),t.adRenditionHeight=this.getRenditionHeight(),t.adRenditionWidth=this.getRenditionWidth(),t.adDuration=this.getDuration(),t.adPlayhead=this.getPlayhead(),t.adLanguage=this.getLanguage(),t.adIsMuted=this.isMuted(),t.adFps=this.getFps(),t.adPosition=this.getAdPosition(),t.adCreativeId=this.getAdCreativeId(),t.adPartner=this.getAdPartner()):(t.contentId=this.getVideoId(),t.contentTitle=this.getTitle(),t.contentSrc=this.getSrc(),t.contentCdn=this.getCdn(),t.contentPlayhead=this.getPlayhead(),t.contentIsLive=this.isLive(),this.state.isStarted&&(t.contentBitrate=this.getBitrate()||0,t.contentManifestBitrate=this.getManifestBitrate()||0,t.contentSegmentDownloadBitrate=this.getSegmentDownloadBitrate()||0,t.contentNetworkDownloadBitrate=this.getNetworkDownloadBitrate()||0),t.contentRenditionName=this.getRenditionName(),t.contentRenditionHeight=this.getRenditionHeight(),t.contentRenditionWidth=this.getRenditionWidth(),t.contentDuration=this.getDuration(),t.contentLanguage=this.getLanguage(),t.contentPlayrate=this.getPlayrate(),t.contentIsFullscreen=this.isFullscreen(),t.contentIsMuted=this.isMuted(),t.contentIsAutoplayed=this.isAutoplayed(),t.contentPreload=this.getPreload(),t.contentFps=this.getFps(),null!=this.adsTracker&&this.adsTracker.state.totalAdPlaytime>0&&(t.totalAdPlaytime=this.adsTracker.state.totalAdPlaytime)),this.state.getStateAttributes(t),this.state.isStarted&&!this.isAd()&&(this.state.trackContentBitrateState(t.contentBitrate),this.state.trackDownloadRate(t.contentNetworkDownloadBitrate),this.state.addPlayedRendition(t.contentRenditionHeight,t.contentRenditionWidth));for(let e in this.customData)t[e]=this.customData[e];if(!this.isAd()){this.state.getQoeAttributes(t);const e=t.qoe;for(let t in this.customData)e[t]=this.customData[t]}return t}sendCustom(t,e,i){i=i||{},this.sendVideoCustomAction(t,i),this.state.setTimeSinceAttribute(e)}sendPlayerReady(t){this.state.goPlayerReady()&&(t=t||{},this.sendVideoAction(k.Events.PLAYER_READY,t))}sendRequest(t){if(this.state.goRequest()){let e;this.isAd()?(e=k.Events.AD_REQUEST,this.sendVideoAdAction(e,t)):(e=k.Events.CONTENT_REQUEST,this.sendVideoAction(e,t))}}sendStart(t){if(this.state.goStart()){let e;if(this.isAd())e=k.Events.AD_START,this.parentTracker&&(this.parentTracker.state.isPlaying=!1),this.sendVideoAdAction(e,t),this.state.startAdsTime();else{e=k.Events.CONTENT_START;let i=0;this.adsTracker&&((this.adsTracker.state.isPlaying||this.adsTracker.state.isBuffering)&&(this.adsTracker.state.stopAdsTime(),this.adsTracker.state.isPlaying=!1,this.adsTracker.state.isBuffering=!1),i=this.adsTracker.state.totalAdTime()??0),this.state.setStartupTime(i),this.sendVideoAction(e,t);const s=this.getHarvester?.();s?.setBeforeDrainCallback(()=>{if(this.state){const t=this.state.getQoeAttributes({}).qoe;s.refreshQoeKpis(t,this.getViewId())}})}this.startHeartbeat(),this.state.goHeartbeat()}}sendEnd(t){if(this.state.goEnd()){let e;if(t=t||{},this.isAd()?(e=k.Events.AD_END,t.timeSinceAdRequested=this.state.timeSinceRequested.getDeltaTime(),t.timeSinceAdStarted=this.state.timeSinceStarted.getDeltaTime(),this.parentTracker&&(this.parentTracker.state.isPlaying=!0,this.parentTracker.state.timeSincePaused.reset()),this.state.stopAdsTime()):(e=k.Events.CONTENT_END,t.timeSinceRequested=this.state.timeSinceRequested.getDeltaTime(),t.timeSinceStarted=this.state.timeSinceStarted.getDeltaTime()),this.stopHeartbeat(),this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t),this.parentTracker&&this.isAd()&&this.parentTracker.state.goLastAd(),this.state.goViewCountUp(),this.state.totalPlaytime=0,!this.isAd()){const t=this.getHarvester?.();t?.forceNextQoeCycle?.(),t?.setBeforeDrainCallback?.(null),this.adsTracker&&this.adsTracker.state.clearTotalAdsTime(),this.state.resetViewIdTrackedState()}}}sendPause(t){if(this.state.goPause()){let e=this.isAd()?k.Events.AD_PAUSE:k.Events.CONTENT_PAUSE;this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendResume(t){if(this.state.goResume()){let e;t=t||{},this.isAd()?(e=k.Events.AD_RESUME,t.timeSinceAdPaused=this.state.timeSincePaused.getDeltaTime()):(e=k.Events.CONTENT_RESUME,t.timeSincePaused=this.state.timeSincePaused.getDeltaTime()),this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendBufferStart(t){if(this.state.goBufferStart()){let e;t=t||{},e=this.isAd()?k.Events.AD_BUFFER_START:k.Events.CONTENT_BUFFER_START,t=this.buildBufferAttributes(t),this._lastBufferType=t.bufferType,this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendBufferEnd(t){if(this.state.goBufferEnd()){let e;t=t||{},this.isAd()?(e=k.Events.AD_BUFFER_END,t.timeSinceAdBufferBegin=this.state.timeSinceBufferBegin.getDeltaTime()):(e=k.Events.CONTENT_BUFFER_END,t.timeSinceBufferBegin=this.state.timeSinceBufferBegin.getDeltaTime()),t=this.buildBufferAttributes(t),null!=this._lastBufferType&&(t.bufferType=this._lastBufferType),this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t),this.state.initialBufferingHappened=!0}}buildBufferAttributes(t){return null==t.timeSinceStarted||t.timeSinceStarted<100?t.isInitialBuffering=!this.state.initialBufferingHappened:t.isInitialBuffering=!1,t.bufferType=this.state.calculateBufferType(t.isInitialBuffering),t.timeSinceResumed=this.state.timeSinceResumed.getDeltaTime(),t.timeSinceSeekEnd=this.state.timeSinceSeekEnd.getDeltaTime(),t}sendSeekStart(t){if(this.state.goSeekStart()){let e;e=this.isAd()?k.Events.AD_SEEK_START:k.Events.CONTENT_SEEK_START,this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendSeekEnd(t){if(this.state.goSeekEnd()){let e;t=t||{},this.isAd()?(e=k.Events.AD_SEEK_END,t.timeSinceAdSeekBegin=this.state.timeSinceSeekBegin.getDeltaTime()):(e=k.Events.CONTENT_SEEK_END,t.timeSinceSeekBegin=this.state.timeSinceSeekBegin.getDeltaTime()),this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendDownload(t){(t=t||{}).state||n.warn("Called sendDownload without { state: xxxxx }."),this.sendVideoAction(k.Events.DOWNLOAD,t),this.state.goDownload()}sendError(t){(t=t||{}).isAd=this.isAd(),this.state.goError();let e=this.isAd()?k.Events.AD_ERROR:k.Events.CONTENT_ERROR;this.sendVideoErrorAction(e,t)}sendRenditionChanged(t){(t=t||{}).timeSinceLastRenditionChange=this.state.timeSinceLastRenditionChange.getDeltaTime();const{oldBitrate:e,newBitrate:i}=t;let s;this.isAd()||void 0===e||void 0===i||(i>e?(t.shift="up",this.state.totalSwitchUps+=1):i<e?(t.shift="down",this.state.totalSwitchDowns+=1):t.shift=null),delete t.oldBitrate,delete t.newBitrate,s=this.isAd()?k.Events.AD_RENDITION_CHANGE:k.Events.CONTENT_RENDITION_CHANGE,this.isAd()?this.sendVideoAdAction(s,t):this.sendVideoAction(s,t),this.state.goRenditionChange()}sendHeartbeat(t){if(this.state.isRequested){let e,i=this.getHeartbeat();this.state._hb=!0,i=this.adjustElapsedTimeForPause(i),this.isAd()?(e=k.Events.AD_HEARTBEAT,"bitmovin-ads"===this.getPlayerName()?this.sendVideoAdAction(e,t):this.sendVideoAdAction(e,{elapsedTime:i,...t})):(e=k.Events.CONTENT_HEARTBEAT,this.sendVideoAction(e,{elapsedTime:i,...t})),this.state.goHeartbeat()}}adjustElapsedTimeForPause(t){return this.state._acc&&(t-=this.state._acc,this.state._acc=0),this.state.isPaused&&((t-=this.state.elapsedTime.getDeltaTime())<10&&(t=0),this.state.elapsedTime.start()),this.state._bufferAcc?(t-=this.state._bufferAcc,this.state._bufferAcc=0):this.state.isBuffering&&((t-=this.state.bufferElapsedTime.getDeltaTime())<5&&(t=0),this.state.bufferElapsedTime.start()),Math.max(0,t)}sendAdBreakStart(t){this.isAd()&&this.state.goAdBreakStart()&&(this.state.totalAdPlaytime=0,this.parentTracker&&(this.parentTracker.state.isPlaying=!1),this.sendVideoAdAction(k.Events.AD_BREAK_START,t))}sendAdBreakEnd(t){this.isAd()&&this.state.goAdBreakEnd()&&((t=t||{}).timeSinceAdBreakBegin=this.state.timeSinceAdBreakStart.getDeltaTime(),this.sendVideoAdAction(k.Events.AD_BREAK_END,t),this.parentTracker&&(this.parentTracker.state.isPlaying=!0),this.stopHeartbeat(),this.parentTracker&&this.isAd()&&this.parentTracker.state.goLastAd())}sendAdQuartile(t){this.isAd()&&((t=t||{}).quartile||n.warn("Called sendAdQuartile without { quartile: xxxxx }."),t.timeSinceLastAdQuartile=this.state.timeSinceLastAdQuartile.getDeltaTime(),this.sendVideoAdAction(k.Events.AD_QUARTILE,t),this.state.goAdQuartile())}sendAdClick(t){this.isAd()&&((t=t||{}).url||n.warn("Called sendAdClick without { url: xxxxx }."),this.sendVideoAdAction(k.Events.AD_CLICK,t))}}function N(t){t.type!==k.Events.AD_ERROR?this.sendVideoAdAction(t.type,t.data):this.sendVideoErrorAction(t.type,t.data)}k.Events={PLAYER_READY:"PLAYER_READY",DOWNLOAD:"DOWNLOAD",ERROR:"ERROR",CONTENT_REQUEST:"CONTENT_REQUEST",CONTENT_START:"CONTENT_START",CONTENT_END:"CONTENT_END",CONTENT_PAUSE:"CONTENT_PAUSE",CONTENT_RESUME:"CONTENT_RESUME",CONTENT_SEEK_START:"CONTENT_SEEK_START",CONTENT_SEEK_END:"CONTENT_SEEK_END",CONTENT_BUFFER_START:"CONTENT_BUFFER_START",CONTENT_BUFFER_END:"CONTENT_BUFFER_END",CONTENT_HEARTBEAT:"CONTENT_HEARTBEAT",CONTENT_RENDITION_CHANGE:"CONTENT_RENDITION_CHANGE",CONTENT_ERROR:"CONTENT_ERROR",AD_REQUEST:"AD_REQUEST",AD_START:"AD_START",AD_END:"AD_END",AD_PAUSE:"AD_PAUSE",AD_RESUME:"AD_RESUME",AD_SEEK_START:"AD_SEEK_START",AD_SEEK_END:"AD_SEEK_END",AD_BUFFER_START:"AD_BUFFER_START",AD_BUFFER_END:"AD_BUFFER_END",AD_HEARTBEAT:"AD_HEARTBEAT",AD_RENDITION_CHANGE:"AD_RENDITION_CHANGE",AD_ERROR:"AD_ERROR",AD_BREAK_START:"AD_BREAK_START",AD_BREAK_END:"AD_BREAK_END",AD_QUARTILE:"AD_QUARTILE",AD_CLICK:"AD_CLICK"};const C=k,{MAX_PAYLOAD_SIZE:O,MAX_EVENTS_PER_BATCH:I}=h;class P{constructor(){this.buffer=[],this.maxPayloadSize=O,this.maxEventsPerBatch=I,this.currentPayloadSize=0,this.totalEvents=0,this.smartHarvestPayloadThreshold=Math.floor(.6*this.maxPayloadSize),this.overflowPayloadThreshold=Math.floor(.9*this.maxPayloadSize),this.smartHarvestEventThreshold=Math.floor(.6*this.maxEventsPerBatch),this.overflowEventThreshold=Math.floor(.9*this.maxEventsPerBatch),this.onSmartHarvestTrigger=null}addOrReplaceByActionName(t,e){const i=this.buffer.findIndex(e=>e.actionName===t);try{return-1===i?this.add(e):this.add(e,i),!0}catch(t){return n.error("Failed to set or replace the event to buffer:",t.message),!1}}addOrReplaceByActionNameAndViewId(t,e,i){const s=this.buffer.findIndex(i=>i.actionName===t&&i.viewId===e);try{return-1===s?this.add(i):this.add(i,s),!0}catch(t){return n.error("Failed to set or replace the event to buffer:",t.message),!1}}findByActionNameAndViewId(t,e){return this.buffer.find(i=>i.actionName===t&&i.viewId===e)||null}findByActionName(t){return this.buffer.find(e=>e.actionName===t)||null}add(t,e){try{const i=E(t),s=this.currentPayloadSize+i>=this.maxPayloadSize,r=this.totalEvents+1>=this.maxEventsPerBatch;if((s||r)&&this.makeRoom(i),null!=e&&e>-1){const s=E(this.buffer[e]);this.buffer[e]=t,this.currentPayloadSize+=i-s}else this.buffer.push(t),this.totalEvents++,this.currentPayloadSize+=i;return this.checkSmartHarvestTrigger(),!0}catch(t){return n.error("Failed to add event to buffer:",t.message),!1}}checkSmartHarvestTrigger(){const t=this.currentPayloadSize/this.maxPayloadSize,e=this.totalEvents/this.maxEventsPerBatch,i=this.currentPayloadSize>=this.overflowPayloadThreshold,s=this.totalEvents>=this.overflowEventThreshold;if(i||s){const s=i?`payload ${this.currentPayloadSize}/${this.maxPayloadSize} bytes (${Math.round(100*t)}%)`:`events ${this.totalEvents}/${this.maxEventsPerBatch} (${Math.round(100*e)}%)`;n.warn(`OVERFLOW PREVENTION: ${s} - Emergency harvest triggered`),this.onSmartHarvestTrigger&&"function"==typeof this.onSmartHarvestTrigger&&this.onSmartHarvestTrigger("overflow",90)}else{const t=this.currentPayloadSize>=this.smartHarvestPayloadThreshold,e=this.totalEvents>=this.smartHarvestEventThreshold;(t||e)&&this.onSmartHarvestTrigger&&"function"==typeof this.onSmartHarvestTrigger&&this.onSmartHarvestTrigger("smart",60)}}setSmartHarvestCallback(t){this.onSmartHarvestTrigger=t}drain(){try{const t=this.buffer.splice(0);return this.totalEvents=0,this.currentPayloadSize=0,t}catch(t){return n.error("Failed to drain events from buffer:",t.message),[]}}isEmpty(){return 0===this.totalEvents}size(){return this.totalEvents}clear(){this.buffer=[],this.totalEvents=0}makeRoom(t){if(t>this.maxPayloadSize)n.error("Event dropped: Event size exceeds maximum payload size.");else for(;(this.totalEvents>=this.maxEventsPerBatch||this.currentPayloadSize+t>=this.maxPayloadSize)&&this.buffer.length>0;){const t=E(this.buffer.shift());this.totalEvents--,this.currentPayloadSize-=t,n.warn("Event buffer full, oldest event removed.")}}}const{MAX_PAYLOAD_SIZE:V,MAX_EVENTS_PER_BATCH:L}=h;class H{constructor(){this.retryQueue=[],this.maxQueueSize=L,this.maxQueueSizeBytes=V}addFailedEvents(t){try{const e=Array.isArray(t)?t:[t];n.notice(`Adding ${e.length} failed events to retry queue`,{queueSizeBefore:this.retryQueue.length});for(const t of e){this.retryQueue.length>=this.maxQueueSize&&this.evictOldestEvent();const e=E(t);for(;E(this.retryQueue)+e>this.maxQueueSizeBytes;)this.evictOldestEvent();this.retryQueue.push({...t})}}catch(t){n.error("Failed to add events to retry queue:",t.message)}}discardEvent(t,e){n.warn("Discarded event",{reason:e,eventType:t.eventType})}evictOldestEvent(){if(this.retryQueue.length>0){const t=this.retryQueue.shift();this.discardEvent(t,"Queue full - evicted oldest")}}getRetryEventsToFit(t,e){const i=[];let s=0,r=0;for(let a=this.retryQueue.length-1;a>=0;a--){const n=this.retryQueue[a];if(r>=e)break;const o=E(n);if(s+o>t)break;i.unshift(n),s+=o,r++,this.retryQueue.splice(a,1)}return i}getQueueSize(){return this.retryQueue.length}clear(){this.retryQueue=[]}}class F{async send(t,e){const{url:i,payload:s,options:r={}}=t;try{if(!i||!s)throw new Error("URL and payload are required");const t={url:i,payload:s,options:r,callback:e};await this.executeRequest(t)}catch(t){n.error("Failed to send request:",t.message),e({retry:!1,status:0,error:t.message})}}async executeRequest(t){const{url:e,payload:i,options:s,callback:r}=t,a=Date.now();try{const r=(o=JSON.stringify(i.body),h=window.NRVIDEO?.config?.obfuscate,h&&0!==h.length?h.reduce((t,e)=>{let i;try{if(e.regex instanceof RegExp){const t=e.regex.flags.includes("g")?e.regex.flags:e.regex.flags+"g";i=new RegExp(e.regex.source,t)}else i=new RegExp(e.regex,"g")}catch(i){return n.warn("applyObfuscationRules: invalid regex, skipping rule:",e.regex,i.message),t}return t.replace(i,e.replacement)},o):o);if(s.isFinalHarvest&&navigator.sendBeacon){const i=await this.sendWithBeacon(e,r),s={success:i,status:i?204:0};return void this.handleRequestComplete(t,s,a)}const d=await this.fetchWithTimeout(e,{method:"POST",body:r,headers:{"Content-Type":"application/json"},keepalive:s.isFinalHarvest},1e4),l={success:d.ok,status:d.status,statusText:d.statusText};this.handleRequestComplete(t,l,a)}catch(e){const i={success:!1,status:0,error:e.message};this.handleRequestComplete(t,i,a)}var o,h}handleRequestComplete(t,e){const{callback:i}=t;i({retry:!e.success&&(0===e.status||function(t){switch(t){case 408:case 429:case 500:return!0;case 401:case 403:case 404:return!1}return t>=502&&t<=504||t>=512&&t<=530}(e.status)),status:e.status,error:e.error})}async sendWithBeacon(t,e){try{return navigator.sendBeacon(t,e)}catch(t){return n.warn("sendBeacon failed, falling back to fetch:",t.message),!1}}async fetchWithTimeout(t,e,i){const s=new AbortController,r=setTimeout(()=>s.abort(),i);try{const i=await fetch(t,{...e,signal:s.signal});return clearTimeout(r),i}catch(t){if(clearTimeout(r),"AbortError"===t.name)throw new Error(`Request timeout after ${i}ms`);throw t}}}function Q(t,e){const i=t[e.viewId];if(!i)return!1;for(const t of h.QOE_KPI_KEYS)if(e[t]!==i[t])return!1;return!0}function x(t,e){const i={};for(const t of h.QOE_KPI_KEYS)i[t]=e[t];t[e.viewId]=i}class q{constructor(t){this.eventBuffer=t,this.retryQueueHandler=new H,this.httpClient=new F,this.fallBackUrl="",this.retryCount=0,this.eventBuffer instanceof P&&this.eventBuffer.setSmartHarvestCallback((t,e)=>this.triggerSmartHarvest(t,e)),this.harvestCycle=h.INTERVAL,this.isHarvesting=!1,this.qoeCycleCount=1,this.forceNextQoeCycle=!1,this.beforeDrainCallback=null,this._lastSentQoeKpis={},this.timer=function({interval:t,onTick:e,errorLabel:i}){let s=!1,r=null,a=t;function o(){s&&(r=setTimeout(async()=>{r=null;try{await e()}catch(t){n.error(`${i}: scheduled tick failed:`,t.message)}finally{s&&o()}},a))}return{start(){s||(s=!0,o())},stop(){s=!1,r&&(clearTimeout(r),r=null)},cancelAndReschedule(){r&&(clearTimeout(r),r=null),s&&o()},updateInterval(t){"number"!=typeof t||t<=0||(a=t,s&&r&&(clearTimeout(r),r=null,o()))},isRunning:()=>s}}({interval:this.harvestCycle,onTick:()=>this.onHarvestInterval(),errorLabel:"HarvestScheduler"}),this.setupPageLifecycleHandlers()}get isStarted(){return this.timer.isRunning()}startScheduler(){this.timer.isRunning()?n.warn("Harvest scheduler is already started"):(n.notice("Starting harvest scheduler",{harvestCycle:this.harvestCycle,eventBufferSize:this.eventBuffer?this.eventBuffer.size():0}),this.timer.start())}stopScheduler(){this.timer.isRunning()&&(this.timer.stop(),n.notice("Harvest scheduler stopped"))}async triggerSmartHarvest(t,e){if(n.notice(`${t} harvest triggered at ${e}% threshold`,{type:t,threshold:e}),this.eventBuffer&&!this.eventBuffer.isEmpty())try{await this.triggerHarvest({})}catch(e){n.error(`${t} harvest failed:`,e.message)}finally{this.timer.cancelAndReschedule()}}async onHarvestInterval(){const t=this.eventBuffer&&!this.eventBuffer.isEmpty(),e=this.retryQueueHandler&&this.retryQueueHandler.getQueueSize()>0;(t||e)&&await this.triggerHarvest({})}async triggerHarvest(t={}){if(this.isHarvesting)return{success:!1,reason:"harvest_in_progress"};this.isHarvesting=!0;try{let e=this.drainEvents(t);if(t.isFinalHarvest){const t=h.MAX_BEACON_SIZE;E(e)>t&&(e=this.trimEventsToFit(e,t))}const i=await this.sendChunk(e,t,!0);return{success:i.success,totalChunks:1,results:[i]}}catch(t){return n.error("Harvest cycle failed:",t.message),this.handleHarvestFailure(t),{success:!1,error:t.message}}finally{this.isHarvesting=!1}}trimEventsToFit(t,e){if(0===t.length)return t;const i=[];let s=0;for(let r=t.length-1;r>=0;r--){const a=t[r],n=E({ins:[a,...i]});n>e||(i.unshift(a),s=n)}const r=t.length-i.length;if(r>0){const a=t.slice(0,r);n.warn(`Discarded ${r} events to fit beacon size limit`,{originalCount:t.length,trimmedCount:i.length,finalSize:s,maxSize:e}),this.retryQueueHandler&&this.retryQueueHandler.addFailedEvents(a)}return i}drainEvents(t={}){const e=window.NRVIDEO?.config?.qoeIntervalFactor??1,i=!!t.isFinalHarvest||this.forceNextQoeCycle,s=(this.qoeCycleCount-1)%e==0||i;if(this.forceNextQoeCycle&&(this.forceNextQoeCycle=!1),this.beforeDrainCallback&&"function"==typeof this.beforeDrainCallback)try{this.beforeDrainCallback()}catch(t){n.error("Before drain callback failed:",t.message)}let r=function(t,e,i){if(e)return t;const s=[];for(const e of t)e.actionName===m.Events.QOE_AGGREGATE?i.add(e):s.push(e);return s}(this.eventBuffer.drain(),s,this.eventBuffer);this.qoeCycleCount++,function(t,e,i){for(let s=t.length-1;s>=0;s--){const r=t[s];r.actionName===m.Events.QOE_AGGREGATE&&(!i&&Q(e,r)?t.splice(s,1):x(e,r))}}(r,this._lastSentQoeKpis,i);let a=[...r],o=E(r);if(this.retryQueueHandler&&this.retryQueueHandler.getQueueSize()>0){const t=h.MAX_PAYLOAD_SIZE-o,e=h.MAX_EVENTS_PER_BATCH-a.length;if(t>0&&e>0){const i=this.retryQueueHandler.getRetryEventsToFit(t,e);i.length>0&&(a=[...i,...a])}}return a}async sendChunk(t,e,i){const s={url:function(t){try{if(!window.NRVIDEO||!window.NRVIDEO.info)throw new Error("NRVIDEO info is not available.");let{beacon:e,licenseKey:i,applicationID:s}=window.NRVIDEO.info;if(!e||!i)throw new Error("Options object provided by New Relic is not correctly initialized");return s?`https://${t||e}/ins/1/${i}?a=${s}&v=${d.rE}&ref=${window.location.href}&ca=VA`:`https://${t||e}/ins/1/${i}?&v=${d.rE}&ref=${window.location.href}&ca=VA`}catch(t){return console.error(t.message),null}}(this.fallBackUrl),payload:{body:{ins:t}},options:{...e,isLastChunk:i}};return new Promise(e=>{this.httpClient.send(s,i=>{i.retry?this.handleRequestFailure(t):(this.retryCount=0,this.fallBackUrl=""),e({success:!i.retry,status:i.status,error:i.error,chunk:t,eventCount:t.length})})})}handleRequestFailure(t){this.retryQueueHandler.addFailedEvents(t),"US"===window.NRVIDEO?.info?.region&&(this.retryCount++,this.retryCount>5?(this.retryCount=0,this.fallBackUrl=""):this.retryCount>=2&&(this.fallBackUrl=h.COLLECTOR.US[1]))}handleHarvestFailure(t){n.warn("Harvest failure handled",{error:t.message})}updateHarvestInterval(t){"number"!=typeof t||isNaN(t)?n.warn("Invalid newInterval provided to updateHarvestInterval"):t<1e3||t>3e5?n.warn("newInterval out of bounds (1000-300000), ignoring"):this.harvestCycle!==t&&(this.harvestCycle=t,n.notice("Updated harvestCycle:",this.harvestCycle),this.timer.updateInterval(t))}setupPageLifecycleHandlers(){let t=!1;const e=()=>{t||(t=!0,this.triggerHarvest({isFinalHarvest:!0,force:!0}))};document.addEventListener("visibilitychange",()=>{document.hidden&&e()}),window.addEventListener("pagehide",()=>{e()}),window.addEventListener("beforeunload",()=>{e()})}}const U=new class{constructor(){this.isInitialized=!1,this.harvestScheduler=null,this.eventBuffer=null}initialize(){if(this.isInitialized)n.warn("Video analytics agent already initialized");else try{this.eventBuffer=new P,this.harvestScheduler=new q(this.eventBuffer),this.harvestScheduler.startScheduler(),this.isInitialized=!0,n.notice("Video analytics agent initialized successfully")}catch(t){n.error("Failed to initialize video analytics agent:",t.message)}}addEvent(t){this.isInitialized||(n.warn("Video analytics agent not initialized, initializing now"),this.initialize());try{return function(t,e){return!!e&&(e.actionName===m.Events.QOE_AGGREGATE?e.viewId?t.addOrReplaceByActionNameAndViewId(m.Events.QOE_AGGREGATE,e.viewId,e):t.addOrReplaceByActionName(m.Events.QOE_AGGREGATE,e):t.add(e))}(this.eventBuffer,t)}catch(t){return n.error("Failed to add event to harvesting system:",t.message),!1}}setHarvestInterval(t){this.isInitialized||this.initialize(),this.harvestScheduler.updateHarvestInterval(t)}forceNextQoeCycle(){this.harvestScheduler&&(this.harvestScheduler.forceNextQoeCycle=!0)}setBeforeDrainCallback(t){this.harvestScheduler&&(this.harvestScheduler.beforeDrainCallback=t)}refreshQoeKpis(t,e){!function(t,e,i){if(!t||!e)return;const s=i?t.findByActionNameAndViewId(m.Events.QOE_AGGREGATE,i):t.findByActionName(m.Events.QOE_AGGREGATE);if(!s)return;const r={...s};for(const t of h.QOE_KPI_KEYS)t in e&&(r[t]=e[t]);i?t.addOrReplaceByActionNameAndViewId(m.Events.QOE_AGGREGATE,i,r):t.addOrReplaceByActionName(m.Events.QOE_AGGREGATE,r)}(this.eventBuffer,t,e)}};var z;z=U,T["Browser"]=z;const G=U,M={Constants:h,Chrono:u,Log:n,Emitter:l,Tracker:m,VideoTracker:C,VideoTrackerState:D,Core:w,version:d.rE,NrVideoEventAggregator:P,RetryQueueHandler:H,OptimizedHttpClient:F,HarvestScheduler:q,recordEvent:v};module.exports=e})();
|
|
3
|
+
//# sourceMappingURL=index.js.map
|