ai-perf-sdk 1.0.4 → 1.0.6
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/package.json +1 -1
- package/src/batcher.js +12 -12
- package/src/client.js +22 -21
- package/src/index.js +12 -20
- package/src/instrument.js +41 -8
package/package.json
CHANGED
package/src/batcher.js
CHANGED
|
@@ -4,9 +4,6 @@ let queue = [];
|
|
|
4
4
|
let timer = null;
|
|
5
5
|
let config = {};
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* Initializes the batching system.
|
|
9
|
-
*/
|
|
10
7
|
function initBatcher(opts) {
|
|
11
8
|
config = {
|
|
12
9
|
endpoint: opts.endpoint,
|
|
@@ -15,34 +12,38 @@ function initBatcher(opts) {
|
|
|
15
12
|
headers: opts.headers || {}
|
|
16
13
|
};
|
|
17
14
|
|
|
15
|
+
console.log("[AI-PERF-SDK] Batcher initialized with:", JSON.stringify(config));
|
|
16
|
+
|
|
18
17
|
if (timer) clearInterval(timer);
|
|
19
18
|
timer = setInterval(flush, config.flushInterval);
|
|
20
19
|
|
|
21
20
|
return {
|
|
22
21
|
stop: () => {
|
|
22
|
+
console.log("[AI-PERF-SDK] Stopping batcher...");
|
|
23
23
|
if (timer) clearInterval(timer);
|
|
24
24
|
return flush();
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
/**
|
|
30
|
-
* Adds data to the queue and flushes if batch size reached.
|
|
31
|
-
*/
|
|
32
29
|
function enqueue(data) {
|
|
33
30
|
queue.push(data);
|
|
31
|
+
console.log(`[AI-PERF-SDK] Item enqueued. Current queue size: ${queue.length}`);
|
|
32
|
+
|
|
34
33
|
if (queue.length >= config.batchSize) {
|
|
34
|
+
console.log("[AI-PERF-SDK] Batch size reached. Triggering flush.");
|
|
35
35
|
flush();
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
/**
|
|
40
|
-
* Flushes the current queue using the client.
|
|
41
|
-
*/
|
|
42
39
|
async function flush() {
|
|
43
|
-
if (queue.length === 0)
|
|
40
|
+
if (queue.length === 0) {
|
|
41
|
+
// console.log("[AI-PERF-SDK] Flush called, but queue is empty.");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
44
|
|
|
45
45
|
const payload = queue.splice(0, queue.length);
|
|
46
|
+
console.log(`[AI-PERF-SDK] Flushing ${payload.length} items...`);
|
|
46
47
|
|
|
47
48
|
try {
|
|
48
49
|
await sendBatch({
|
|
@@ -51,8 +52,7 @@ async function flush() {
|
|
|
51
52
|
payload: payload
|
|
52
53
|
});
|
|
53
54
|
} catch (err) {
|
|
54
|
-
console.error("[AI-PERF-SDK]
|
|
55
|
-
// Put back in queue to retry
|
|
55
|
+
console.error("[AI-PERF-SDK] Flush failed. Returning items to queue.");
|
|
56
56
|
queue.unshift(...payload);
|
|
57
57
|
}
|
|
58
58
|
}
|
package/src/client.js
CHANGED
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
const fetch = global.fetch || (typeof require !== 'undefined' ? require("node-fetch") : null);
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Sends a batch of telemetry data to the endpoint.
|
|
5
|
-
* @param {Object} options
|
|
6
|
-
* @param {string} options.endpoint - Collector URL
|
|
7
|
-
* @param {Object} options.headers - Custom request headers
|
|
8
|
-
* @param {Array} options.payload - Array of telemetry items
|
|
9
|
-
*/
|
|
10
3
|
async function sendBatch({ endpoint, headers, payload }) {
|
|
4
|
+
console.log(`[AI-PERF-SDK] Sending batch to ${endpoint}... Payload size: ${payload.length}`);
|
|
5
|
+
|
|
11
6
|
if (!fetch) {
|
|
12
|
-
throw new Error("Fetch is not available.
|
|
7
|
+
throw new Error("Fetch is not available.");
|
|
13
8
|
}
|
|
14
9
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
try {
|
|
11
|
+
const response = await fetch(endpoint, {
|
|
12
|
+
method: "POST",
|
|
13
|
+
headers: {
|
|
14
|
+
"Content-Type": "application/json",
|
|
15
|
+
...headers,
|
|
16
|
+
},
|
|
17
|
+
body: JSON.stringify(payload),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
const text = await response.text();
|
|
22
|
+
console.error(`[AI-PERF-SDK] HTTP Error: ${response.status} - ${text}`);
|
|
23
|
+
throw new Error(`Telemetry send failed: ${response.status} ${text}`);
|
|
24
|
+
}
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
);
|
|
26
|
+
console.log(`[AI-PERF-SDK] Batch successfully sent to ${endpoint} (Status: ${response.status})`);
|
|
27
|
+
} catch (err) {
|
|
28
|
+
console.error(`[AI-PERF-SDK] Network Error sending batch:`, err.message);
|
|
29
|
+
throw err;
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
|
package/src/index.js
CHANGED
|
@@ -3,35 +3,28 @@ const { instrumentHttp } = require("./instrument");
|
|
|
3
3
|
|
|
4
4
|
let stopBatcher = null;
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
* Starts the custom Performance SDK.
|
|
8
|
-
* @param {Object} options
|
|
9
|
-
* @param {string} options.endpoint - Collector URL
|
|
10
|
-
* @param {number} [options.batchSize] - Items per batch (default 10)
|
|
11
|
-
* @param {number} [options.flushInterval] - MS between flushes (default 5000)
|
|
12
|
-
* @param {Object} [options.headers] - Custom headers (e.g., x-session-id)
|
|
13
|
-
*/
|
|
14
6
|
function startSdk(options = {}) {
|
|
7
|
+
console.log("[AI-PERF-SDK] startSDK called with configuration:", JSON.stringify(options));
|
|
8
|
+
|
|
15
9
|
if (!options.endpoint) {
|
|
16
|
-
console.error("[AI-PERF-SDK]
|
|
10
|
+
console.error("[AI-PERF-SDK] CRITICAL ERROR: No endpoint provided. Telemetry will not be sent.");
|
|
17
11
|
return;
|
|
18
12
|
}
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
try {
|
|
15
|
+
const batcher = initBatcher(options);
|
|
16
|
+
stopBatcher = batcher.stop;
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
instrumentHttp();
|
|
18
|
+
instrumentHttp();
|
|
26
19
|
|
|
27
|
-
|
|
20
|
+
console.log("[AI-PERF-SDK] SDK Start Sequence Complete.");
|
|
21
|
+
} catch (err) {
|
|
22
|
+
console.error("[AI-PERF-SDK] Initialization failed:", err);
|
|
23
|
+
}
|
|
28
24
|
}
|
|
29
25
|
|
|
30
|
-
/**
|
|
31
|
-
* Shuts down the SDK and flushing pending spans.
|
|
32
|
-
*/
|
|
33
26
|
async function shutdownSdk() {
|
|
34
|
-
console.log("[AI-PERF-SDK]
|
|
27
|
+
console.log("[AI-PERF-SDK] shutdownSDK initiated.");
|
|
35
28
|
if (stopBatcher) {
|
|
36
29
|
await stopBatcher();
|
|
37
30
|
}
|
|
@@ -40,7 +33,6 @@ async function shutdownSdk() {
|
|
|
40
33
|
module.exports = {
|
|
41
34
|
startSDK: startSdk,
|
|
42
35
|
shutdownSDK: shutdownSdk,
|
|
43
|
-
// Aliases for compatibility
|
|
44
36
|
initPerformanceSDK: startSdk,
|
|
45
37
|
shutdownPerformanceSDK: shutdownSdk
|
|
46
38
|
};
|
package/src/instrument.js
CHANGED
|
@@ -3,22 +3,22 @@ const { enqueue } = require("./batcher");
|
|
|
3
3
|
const http = require("http");
|
|
4
4
|
const https = require("https");
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
* Instruments global fetch and Node.js http/https modules.
|
|
8
|
-
*/
|
|
9
6
|
function instrumentHttp() {
|
|
7
|
+
console.log("[AI-PERF-SDK] Starting HTTP instrumentation...");
|
|
8
|
+
|
|
10
9
|
// 1. Instrument global fetch
|
|
11
10
|
if (global.fetch) {
|
|
11
|
+
console.log("[AI-PERF-SDK] Fetch detected. Patching global.fetch...");
|
|
12
12
|
const originalFetch = global.fetch;
|
|
13
13
|
global.fetch = async (...args) => {
|
|
14
14
|
const url = args[0];
|
|
15
15
|
const urlStr = typeof url === 'string' ? url : (url.url || url.toString());
|
|
16
16
|
|
|
17
|
-
// Avoid self-telemetry loops
|
|
18
17
|
if (urlStr && urlStr.includes('/api/telemetry')) {
|
|
19
18
|
return originalFetch(...args);
|
|
20
19
|
}
|
|
21
20
|
|
|
21
|
+
console.log(`[AI-PERF-SDK] Fetch intercepted: ${urlStr}`);
|
|
22
22
|
const start = performance.now();
|
|
23
23
|
let status = 0;
|
|
24
24
|
let error = null;
|
|
@@ -47,12 +47,13 @@ function instrumentHttp() {
|
|
|
47
47
|
|
|
48
48
|
// 2. Instrument Node.js http/https modules
|
|
49
49
|
[http, https].forEach((module) => {
|
|
50
|
+
const moduleName = module === https ? 'https' : 'http';
|
|
51
|
+
console.log(`[AI-PERF-SDK] Patching Node.js ${moduleName} module...`);
|
|
50
52
|
const originalRequest = module.request;
|
|
53
|
+
|
|
51
54
|
module.request = function (options, callback) {
|
|
52
55
|
const start = performance.now();
|
|
53
|
-
|
|
54
|
-
// Reconstruct URL
|
|
55
|
-
const protocol = module === https ? 'https:' : 'http:';
|
|
56
|
+
const protocol = moduleName === 'https' ? 'https:' : 'http:';
|
|
56
57
|
const host = options.host || options.hostname || 'localhost';
|
|
57
58
|
const path = options.path || '/';
|
|
58
59
|
const urlStr = `${protocol}//${host}${path}`;
|
|
@@ -61,6 +62,8 @@ function instrumentHttp() {
|
|
|
61
62
|
return originalRequest.apply(this, arguments);
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
// console.log(`[AI-PERF-SDK] HTTP Request intercepted: ${urlStr}`);
|
|
66
|
+
|
|
64
67
|
const req = originalRequest.call(this, options, (res) => {
|
|
65
68
|
res.on('end', () => {
|
|
66
69
|
enqueue({
|
|
@@ -90,13 +93,43 @@ function instrumentHttp() {
|
|
|
90
93
|
return req;
|
|
91
94
|
};
|
|
92
95
|
|
|
93
|
-
|
|
96
|
+
const originalGet = module.get;
|
|
94
97
|
module.get = function (options, callback) {
|
|
95
98
|
const req = module.request(options, callback);
|
|
96
99
|
req.end();
|
|
97
100
|
return req;
|
|
98
101
|
};
|
|
102
|
+
|
|
103
|
+
// --- Inbound Request (Server) Patching ---
|
|
104
|
+
const originalCreateServer = module.createServer;
|
|
105
|
+
module.createServer = function () {
|
|
106
|
+
const server = originalCreateServer.apply(this, arguments);
|
|
107
|
+
|
|
108
|
+
server.on('request', (req, res) => {
|
|
109
|
+
const start = performance.now();
|
|
110
|
+
const url = req.url;
|
|
111
|
+
const method = req.method;
|
|
112
|
+
|
|
113
|
+
// Ignore telemetry calls
|
|
114
|
+
if (url.includes('/api/telemetry')) return;
|
|
115
|
+
|
|
116
|
+
res.on('finish', () => {
|
|
117
|
+
const duration = performance.now() - start;
|
|
118
|
+
enqueue({
|
|
119
|
+
type: "http-inbound",
|
|
120
|
+
url: url,
|
|
121
|
+
method: method,
|
|
122
|
+
duration: Math.round(duration),
|
|
123
|
+
status: res.statusCode,
|
|
124
|
+
timestamp: new Date().toISOString()
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return server;
|
|
130
|
+
};
|
|
99
131
|
});
|
|
100
132
|
}
|
|
101
133
|
|
|
102
134
|
module.exports = { instrumentHttp };
|
|
135
|
+
|