@newrelic/video-core 4.1.8 → 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/README.md +140 -27
- 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 +25 -7
- package/src/{agent.js → browser/agent.js} +14 -35
- package/src/{harvestScheduler.js → browser/harvestScheduler.js} +55 -137
- 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 +2 -0
- package/src/core.js +4 -18
- package/src/index.js +9 -10
- 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 +56 -10
- package/src/videotracker.js +26 -9
|
@@ -15,18 +15,42 @@ class VideoConfiguration {
|
|
|
15
15
|
* @returns {boolean} True if configuration is valid and set
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
setConfiguration(userInfo, config) {
|
|
19
|
-
|
|
18
|
+
setConfiguration(userInfo, config, src) {
|
|
19
|
+
const validated = src === "Vega"
|
|
20
|
+
? this.validateVegaFields(userInfo)
|
|
21
|
+
: this.validateRequiredFields(userInfo);
|
|
22
|
+
if (!validated) {
|
|
20
23
|
return false;
|
|
21
24
|
}
|
|
22
25
|
if (!this.validateConfigFields(config)) {
|
|
23
26
|
return false;
|
|
24
27
|
}
|
|
25
|
-
this.initializeGlobalConfig(userInfo, config);
|
|
28
|
+
this.initializeGlobalConfig(userInfo, config, src);
|
|
26
29
|
Log.notice("Video analytics configuration initialized successfully");
|
|
27
30
|
return true;
|
|
28
31
|
}
|
|
29
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Validates required Vega configuration fields.
|
|
35
|
+
* @param {object} info
|
|
36
|
+
* @returns {boolean} True if valid
|
|
37
|
+
*/
|
|
38
|
+
validateVegaFields(info) {
|
|
39
|
+
if (!info || typeof info !== "object") {
|
|
40
|
+
Log.error("Configuration must be an object");
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
if (!info.applicationToken) {
|
|
44
|
+
Log.error("applicationToken is required");
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
if (!["US", "EU", "staging", "GOV"].includes(info.endpoint)) {
|
|
48
|
+
Log.error("Invalid endpoint (must be US, EU, staging, or GOV)");
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
30
54
|
/**
|
|
31
55
|
* Validates required configuration fields.
|
|
32
56
|
* @param {object} config - Configuration to validate
|
|
@@ -126,15 +150,16 @@ class VideoConfiguration {
|
|
|
126
150
|
}
|
|
127
151
|
|
|
128
152
|
/**
|
|
129
|
-
* Sanitizes qoeIntervalFactor, defaulting to
|
|
153
|
+
* Sanitizes qoeIntervalFactor, defaulting to Constants.DEFAULT_QOE_INTERVAL_FACTOR
|
|
154
|
+
* if the value is not a positive integer.
|
|
130
155
|
* @param {*} value
|
|
131
156
|
* @returns {number}
|
|
132
157
|
*/
|
|
133
158
|
sanitizeQoeIntervalFactor(value) {
|
|
134
|
-
if (value === undefined || value === null) return
|
|
159
|
+
if (value === undefined || value === null) return Constants.DEFAULT_QOE_INTERVAL_FACTOR;
|
|
135
160
|
if (typeof value === "number" && Number.isInteger(value) && value >= 1) return value;
|
|
136
|
-
Log.warn(`Invalid qoeIntervalFactor "${value}" — must be a positive integer. Defaulting to
|
|
137
|
-
return
|
|
161
|
+
Log.warn(`Invalid qoeIntervalFactor "${value}" — must be a positive integer. Defaulting to ${Constants.DEFAULT_QOE_INTERVAL_FACTOR}.`);
|
|
162
|
+
return Constants.DEFAULT_QOE_INTERVAL_FACTOR;
|
|
138
163
|
}
|
|
139
164
|
|
|
140
165
|
/**
|
|
@@ -142,7 +167,28 @@ class VideoConfiguration {
|
|
|
142
167
|
* @param {object} userInfo - User provided configuration
|
|
143
168
|
* @param {object} [config] - Optional configuration object
|
|
144
169
|
*/
|
|
145
|
-
initializeGlobalConfig(userInfo, config) {
|
|
170
|
+
initializeGlobalConfig(userInfo, config, src) {
|
|
171
|
+
// Vega path: write `globalThis.__NRVIDEO_CD__` with info+config only.
|
|
172
|
+
// The harvester is owned by `connectedDeviceAgent.js` as a module singleton — no
|
|
173
|
+
// harvester field on this global.
|
|
174
|
+
if (src === "Vega") {
|
|
175
|
+
globalThis.__NRVIDEO_CD__ = {
|
|
176
|
+
info: {
|
|
177
|
+
accountId: userInfo.accountId,
|
|
178
|
+
applicationToken: userInfo.applicationToken,
|
|
179
|
+
endpoint: userInfo.endpoint,
|
|
180
|
+
...(userInfo.appName ? { appName: userInfo.appName } : {}),
|
|
181
|
+
...(userInfo.applicationID ? { applicationID: userInfo.applicationID } : {}),
|
|
182
|
+
...(userInfo.deviceInfo ? { deviceInfo: userInfo.deviceInfo } : {}),
|
|
183
|
+
},
|
|
184
|
+
config: {
|
|
185
|
+
qoeAggregate: config?.qoeAggregate ?? true,
|
|
186
|
+
qoeIntervalFactor: this.sanitizeQoeIntervalFactor(config?.qoeIntervalFactor),
|
|
187
|
+
obfuscate: this.filterObfuscateRules(config?.obfuscate),
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
146
192
|
|
|
147
193
|
let { licenseKey, appName, region, beacon, applicationID } = userInfo;
|
|
148
194
|
|
|
@@ -179,8 +225,8 @@ const videoConfiguration = new VideoConfiguration();
|
|
|
179
225
|
* @param {object} [config] - Optional configuration object
|
|
180
226
|
* @returns {boolean} True if configuration was set successfully
|
|
181
227
|
*/
|
|
182
|
-
export function setVideoConfig(info, config) {
|
|
183
|
-
return videoConfiguration.setConfiguration(info, config);
|
|
228
|
+
export function setVideoConfig(info, config, src) {
|
|
229
|
+
return videoConfiguration.setConfiguration(info, config, src);
|
|
184
230
|
}
|
|
185
231
|
|
|
186
232
|
export { videoConfiguration };
|
package/src/videotracker.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import Log from "./log";
|
|
2
2
|
import Tracker from "./tracker";
|
|
3
3
|
import TrackerState from "./videotrackerstate";
|
|
4
|
-
import { videoAnalyticsHarvester } from "./agent";
|
|
5
4
|
import pkg from "../package.json";
|
|
6
5
|
|
|
7
6
|
/**
|
|
@@ -45,6 +44,7 @@ class VideoTracker extends Tracker {
|
|
|
45
44
|
*/
|
|
46
45
|
this._lastBufferType = null;
|
|
47
46
|
this._userId = null;
|
|
47
|
+
this._src = null;
|
|
48
48
|
|
|
49
49
|
options = options || {};
|
|
50
50
|
this.setOptions(options);
|
|
@@ -84,6 +84,16 @@ class VideoTracker extends Tracker {
|
|
|
84
84
|
if (typeof options.isAd === "boolean") {
|
|
85
85
|
this.setIsAd(options.isAd);
|
|
86
86
|
}
|
|
87
|
+
if (options.src !== undefined) {
|
|
88
|
+
if (this._src !== null && this._src !== options.src) {
|
|
89
|
+
Log.warn(`setOptions: src is locked to '${this._src}'. Ignoring override '${options.src}'.`);
|
|
90
|
+
} else {
|
|
91
|
+
this._src = options.src;
|
|
92
|
+
if (this.adsTracker && this.adsTracker._src == null) {
|
|
93
|
+
this.adsTracker._src = this._src;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
87
97
|
Tracker.prototype.setOptions.apply(this, arguments);
|
|
88
98
|
}
|
|
89
99
|
}
|
|
@@ -135,6 +145,12 @@ class VideoTracker extends Tracker {
|
|
|
135
145
|
this.adsTracker = tracker;
|
|
136
146
|
this.adsTracker.setIsAd(true);
|
|
137
147
|
this.adsTracker.parentTracker = this;
|
|
148
|
+
// Propagate src so ads events route to the same pipeline as content events.
|
|
149
|
+
// Covers the case where setAdsTracker is called after the content tracker
|
|
150
|
+
// is fully initialised and this._src is already set.
|
|
151
|
+
if (this._src != null && tracker._src == null) {
|
|
152
|
+
tracker._src = this._src;
|
|
153
|
+
}
|
|
138
154
|
this.adsTracker.on("*", funnelAdEvents.bind(this));
|
|
139
155
|
}
|
|
140
156
|
}
|
|
@@ -465,7 +481,7 @@ class VideoTracker extends Tracker {
|
|
|
465
481
|
att["instrumentation.name"] = this.getInstrumentationName();
|
|
466
482
|
att["instrumentation.version"] = this.getInstrumentationVersion();
|
|
467
483
|
att["enduser.id"] = this._userId;
|
|
468
|
-
att["src"] = "Browser";
|
|
484
|
+
att["src"] = this._src || "Browser";
|
|
469
485
|
|
|
470
486
|
if (type === "customAction") return att;
|
|
471
487
|
|
|
@@ -639,11 +655,11 @@ class VideoTracker extends Tracker {
|
|
|
639
655
|
this.state.setStartupTime(totalAdsTime)
|
|
640
656
|
this.sendVideoAction(ev, att);
|
|
641
657
|
|
|
642
|
-
|
|
643
|
-
|
|
658
|
+
const harvester = this.getHarvester?.();
|
|
659
|
+
harvester?.setBeforeDrainCallback(() => {
|
|
644
660
|
if (this.state) {
|
|
645
661
|
const freshKpis = this.state.getQoeAttributes({}).qoe;
|
|
646
|
-
|
|
662
|
+
harvester.refreshQoeKpis(freshKpis, this.getViewId());
|
|
647
663
|
}
|
|
648
664
|
});
|
|
649
665
|
}
|
|
@@ -688,14 +704,15 @@ class VideoTracker extends Tracker {
|
|
|
688
704
|
this.state.goViewCountUp();
|
|
689
705
|
this.state.totalPlaytime = 0;
|
|
690
706
|
if(!this.isAd()) {
|
|
707
|
+
const harvester = this.getHarvester?.();
|
|
691
708
|
// Force QoE to be included in the next harvest cycle at content end
|
|
692
|
-
|
|
709
|
+
harvester?.forceNextQoeCycle?.();
|
|
693
710
|
// Clear the before-drain callback so the next harvest doesn't overwrite
|
|
694
711
|
// the final QoE (already in buffer) with zeroed-out state values
|
|
695
|
-
|
|
712
|
+
harvester?.setBeforeDrainCallback?.(null);
|
|
696
713
|
// reset the states after the view count is up
|
|
697
|
-
|
|
698
|
-
|
|
714
|
+
if(this.adsTracker) this.adsTracker.state.clearTotalAdsTime();
|
|
715
|
+
this.state.resetViewIdTrackedState();
|
|
699
716
|
}
|
|
700
717
|
}
|
|
701
718
|
}
|