@newrelic/video-core 3.2.0-beta-0 → 4.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 +12 -3
- package/README.md +17 -39
- package/dist/cjs/index.js +3 -0
- package/dist/cjs/index.js.LICENSE.txt +6 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.LICENSE.txt +6 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/umd/nrvideo.min.js +3 -0
- package/dist/umd/nrvideo.min.js.LICENSE.txt +8 -0
- package/dist/umd/nrvideo.min.js.map +1 -0
- package/package.json +6 -4
- package/src/agent.js +74 -5
- package/src/constants.js +15 -13
- package/src/core.js +59 -15
- package/src/eventAggregator.js +189 -37
- package/src/harvestScheduler.js +416 -0
- package/src/index.js +21 -0
- package/src/optimizedHttpClient.js +165 -0
- package/src/recordEvent.js +23 -50
- package/src/retryQueueHandler.js +124 -0
- package/src/tracker.js +23 -6
- package/src/utils.js +124 -63
- package/src/videoConfiguration.js +113 -0
- package/src/authConfiguration.js +0 -138
- package/src/harvester.js +0 -171
package/src/harvester.js
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import Constants from "./constants";
|
|
2
|
-
import pkg from "../package.json";
|
|
3
|
-
import { callApi, getPayloadSize } from "./utils";
|
|
4
|
-
|
|
5
|
-
const { INTERVAL, MAX_EVENTS_PER_BATCH, MAX_PAYLOAD_SIZE, MAX_BEACON_SIZE } =
|
|
6
|
-
Constants;
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* A scheduler and dispatcher for sending raw event data to the New Relic 'ins' endpoint.
|
|
10
|
-
* It manages the harvest cycle, URL construction, and retries.
|
|
11
|
-
*/
|
|
12
|
-
export class NRVideoHarvester {
|
|
13
|
-
#started = false;
|
|
14
|
-
#aggregate; // EventAggregator instance
|
|
15
|
-
#timerId = null; // Timer ID for cleanup
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @param {object} agentController - The agent's configuration object.
|
|
19
|
-
* @param {object} aggregate - The aggregator instance (e.g., EventAggregator).
|
|
20
|
-
*/
|
|
21
|
-
constructor(aggregate) {
|
|
22
|
-
this.#aggregate = aggregate;
|
|
23
|
-
// Ensure any queued data is sent when the user navigates away.
|
|
24
|
-
window.addEventListener("pagehide", () =>
|
|
25
|
-
this.triggerHarvest({ isFinalHarvest: true })
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Starts the periodic harvest timer.
|
|
31
|
-
*/
|
|
32
|
-
startTimer() {
|
|
33
|
-
if (this.#started) return;
|
|
34
|
-
this.#started = true;
|
|
35
|
-
const onHarvestInterval = () => {
|
|
36
|
-
this.triggerHarvest({});
|
|
37
|
-
if (this.#started) {
|
|
38
|
-
this.#timerId = setTimeout(onHarvestInterval, INTERVAL);
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
this.#timerId = setTimeout(onHarvestInterval, INTERVAL);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Stops the harvest timer and cleans up resources.
|
|
46
|
-
*/
|
|
47
|
-
stopTimer() {
|
|
48
|
-
this.#started = false;
|
|
49
|
-
if (this.#timerId) {
|
|
50
|
-
clearTimeout(this.#timerId);
|
|
51
|
-
this.#timerId = null;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Executes a harvest cycle by draining the queue and sending it in chunks.
|
|
57
|
-
*/
|
|
58
|
-
|
|
59
|
-
triggerHarvest(options = {}) {
|
|
60
|
-
if (this.#aggregate.isEmpty()) return;
|
|
61
|
-
|
|
62
|
-
try {
|
|
63
|
-
// 1. Drain the entire queue to get all pending events.
|
|
64
|
-
const allEvents = this.#aggregate.drain();
|
|
65
|
-
|
|
66
|
-
// 2. Determine the correct size limit for this harvest.
|
|
67
|
-
const maxChunkSize = options.isFinalHarvest
|
|
68
|
-
? MAX_BEACON_SIZE
|
|
69
|
-
: MAX_PAYLOAD_SIZE;
|
|
70
|
-
|
|
71
|
-
// 3. Split the events into chunks that respect size and count limits.
|
|
72
|
-
const chunks = this.chunkEvents(allEvents, maxChunkSize);
|
|
73
|
-
|
|
74
|
-
// 4. Send each chunk sequentially.
|
|
75
|
-
chunks.forEach((chunk, index) => {
|
|
76
|
-
const isLastChunk = index === chunks.length - 1;
|
|
77
|
-
this.sendChunk(chunk, options, isLastChunk);
|
|
78
|
-
});
|
|
79
|
-
} catch (error) {
|
|
80
|
-
console.error("Error during harvest:", error);
|
|
81
|
-
// Re-add events to the queue if something went wrong
|
|
82
|
-
// This is a failsafe to prevent data loss
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Splits an array of events into multiple smaller arrays (chunks).
|
|
88
|
-
*/
|
|
89
|
-
chunkEvents(events, maxChunkSize) {
|
|
90
|
-
const chunks = [];
|
|
91
|
-
let currentChunk = [];
|
|
92
|
-
|
|
93
|
-
for (const event of events) {
|
|
94
|
-
if (currentChunk.length >= MAX_EVENTS_PER_BATCH) {
|
|
95
|
-
chunks.push(currentChunk);
|
|
96
|
-
currentChunk = [];
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
currentChunk.push(event);
|
|
100
|
-
const payloadSize = getPayloadSize({ ins: currentChunk });
|
|
101
|
-
// Use the maxChunkSize passed into the function
|
|
102
|
-
if (payloadSize > maxChunkSize) {
|
|
103
|
-
const lastEvent = currentChunk.pop();
|
|
104
|
-
if (currentChunk.length > 0) {
|
|
105
|
-
chunks.push(currentChunk);
|
|
106
|
-
}
|
|
107
|
-
currentChunk = [lastEvent];
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (currentChunk.length > 0) {
|
|
112
|
-
chunks.push(currentChunk);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return chunks;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Sends a single chunk of events.
|
|
120
|
-
*/
|
|
121
|
-
sendChunk(chunk, options, isLastChunk) {
|
|
122
|
-
const url = this.#buildUrl();
|
|
123
|
-
if (!url) {
|
|
124
|
-
// If URL construction failed, treat as a failed request that shouldn't be retried
|
|
125
|
-
this.#aggregate.postHarvestCleanup({ retry: false, status: 0 });
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const payload = { body: { ins: chunk } };
|
|
130
|
-
|
|
131
|
-
callApi(
|
|
132
|
-
{
|
|
133
|
-
url: url,
|
|
134
|
-
payload: payload,
|
|
135
|
-
options: options,
|
|
136
|
-
},
|
|
137
|
-
(result) => {
|
|
138
|
-
// Pass the failed chunk back to the aggregator for re-queuing.
|
|
139
|
-
if (result.retry) {
|
|
140
|
-
result.chunk = chunk;
|
|
141
|
-
}
|
|
142
|
-
this.#aggregate.postHarvestCleanup(result);
|
|
143
|
-
}
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Constructs the specific URL for the New Relic 'ins' endpoint with all required parameters.
|
|
149
|
-
* @private
|
|
150
|
-
*/
|
|
151
|
-
|
|
152
|
-
#buildUrl() {
|
|
153
|
-
try {
|
|
154
|
-
if (!window.NRVIDEO || !window.NRVIDEO.info) {
|
|
155
|
-
throw new Error("NRVIDEO info is not available.");
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const { beacon, licenseKey, applicationID, sa } = window.NRVIDEO.info;
|
|
159
|
-
|
|
160
|
-
if (!beacon || !licenseKey || !applicationID)
|
|
161
|
-
throw new Error(
|
|
162
|
-
"Options object provided by New Relic is not correctly initialized"
|
|
163
|
-
);
|
|
164
|
-
const url = `https://${beacon}/ins/1/${licenseKey}?a=${applicationID}&v=${pkg.version}&ref=${window.location.href}&ca=VA`;
|
|
165
|
-
return url;
|
|
166
|
-
} catch (error) {
|
|
167
|
-
console.error(error.message);
|
|
168
|
-
return null; // Return null instead of undefined
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|