@runtimescope/server-sdk 0.6.1 → 0.7.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/dist/index.cjs +141 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.js +140 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -69,6 +69,8 @@ interface PerformanceEvent {
|
|
|
69
69
|
type ServerRuntimeEvent = DatabaseEvent | ConsoleEvent | NetworkEvent | PerformanceEvent;
|
|
70
70
|
interface ServerSdkConfig {
|
|
71
71
|
serverUrl?: string;
|
|
72
|
+
/** Alias for serverUrl — matches the browser SDK's config */
|
|
73
|
+
endpoint?: string;
|
|
72
74
|
appName?: string;
|
|
73
75
|
sessionId?: string;
|
|
74
76
|
/** API key for authenticated connections to the collector */
|
|
@@ -89,6 +91,12 @@ interface ServerSdkConfig {
|
|
|
89
91
|
sampleRate?: number;
|
|
90
92
|
maxEventsPerSecond?: number;
|
|
91
93
|
maxQueueSize?: number;
|
|
94
|
+
/** Transport type: 'ws' (WebSocket, default) or 'http' (HTTP POST for serverless) */
|
|
95
|
+
transport?: 'ws' | 'http';
|
|
96
|
+
/** HTTP endpoint URL for HTTP transport (e.g., 'http://collector:9091/api/events') */
|
|
97
|
+
httpEndpoint?: string;
|
|
98
|
+
/** HTTP batch flush interval in ms (default: 1000) */
|
|
99
|
+
httpFlushIntervalMs?: number;
|
|
92
100
|
}
|
|
93
101
|
|
|
94
102
|
type EmitFn = (event: NetworkEvent) => void;
|
|
@@ -160,12 +168,46 @@ declare class Sampler {
|
|
|
160
168
|
reset(): void;
|
|
161
169
|
}
|
|
162
170
|
|
|
171
|
+
interface HttpTransportOptions {
|
|
172
|
+
url: string;
|
|
173
|
+
sessionId: string;
|
|
174
|
+
appName: string;
|
|
175
|
+
sdkVersion: string;
|
|
176
|
+
authToken?: string;
|
|
177
|
+
maxQueueSize?: number;
|
|
178
|
+
flushIntervalMs?: number;
|
|
179
|
+
maxRetries?: number;
|
|
180
|
+
retryDelayMs?: number;
|
|
181
|
+
}
|
|
182
|
+
declare class HttpTransport {
|
|
183
|
+
private queue;
|
|
184
|
+
private url;
|
|
185
|
+
private sessionId;
|
|
186
|
+
private appName;
|
|
187
|
+
private sdkVersion;
|
|
188
|
+
private authToken;
|
|
189
|
+
private maxQueueSize;
|
|
190
|
+
private maxRetries;
|
|
191
|
+
private retryDelayMs;
|
|
192
|
+
private flushTimer;
|
|
193
|
+
private _droppedCount;
|
|
194
|
+
private sessionRegistered;
|
|
195
|
+
constructor(options: HttpTransportOptions);
|
|
196
|
+
get droppedCount(): number;
|
|
197
|
+
sendEvent(event: ServerRuntimeEvent): void;
|
|
198
|
+
flush(): Promise<void>;
|
|
199
|
+
disconnect(): Promise<void>;
|
|
200
|
+
}
|
|
201
|
+
|
|
163
202
|
declare class RuntimeScopeServer {
|
|
164
203
|
private transport;
|
|
204
|
+
private httpTransport;
|
|
165
205
|
private sessionId;
|
|
166
206
|
private config;
|
|
167
207
|
private sampler;
|
|
168
208
|
private restoreFunctions;
|
|
209
|
+
/** Alias for `connect` — mirrors the browser SDK's init() API */
|
|
210
|
+
init(config?: ServerSdkConfig): void;
|
|
169
211
|
connect(config?: ServerSdkConfig): void;
|
|
170
212
|
disconnect(): void;
|
|
171
213
|
get currentSessionId(): string;
|
|
@@ -183,4 +225,4 @@ declare class RuntimeScopeServer {
|
|
|
183
225
|
}
|
|
184
226
|
declare const RuntimeScope: RuntimeScopeServer;
|
|
185
227
|
|
|
186
|
-
export { type ConsoleEvent, type DatabaseEvent, type MetricUnit, type NetworkEvent, type PerformanceEvent, RuntimeScope, Sampler, type ServerMetricName, type ServerRuntimeEvent, type ServerSdkConfig, _log, generateId, generateSessionId, getRequestContext, getSessionId, normalizeQuery, parseOperation, parseTablesAccessed, redactParams, runWithContext, runtimeScopeMiddleware };
|
|
228
|
+
export { type ConsoleEvent, type DatabaseEvent, HttpTransport, type HttpTransportOptions, type MetricUnit, type NetworkEvent, type PerformanceEvent, RuntimeScope, Sampler, type ServerMetricName, type ServerRuntimeEvent, type ServerSdkConfig, _log, generateId, generateSessionId, getRequestContext, getSessionId, normalizeQuery, parseOperation, parseTablesAccessed, redactParams, runWithContext, runtimeScopeMiddleware };
|
package/dist/index.d.ts
CHANGED
|
@@ -69,6 +69,8 @@ interface PerformanceEvent {
|
|
|
69
69
|
type ServerRuntimeEvent = DatabaseEvent | ConsoleEvent | NetworkEvent | PerformanceEvent;
|
|
70
70
|
interface ServerSdkConfig {
|
|
71
71
|
serverUrl?: string;
|
|
72
|
+
/** Alias for serverUrl — matches the browser SDK's config */
|
|
73
|
+
endpoint?: string;
|
|
72
74
|
appName?: string;
|
|
73
75
|
sessionId?: string;
|
|
74
76
|
/** API key for authenticated connections to the collector */
|
|
@@ -89,6 +91,12 @@ interface ServerSdkConfig {
|
|
|
89
91
|
sampleRate?: number;
|
|
90
92
|
maxEventsPerSecond?: number;
|
|
91
93
|
maxQueueSize?: number;
|
|
94
|
+
/** Transport type: 'ws' (WebSocket, default) or 'http' (HTTP POST for serverless) */
|
|
95
|
+
transport?: 'ws' | 'http';
|
|
96
|
+
/** HTTP endpoint URL for HTTP transport (e.g., 'http://collector:9091/api/events') */
|
|
97
|
+
httpEndpoint?: string;
|
|
98
|
+
/** HTTP batch flush interval in ms (default: 1000) */
|
|
99
|
+
httpFlushIntervalMs?: number;
|
|
92
100
|
}
|
|
93
101
|
|
|
94
102
|
type EmitFn = (event: NetworkEvent) => void;
|
|
@@ -160,12 +168,46 @@ declare class Sampler {
|
|
|
160
168
|
reset(): void;
|
|
161
169
|
}
|
|
162
170
|
|
|
171
|
+
interface HttpTransportOptions {
|
|
172
|
+
url: string;
|
|
173
|
+
sessionId: string;
|
|
174
|
+
appName: string;
|
|
175
|
+
sdkVersion: string;
|
|
176
|
+
authToken?: string;
|
|
177
|
+
maxQueueSize?: number;
|
|
178
|
+
flushIntervalMs?: number;
|
|
179
|
+
maxRetries?: number;
|
|
180
|
+
retryDelayMs?: number;
|
|
181
|
+
}
|
|
182
|
+
declare class HttpTransport {
|
|
183
|
+
private queue;
|
|
184
|
+
private url;
|
|
185
|
+
private sessionId;
|
|
186
|
+
private appName;
|
|
187
|
+
private sdkVersion;
|
|
188
|
+
private authToken;
|
|
189
|
+
private maxQueueSize;
|
|
190
|
+
private maxRetries;
|
|
191
|
+
private retryDelayMs;
|
|
192
|
+
private flushTimer;
|
|
193
|
+
private _droppedCount;
|
|
194
|
+
private sessionRegistered;
|
|
195
|
+
constructor(options: HttpTransportOptions);
|
|
196
|
+
get droppedCount(): number;
|
|
197
|
+
sendEvent(event: ServerRuntimeEvent): void;
|
|
198
|
+
flush(): Promise<void>;
|
|
199
|
+
disconnect(): Promise<void>;
|
|
200
|
+
}
|
|
201
|
+
|
|
163
202
|
declare class RuntimeScopeServer {
|
|
164
203
|
private transport;
|
|
204
|
+
private httpTransport;
|
|
165
205
|
private sessionId;
|
|
166
206
|
private config;
|
|
167
207
|
private sampler;
|
|
168
208
|
private restoreFunctions;
|
|
209
|
+
/** Alias for `connect` — mirrors the browser SDK's init() API */
|
|
210
|
+
init(config?: ServerSdkConfig): void;
|
|
169
211
|
connect(config?: ServerSdkConfig): void;
|
|
170
212
|
disconnect(): void;
|
|
171
213
|
get currentSessionId(): string;
|
|
@@ -183,4 +225,4 @@ declare class RuntimeScopeServer {
|
|
|
183
225
|
}
|
|
184
226
|
declare const RuntimeScope: RuntimeScopeServer;
|
|
185
227
|
|
|
186
|
-
export { type ConsoleEvent, type DatabaseEvent, type MetricUnit, type NetworkEvent, type PerformanceEvent, RuntimeScope, Sampler, type ServerMetricName, type ServerRuntimeEvent, type ServerSdkConfig, _log, generateId, generateSessionId, getRequestContext, getSessionId, normalizeQuery, parseOperation, parseTablesAccessed, redactParams, runWithContext, runtimeScopeMiddleware };
|
|
228
|
+
export { type ConsoleEvent, type DatabaseEvent, HttpTransport, type HttpTransportOptions, type MetricUnit, type NetworkEvent, type PerformanceEvent, RuntimeScope, Sampler, type ServerMetricName, type ServerRuntimeEvent, type ServerSdkConfig, _log, generateId, generateSessionId, getRequestContext, getSessionId, normalizeQuery, parseOperation, parseTablesAccessed, redactParams, runWithContext, runtimeScopeMiddleware };
|
package/dist/index.js
CHANGED
|
@@ -128,6 +128,94 @@ var ServerTransport = class {
|
|
|
128
128
|
}
|
|
129
129
|
};
|
|
130
130
|
|
|
131
|
+
// src/http-transport.ts
|
|
132
|
+
var HttpTransport = class {
|
|
133
|
+
queue = [];
|
|
134
|
+
url;
|
|
135
|
+
sessionId;
|
|
136
|
+
appName;
|
|
137
|
+
sdkVersion;
|
|
138
|
+
authToken;
|
|
139
|
+
maxQueueSize;
|
|
140
|
+
maxRetries;
|
|
141
|
+
retryDelayMs;
|
|
142
|
+
flushTimer = null;
|
|
143
|
+
_droppedCount = 0;
|
|
144
|
+
sessionRegistered = false;
|
|
145
|
+
constructor(options) {
|
|
146
|
+
this.url = options.url;
|
|
147
|
+
this.sessionId = options.sessionId;
|
|
148
|
+
this.appName = options.appName;
|
|
149
|
+
this.sdkVersion = options.sdkVersion;
|
|
150
|
+
this.authToken = options.authToken;
|
|
151
|
+
this.maxQueueSize = options.maxQueueSize ?? 1e4;
|
|
152
|
+
this.maxRetries = options.maxRetries ?? 2;
|
|
153
|
+
this.retryDelayMs = options.retryDelayMs ?? 500;
|
|
154
|
+
const intervalMs = options.flushIntervalMs ?? 1e3;
|
|
155
|
+
this.flushTimer = setInterval(() => this.flush(), intervalMs);
|
|
156
|
+
if (this.flushTimer && typeof this.flushTimer === "object" && "unref" in this.flushTimer) {
|
|
157
|
+
this.flushTimer.unref();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
get droppedCount() {
|
|
161
|
+
return this._droppedCount;
|
|
162
|
+
}
|
|
163
|
+
sendEvent(event) {
|
|
164
|
+
if (this.queue.length >= this.maxQueueSize) {
|
|
165
|
+
this.queue.shift();
|
|
166
|
+
this._droppedCount++;
|
|
167
|
+
}
|
|
168
|
+
this.queue.push(event);
|
|
169
|
+
}
|
|
170
|
+
async flush() {
|
|
171
|
+
if (this.queue.length === 0) return;
|
|
172
|
+
const batch = this.queue.splice(0);
|
|
173
|
+
const payload = {
|
|
174
|
+
sessionId: this.sessionId,
|
|
175
|
+
events: batch
|
|
176
|
+
};
|
|
177
|
+
if (!this.sessionRegistered) {
|
|
178
|
+
payload.appName = this.appName;
|
|
179
|
+
payload.sdkVersion = this.sdkVersion;
|
|
180
|
+
}
|
|
181
|
+
const body = JSON.stringify(payload);
|
|
182
|
+
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
183
|
+
try {
|
|
184
|
+
const headers = {
|
|
185
|
+
"Content-Type": "application/json"
|
|
186
|
+
};
|
|
187
|
+
if (this.authToken) {
|
|
188
|
+
headers["Authorization"] = `Bearer ${this.authToken}`;
|
|
189
|
+
}
|
|
190
|
+
const response = await fetch(this.url, {
|
|
191
|
+
method: "POST",
|
|
192
|
+
headers,
|
|
193
|
+
body,
|
|
194
|
+
signal: AbortSignal.timeout(5e3)
|
|
195
|
+
});
|
|
196
|
+
if (response.ok) {
|
|
197
|
+
this.sessionRegistered = true;
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (response.status === 401 || response.status === 400) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
} catch {
|
|
204
|
+
}
|
|
205
|
+
if (attempt < this.maxRetries) {
|
|
206
|
+
await new Promise((r) => setTimeout(r, this.retryDelayMs));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async disconnect() {
|
|
211
|
+
if (this.flushTimer) {
|
|
212
|
+
clearInterval(this.flushTimer);
|
|
213
|
+
this.flushTimer = null;
|
|
214
|
+
}
|
|
215
|
+
await this.flush();
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
|
|
131
219
|
// src/utils/id.ts
|
|
132
220
|
import { randomBytes } from "crypto";
|
|
133
221
|
function generateId() {
|
|
@@ -1351,26 +1439,51 @@ function runtimeScopeMiddleware(emit, sessionId, options) {
|
|
|
1351
1439
|
}
|
|
1352
1440
|
|
|
1353
1441
|
// src/index.ts
|
|
1354
|
-
var SDK_VERSION = "0.
|
|
1442
|
+
var SDK_VERSION = "0.7.0";
|
|
1355
1443
|
var RuntimeScopeServer = class {
|
|
1356
1444
|
transport = null;
|
|
1445
|
+
httpTransport = null;
|
|
1357
1446
|
sessionId = "";
|
|
1358
1447
|
config = {};
|
|
1359
1448
|
sampler = null;
|
|
1360
1449
|
restoreFunctions = [];
|
|
1450
|
+
/** Alias for `connect` — mirrors the browser SDK's init() API */
|
|
1451
|
+
init(config = {}) {
|
|
1452
|
+
return this.connect(config);
|
|
1453
|
+
}
|
|
1361
1454
|
connect(config = {}) {
|
|
1362
1455
|
this.config = config;
|
|
1363
1456
|
this.sessionId = config.sessionId ?? generateSessionId();
|
|
1364
|
-
const serverUrl = config.serverUrl ?? "ws://127.0.0.1:9090";
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1457
|
+
const serverUrl = config.serverUrl ?? config.endpoint ?? "ws://127.0.0.1:9090";
|
|
1458
|
+
if (config.transport === "http") {
|
|
1459
|
+
let httpUrl = config.httpEndpoint;
|
|
1460
|
+
if (!httpUrl) {
|
|
1461
|
+
const wsUrl = new URL(serverUrl);
|
|
1462
|
+
wsUrl.protocol = wsUrl.protocol === "wss:" ? "https:" : "http:";
|
|
1463
|
+
wsUrl.port = "9091";
|
|
1464
|
+
wsUrl.pathname = "/api/events";
|
|
1465
|
+
httpUrl = wsUrl.toString();
|
|
1466
|
+
}
|
|
1467
|
+
this.httpTransport = new HttpTransport({
|
|
1468
|
+
url: httpUrl,
|
|
1469
|
+
sessionId: this.sessionId,
|
|
1470
|
+
appName: config.appName ?? "server-app",
|
|
1471
|
+
sdkVersion: SDK_VERSION,
|
|
1472
|
+
authToken: config.authToken,
|
|
1473
|
+
maxQueueSize: config.maxQueueSize,
|
|
1474
|
+
flushIntervalMs: config.httpFlushIntervalMs
|
|
1475
|
+
});
|
|
1476
|
+
} else {
|
|
1477
|
+
this.transport = new ServerTransport({
|
|
1478
|
+
url: serverUrl,
|
|
1479
|
+
sessionId: this.sessionId,
|
|
1480
|
+
appName: config.appName ?? "server-app",
|
|
1481
|
+
sdkVersion: SDK_VERSION,
|
|
1482
|
+
authToken: config.authToken,
|
|
1483
|
+
maxQueueSize: config.maxQueueSize
|
|
1484
|
+
});
|
|
1485
|
+
this.transport.connect();
|
|
1486
|
+
}
|
|
1374
1487
|
if (config.sampleRate !== void 0 || config.maxEventsPerSecond !== void 0) {
|
|
1375
1488
|
this.sampler = new Sampler({
|
|
1376
1489
|
sampleRate: config.sampleRate,
|
|
@@ -1399,7 +1512,7 @@ var RuntimeScopeServer = class {
|
|
|
1399
1512
|
} catch {
|
|
1400
1513
|
}
|
|
1401
1514
|
}
|
|
1402
|
-
if (config.captureHttp) {
|
|
1515
|
+
if (config.captureHttp !== false) {
|
|
1403
1516
|
try {
|
|
1404
1517
|
this.restoreFunctions.push(
|
|
1405
1518
|
interceptHttp(emit, this.sessionId, {
|
|
@@ -1407,14 +1520,17 @@ var RuntimeScopeServer = class {
|
|
|
1407
1520
|
maxBodySize: config.maxBodySize,
|
|
1408
1521
|
redactHeaders: config.redactHeaders,
|
|
1409
1522
|
// Auto-ignore the collector URL to prevent recursion
|
|
1410
|
-
ignoreUrls: [
|
|
1523
|
+
ignoreUrls: [
|
|
1524
|
+
serverUrl.replace("ws://", "").replace("wss://", ""),
|
|
1525
|
+
...config.httpEndpoint ? [config.httpEndpoint.replace(/^https?:\/\//, "")] : []
|
|
1526
|
+
],
|
|
1411
1527
|
beforeSend: config.beforeSend
|
|
1412
1528
|
})
|
|
1413
1529
|
);
|
|
1414
1530
|
} catch {
|
|
1415
1531
|
}
|
|
1416
1532
|
}
|
|
1417
|
-
if (config.capturePerformance) {
|
|
1533
|
+
if (config.capturePerformance !== false) {
|
|
1418
1534
|
try {
|
|
1419
1535
|
this.restoreFunctions.push(
|
|
1420
1536
|
startPerfMetrics(emit, this.sessionId, {
|
|
@@ -1435,6 +1551,10 @@ var RuntimeScopeServer = class {
|
|
|
1435
1551
|
}
|
|
1436
1552
|
this.restoreFunctions = [];
|
|
1437
1553
|
this.sampler = null;
|
|
1554
|
+
if (this.httpTransport) {
|
|
1555
|
+
this.httpTransport.disconnect();
|
|
1556
|
+
this.httpTransport = null;
|
|
1557
|
+
}
|
|
1438
1558
|
this.transport?.disconnect();
|
|
1439
1559
|
this.transport = null;
|
|
1440
1560
|
}
|
|
@@ -1443,12 +1563,12 @@ var RuntimeScopeServer = class {
|
|
|
1443
1563
|
}
|
|
1444
1564
|
emitEvent(event) {
|
|
1445
1565
|
if (this.sampler && !this.sampler.shouldSample(event)) return;
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
this.
|
|
1566
|
+
const filtered = this.config.beforeSend ? this.config.beforeSend(event) : event;
|
|
1567
|
+
if (!filtered) return;
|
|
1568
|
+
if (this.httpTransport) {
|
|
1569
|
+
this.httpTransport.sendEvent(filtered);
|
|
1450
1570
|
} else {
|
|
1451
|
-
this.transport?.sendEvent(
|
|
1571
|
+
this.transport?.sendEvent(filtered);
|
|
1452
1572
|
}
|
|
1453
1573
|
}
|
|
1454
1574
|
// --- Express/Connect Middleware ---
|
|
@@ -1569,6 +1689,7 @@ var RuntimeScopeServer = class {
|
|
|
1569
1689
|
};
|
|
1570
1690
|
var RuntimeScope = new RuntimeScopeServer();
|
|
1571
1691
|
export {
|
|
1692
|
+
HttpTransport,
|
|
1572
1693
|
RuntimeScope,
|
|
1573
1694
|
Sampler,
|
|
1574
1695
|
_log,
|