@runtimescope/server-sdk 0.6.2 → 0.7.1
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 +134 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -1
- package/dist/index.d.ts +39 -1
- package/dist/index.js +133 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -91,6 +91,12 @@ interface ServerSdkConfig {
|
|
|
91
91
|
sampleRate?: number;
|
|
92
92
|
maxEventsPerSecond?: number;
|
|
93
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;
|
|
94
100
|
}
|
|
95
101
|
|
|
96
102
|
type EmitFn = (event: NetworkEvent) => void;
|
|
@@ -162,8 +168,40 @@ declare class Sampler {
|
|
|
162
168
|
reset(): void;
|
|
163
169
|
}
|
|
164
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
|
+
|
|
165
202
|
declare class RuntimeScopeServer {
|
|
166
203
|
private transport;
|
|
204
|
+
private httpTransport;
|
|
167
205
|
private sessionId;
|
|
168
206
|
private config;
|
|
169
207
|
private sampler;
|
|
@@ -187,4 +225,4 @@ declare class RuntimeScopeServer {
|
|
|
187
225
|
}
|
|
188
226
|
declare const RuntimeScope: RuntimeScopeServer;
|
|
189
227
|
|
|
190
|
-
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
|
@@ -91,6 +91,12 @@ interface ServerSdkConfig {
|
|
|
91
91
|
sampleRate?: number;
|
|
92
92
|
maxEventsPerSecond?: number;
|
|
93
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;
|
|
94
100
|
}
|
|
95
101
|
|
|
96
102
|
type EmitFn = (event: NetworkEvent) => void;
|
|
@@ -162,8 +168,40 @@ declare class Sampler {
|
|
|
162
168
|
reset(): void;
|
|
163
169
|
}
|
|
164
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
|
+
|
|
165
202
|
declare class RuntimeScopeServer {
|
|
166
203
|
private transport;
|
|
204
|
+
private httpTransport;
|
|
167
205
|
private sessionId;
|
|
168
206
|
private config;
|
|
169
207
|
private sampler;
|
|
@@ -187,4 +225,4 @@ declare class RuntimeScopeServer {
|
|
|
187
225
|
}
|
|
188
226
|
declare const RuntimeScope: RuntimeScopeServer;
|
|
189
227
|
|
|
190
|
-
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,9 +1439,10 @@ 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.1";
|
|
1355
1443
|
var RuntimeScopeServer = class {
|
|
1356
1444
|
transport = null;
|
|
1445
|
+
httpTransport = null;
|
|
1357
1446
|
sessionId = "";
|
|
1358
1447
|
config = {};
|
|
1359
1448
|
sampler = null;
|
|
@@ -1366,15 +1455,35 @@ var RuntimeScopeServer = class {
|
|
|
1366
1455
|
this.config = config;
|
|
1367
1456
|
this.sessionId = config.sessionId ?? generateSessionId();
|
|
1368
1457
|
const serverUrl = config.serverUrl ?? config.endpoint ?? "ws://127.0.0.1:9090";
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
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
|
+
}
|
|
1378
1487
|
if (config.sampleRate !== void 0 || config.maxEventsPerSecond !== void 0) {
|
|
1379
1488
|
this.sampler = new Sampler({
|
|
1380
1489
|
sampleRate: config.sampleRate,
|
|
@@ -1411,7 +1520,10 @@ var RuntimeScopeServer = class {
|
|
|
1411
1520
|
maxBodySize: config.maxBodySize,
|
|
1412
1521
|
redactHeaders: config.redactHeaders,
|
|
1413
1522
|
// Auto-ignore the collector URL to prevent recursion
|
|
1414
|
-
ignoreUrls: [
|
|
1523
|
+
ignoreUrls: [
|
|
1524
|
+
serverUrl.replace("ws://", "").replace("wss://", ""),
|
|
1525
|
+
...config.httpEndpoint ? [config.httpEndpoint.replace(/^https?:\/\//, "")] : []
|
|
1526
|
+
],
|
|
1415
1527
|
beforeSend: config.beforeSend
|
|
1416
1528
|
})
|
|
1417
1529
|
);
|
|
@@ -1439,6 +1551,10 @@ var RuntimeScopeServer = class {
|
|
|
1439
1551
|
}
|
|
1440
1552
|
this.restoreFunctions = [];
|
|
1441
1553
|
this.sampler = null;
|
|
1554
|
+
if (this.httpTransport) {
|
|
1555
|
+
this.httpTransport.disconnect();
|
|
1556
|
+
this.httpTransport = null;
|
|
1557
|
+
}
|
|
1442
1558
|
this.transport?.disconnect();
|
|
1443
1559
|
this.transport = null;
|
|
1444
1560
|
}
|
|
@@ -1447,12 +1563,12 @@ var RuntimeScopeServer = class {
|
|
|
1447
1563
|
}
|
|
1448
1564
|
emitEvent(event) {
|
|
1449
1565
|
if (this.sampler && !this.sampler.shouldSample(event)) return;
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
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);
|
|
1454
1570
|
} else {
|
|
1455
|
-
this.transport?.sendEvent(
|
|
1571
|
+
this.transport?.sendEvent(filtered);
|
|
1456
1572
|
}
|
|
1457
1573
|
}
|
|
1458
1574
|
// --- Express/Connect Middleware ---
|
|
@@ -1573,6 +1689,7 @@ var RuntimeScopeServer = class {
|
|
|
1573
1689
|
};
|
|
1574
1690
|
var RuntimeScope = new RuntimeScopeServer();
|
|
1575
1691
|
export {
|
|
1692
|
+
HttpTransport,
|
|
1576
1693
|
RuntimeScope,
|
|
1577
1694
|
Sampler,
|
|
1578
1695
|
_log,
|