apitally 0.9.5 → 0.11.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 +1 -2
- package/dist/common/client.cjs +398 -12
- package/dist/common/client.cjs.map +1 -1
- package/dist/common/client.d.cts +8 -1
- package/dist/common/client.d.ts +8 -1
- package/dist/common/client.js +394 -8
- package/dist/common/client.js.map +1 -1
- package/dist/common/consumerRegistry.d.cts +4 -0
- package/dist/common/consumerRegistry.d.ts +4 -0
- package/dist/common/requestCounter.d.cts +4 -0
- package/dist/common/requestCounter.d.ts +4 -0
- package/dist/common/requestLogger.cjs +419 -0
- package/dist/common/requestLogger.cjs.map +1 -0
- package/dist/common/requestLogger.d.cts +63 -0
- package/dist/common/requestLogger.d.ts +63 -0
- package/dist/common/requestLogger.js +395 -0
- package/dist/common/requestLogger.js.map +1 -0
- package/dist/common/serverErrorCounter.d.cts +4 -0
- package/dist/common/serverErrorCounter.d.ts +4 -0
- package/dist/common/tempGzipFile.cjs +93 -0
- package/dist/common/tempGzipFile.cjs.map +1 -0
- package/dist/common/tempGzipFile.d.cts +17 -0
- package/dist/common/tempGzipFile.d.ts +17 -0
- package/dist/common/tempGzipFile.js +74 -0
- package/dist/common/tempGzipFile.js.map +1 -0
- package/dist/common/types.cjs.map +1 -1
- package/dist/common/types.d.cts +5 -0
- package/dist/common/types.d.ts +5 -0
- package/dist/common/validationErrorCounter.d.cts +4 -0
- package/dist/common/validationErrorCounter.d.ts +4 -0
- package/dist/express/index.cjs +500 -34
- package/dist/express/index.cjs.map +1 -1
- package/dist/express/index.d.cts +4 -0
- package/dist/express/index.d.ts +4 -0
- package/dist/express/index.js +496 -30
- package/dist/express/index.js.map +1 -1
- package/dist/express/middleware.cjs +500 -34
- package/dist/express/middleware.cjs.map +1 -1
- package/dist/express/middleware.d.cts +4 -0
- package/dist/express/middleware.d.ts +4 -0
- package/dist/express/middleware.js +496 -30
- package/dist/express/middleware.js.map +1 -1
- package/dist/fastify/index.cjs +491 -27
- package/dist/fastify/index.cjs.map +1 -1
- package/dist/fastify/index.d.cts +4 -0
- package/dist/fastify/index.d.ts +4 -0
- package/dist/fastify/index.js +487 -23
- package/dist/fastify/index.js.map +1 -1
- package/dist/fastify/plugin.cjs +491 -27
- package/dist/fastify/plugin.cjs.map +1 -1
- package/dist/fastify/plugin.d.cts +4 -0
- package/dist/fastify/plugin.d.ts +4 -0
- package/dist/fastify/plugin.js +487 -23
- package/dist/fastify/plugin.js.map +1 -1
- package/dist/hono/index.cjs +460 -15
- package/dist/hono/index.cjs.map +1 -1
- package/dist/hono/index.d.cts +4 -0
- package/dist/hono/index.d.ts +4 -0
- package/dist/hono/index.js +456 -11
- package/dist/hono/index.js.map +1 -1
- package/dist/hono/middleware.cjs +460 -15
- package/dist/hono/middleware.cjs.map +1 -1
- package/dist/hono/middleware.d.cts +4 -0
- package/dist/hono/middleware.d.ts +4 -0
- package/dist/hono/middleware.js +456 -11
- package/dist/hono/middleware.js.map +1 -1
- package/dist/koa/index.cjs +475 -15
- package/dist/koa/index.cjs.map +1 -1
- package/dist/koa/index.d.cts +4 -0
- package/dist/koa/index.d.ts +4 -0
- package/dist/koa/index.js +471 -11
- package/dist/koa/index.js.map +1 -1
- package/dist/koa/middleware.cjs +475 -15
- package/dist/koa/middleware.cjs.map +1 -1
- package/dist/koa/middleware.d.cts +4 -0
- package/dist/koa/middleware.d.ts +4 -0
- package/dist/koa/middleware.js +471 -11
- package/dist/koa/middleware.js.map +1 -1
- package/dist/nestjs/index.cjs +536 -41
- package/dist/nestjs/index.cjs.map +1 -1
- package/dist/nestjs/index.d.cts +10 -2
- package/dist/nestjs/index.d.ts +10 -2
- package/dist/nestjs/index.js +534 -37
- package/dist/nestjs/index.js.map +1 -1
- package/package.json +8 -2
package/dist/common/client.js
CHANGED
|
@@ -4,7 +4,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
|
|
6
6
|
// src/common/client.ts
|
|
7
|
-
import { randomUUID } from "crypto";
|
|
7
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
8
8
|
import fetchRetry from "fetch-retry";
|
|
9
9
|
|
|
10
10
|
// src/common/consumerRegistry.ts
|
|
@@ -159,6 +159,338 @@ var _RequestCounter = class _RequestCounter {
|
|
|
159
159
|
__name(_RequestCounter, "RequestCounter");
|
|
160
160
|
var RequestCounter = _RequestCounter;
|
|
161
161
|
|
|
162
|
+
// src/common/requestLogger.ts
|
|
163
|
+
import { Buffer as Buffer3 } from "buffer";
|
|
164
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
165
|
+
import { unlinkSync as unlinkSync2, writeFileSync } from "fs";
|
|
166
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
167
|
+
import { join as join2 } from "path";
|
|
168
|
+
|
|
169
|
+
// src/common/tempGzipFile.ts
|
|
170
|
+
import { Buffer as Buffer2 } from "buffer";
|
|
171
|
+
import { randomUUID } from "crypto";
|
|
172
|
+
import { createWriteStream, readFile, unlinkSync } from "fs";
|
|
173
|
+
import { tmpdir } from "os";
|
|
174
|
+
import { join } from "path";
|
|
175
|
+
import { createGzip } from "zlib";
|
|
176
|
+
var _TempGzipFile = class _TempGzipFile {
|
|
177
|
+
uuid;
|
|
178
|
+
filePath;
|
|
179
|
+
gzip;
|
|
180
|
+
writeStream;
|
|
181
|
+
readyPromise;
|
|
182
|
+
constructor() {
|
|
183
|
+
this.uuid = randomUUID();
|
|
184
|
+
this.filePath = join(tmpdir(), `apitally-${this.uuid}.gz`);
|
|
185
|
+
this.writeStream = createWriteStream(this.filePath);
|
|
186
|
+
this.readyPromise = new Promise((resolve, reject) => {
|
|
187
|
+
this.writeStream.once("ready", resolve);
|
|
188
|
+
this.writeStream.once("error", reject);
|
|
189
|
+
});
|
|
190
|
+
this.gzip = createGzip();
|
|
191
|
+
this.gzip.pipe(this.writeStream);
|
|
192
|
+
}
|
|
193
|
+
get size() {
|
|
194
|
+
return this.writeStream.bytesWritten;
|
|
195
|
+
}
|
|
196
|
+
async writeLine(data) {
|
|
197
|
+
await this.readyPromise;
|
|
198
|
+
return new Promise((resolve, reject) => {
|
|
199
|
+
this.gzip.write(Buffer2.concat([
|
|
200
|
+
data,
|
|
201
|
+
Buffer2.from("\n")
|
|
202
|
+
]), (error) => {
|
|
203
|
+
if (error) {
|
|
204
|
+
reject(error);
|
|
205
|
+
} else {
|
|
206
|
+
resolve();
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
async getContent() {
|
|
212
|
+
return new Promise((resolve, reject) => {
|
|
213
|
+
readFile(this.filePath, (error, data) => {
|
|
214
|
+
if (error) {
|
|
215
|
+
reject(error);
|
|
216
|
+
} else {
|
|
217
|
+
resolve(data);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
async close() {
|
|
223
|
+
return new Promise((resolve) => {
|
|
224
|
+
this.gzip.end(() => {
|
|
225
|
+
resolve();
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
async delete() {
|
|
230
|
+
await this.close();
|
|
231
|
+
unlinkSync(this.filePath);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
__name(_TempGzipFile, "TempGzipFile");
|
|
235
|
+
var TempGzipFile = _TempGzipFile;
|
|
236
|
+
|
|
237
|
+
// src/common/requestLogger.ts
|
|
238
|
+
var MAX_BODY_SIZE = 5e4;
|
|
239
|
+
var MAX_FILE_SIZE = 1e6;
|
|
240
|
+
var MAX_FILES = 50;
|
|
241
|
+
var MAX_PENDING_WRITES = 100;
|
|
242
|
+
var BODY_TOO_LARGE = Buffer3.from("<body too large>");
|
|
243
|
+
var BODY_MASKED = Buffer3.from("<masked>");
|
|
244
|
+
var MASKED = "******";
|
|
245
|
+
var ALLOWED_CONTENT_TYPES = [
|
|
246
|
+
"application/json",
|
|
247
|
+
"text/plain"
|
|
248
|
+
];
|
|
249
|
+
var EXCLUDE_PATH_PATTERNS = [
|
|
250
|
+
/\/_?healthz?$/,
|
|
251
|
+
/\/_?health[_-]?checks?$/,
|
|
252
|
+
/\/_?heart[_-]?beats?$/,
|
|
253
|
+
/\/ping$/,
|
|
254
|
+
/\/ready$/,
|
|
255
|
+
/\/live$/
|
|
256
|
+
];
|
|
257
|
+
var MASK_QUERY_PARAM_PATTERNS = [
|
|
258
|
+
/auth/i,
|
|
259
|
+
/api-?key/i,
|
|
260
|
+
/secret/i,
|
|
261
|
+
/token/i,
|
|
262
|
+
/password/i,
|
|
263
|
+
/pwd/i
|
|
264
|
+
];
|
|
265
|
+
var MASK_HEADER_PATTERNS = [
|
|
266
|
+
/auth/i,
|
|
267
|
+
/api-?key/i,
|
|
268
|
+
/secret/i,
|
|
269
|
+
/token/i,
|
|
270
|
+
/cookie/i
|
|
271
|
+
];
|
|
272
|
+
var DEFAULT_CONFIG = {
|
|
273
|
+
enabled: false,
|
|
274
|
+
logQueryParams: true,
|
|
275
|
+
logRequestHeaders: false,
|
|
276
|
+
logRequestBody: false,
|
|
277
|
+
logResponseHeaders: true,
|
|
278
|
+
logResponseBody: false,
|
|
279
|
+
maskQueryParams: [],
|
|
280
|
+
maskHeaders: [],
|
|
281
|
+
excludePaths: []
|
|
282
|
+
};
|
|
283
|
+
var _RequestLogger = class _RequestLogger {
|
|
284
|
+
config;
|
|
285
|
+
enabled;
|
|
286
|
+
suspendUntil = null;
|
|
287
|
+
pendingWrites = [];
|
|
288
|
+
currentFile = null;
|
|
289
|
+
files = [];
|
|
290
|
+
maintainIntervalId;
|
|
291
|
+
constructor(config) {
|
|
292
|
+
this.config = {
|
|
293
|
+
...DEFAULT_CONFIG,
|
|
294
|
+
...config
|
|
295
|
+
};
|
|
296
|
+
this.enabled = this.config.enabled && checkWritableFs();
|
|
297
|
+
if (this.enabled) {
|
|
298
|
+
this.maintainIntervalId = setInterval(() => {
|
|
299
|
+
this.maintain();
|
|
300
|
+
}, 1e3);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
shouldExcludePath(urlPath) {
|
|
304
|
+
const patterns = [
|
|
305
|
+
...this.config.excludePaths,
|
|
306
|
+
...EXCLUDE_PATH_PATTERNS
|
|
307
|
+
];
|
|
308
|
+
return matchPatterns(urlPath, patterns);
|
|
309
|
+
}
|
|
310
|
+
shouldMaskQueryParam(name) {
|
|
311
|
+
const patterns = [
|
|
312
|
+
...this.config.maskQueryParams,
|
|
313
|
+
...MASK_QUERY_PARAM_PATTERNS
|
|
314
|
+
];
|
|
315
|
+
return matchPatterns(name, patterns);
|
|
316
|
+
}
|
|
317
|
+
shouldMaskHeader(name) {
|
|
318
|
+
const patterns = [
|
|
319
|
+
...this.config.maskHeaders,
|
|
320
|
+
...MASK_HEADER_PATTERNS
|
|
321
|
+
];
|
|
322
|
+
return matchPatterns(name, patterns);
|
|
323
|
+
}
|
|
324
|
+
hasSupportedContentType(headers) {
|
|
325
|
+
var _a2;
|
|
326
|
+
const contentType = (_a2 = headers.find(([k]) => k.toLowerCase() === "content-type")) == null ? void 0 : _a2[1];
|
|
327
|
+
return contentType !== void 0 && ALLOWED_CONTENT_TYPES.some((t) => contentType.startsWith(t));
|
|
328
|
+
}
|
|
329
|
+
maskQueryParams(search) {
|
|
330
|
+
const params = new URLSearchParams(search);
|
|
331
|
+
for (const [key] of params) {
|
|
332
|
+
if (this.shouldMaskQueryParam(key)) {
|
|
333
|
+
params.set(key, MASKED);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return params.toString();
|
|
337
|
+
}
|
|
338
|
+
maskHeaders(headers) {
|
|
339
|
+
return headers.map(([k, v]) => [
|
|
340
|
+
k,
|
|
341
|
+
this.shouldMaskHeader(k) ? MASKED : v
|
|
342
|
+
]);
|
|
343
|
+
}
|
|
344
|
+
logRequest(request, response) {
|
|
345
|
+
var _a2, _b;
|
|
346
|
+
if (!this.enabled || this.suspendUntil !== null) return;
|
|
347
|
+
const url = new URL(request.url);
|
|
348
|
+
const path = request.path ?? url.pathname;
|
|
349
|
+
if (this.shouldExcludePath(path) || (((_b = (_a2 = this.config).excludeCallback) == null ? void 0 : _b.call(_a2, request, response)) ?? false)) {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
url.search = this.config.logQueryParams ? this.maskQueryParams(url.search) : "";
|
|
353
|
+
request.url = url.toString();
|
|
354
|
+
request.headers = this.config.logRequestHeaders ? this.maskHeaders(request.headers) : [];
|
|
355
|
+
response.headers = this.config.logResponseHeaders ? this.maskHeaders(response.headers) : [];
|
|
356
|
+
if (!this.config.logRequestBody || !this.hasSupportedContentType(request.headers)) {
|
|
357
|
+
request.body = void 0;
|
|
358
|
+
} else if (request.body) {
|
|
359
|
+
if (request.body.length > MAX_BODY_SIZE) {
|
|
360
|
+
request.body = BODY_TOO_LARGE;
|
|
361
|
+
} else if (this.config.maskRequestBodyCallback) {
|
|
362
|
+
try {
|
|
363
|
+
request.body = this.config.maskRequestBodyCallback(request) ?? BODY_MASKED;
|
|
364
|
+
if (request.body.length > MAX_BODY_SIZE) {
|
|
365
|
+
request.body = BODY_TOO_LARGE;
|
|
366
|
+
}
|
|
367
|
+
} catch {
|
|
368
|
+
request.body = void 0;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
if (!this.config.logResponseBody || !this.hasSupportedContentType(response.headers)) {
|
|
373
|
+
response.body = void 0;
|
|
374
|
+
} else if (response.body) {
|
|
375
|
+
if (response.body.length > MAX_BODY_SIZE) {
|
|
376
|
+
response.body = BODY_TOO_LARGE;
|
|
377
|
+
} else if (this.config.maskResponseBodyCallback) {
|
|
378
|
+
try {
|
|
379
|
+
response.body = this.config.maskResponseBodyCallback(request, response) ?? BODY_MASKED;
|
|
380
|
+
if (response.body.length > MAX_BODY_SIZE) {
|
|
381
|
+
response.body = BODY_TOO_LARGE;
|
|
382
|
+
}
|
|
383
|
+
} catch {
|
|
384
|
+
response.body = void 0;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
const item = {
|
|
389
|
+
uuid: randomUUID2(),
|
|
390
|
+
request: skipEmptyValues(request),
|
|
391
|
+
response: skipEmptyValues(response)
|
|
392
|
+
};
|
|
393
|
+
[
|
|
394
|
+
item.request.body,
|
|
395
|
+
item.response.body
|
|
396
|
+
].forEach((body) => {
|
|
397
|
+
if (body) {
|
|
398
|
+
body.toJSON = function() {
|
|
399
|
+
return this.toString("base64");
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
this.pendingWrites.push(JSON.stringify(item));
|
|
404
|
+
if (this.pendingWrites.length > MAX_PENDING_WRITES) {
|
|
405
|
+
this.pendingWrites.shift();
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
async writeToFile() {
|
|
409
|
+
if (!this.enabled || this.pendingWrites.length === 0) {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (!this.currentFile) {
|
|
413
|
+
this.currentFile = new TempGzipFile();
|
|
414
|
+
}
|
|
415
|
+
while (this.pendingWrites.length > 0) {
|
|
416
|
+
const item = this.pendingWrites.shift();
|
|
417
|
+
if (item) {
|
|
418
|
+
await this.currentFile.writeLine(Buffer3.from(item));
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
getFile() {
|
|
423
|
+
return this.files.shift();
|
|
424
|
+
}
|
|
425
|
+
retryFileLater(file) {
|
|
426
|
+
this.files.unshift(file);
|
|
427
|
+
}
|
|
428
|
+
async rotateFile() {
|
|
429
|
+
if (this.currentFile) {
|
|
430
|
+
await this.currentFile.close();
|
|
431
|
+
this.files.push(this.currentFile);
|
|
432
|
+
this.currentFile = null;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
async maintain() {
|
|
436
|
+
await this.writeToFile();
|
|
437
|
+
if (this.currentFile && this.currentFile.size > MAX_FILE_SIZE) {
|
|
438
|
+
await this.rotateFile();
|
|
439
|
+
}
|
|
440
|
+
while (this.files.length > MAX_FILES) {
|
|
441
|
+
const file = this.files.shift();
|
|
442
|
+
file == null ? void 0 : file.delete();
|
|
443
|
+
}
|
|
444
|
+
if (this.suspendUntil !== null && this.suspendUntil < Date.now()) {
|
|
445
|
+
this.suspendUntil = null;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
async clear() {
|
|
449
|
+
this.pendingWrites = [];
|
|
450
|
+
await this.rotateFile();
|
|
451
|
+
this.files.forEach((file) => {
|
|
452
|
+
file.delete();
|
|
453
|
+
});
|
|
454
|
+
this.files = [];
|
|
455
|
+
}
|
|
456
|
+
async close() {
|
|
457
|
+
this.enabled = false;
|
|
458
|
+
await this.clear();
|
|
459
|
+
if (this.maintainIntervalId) {
|
|
460
|
+
clearInterval(this.maintainIntervalId);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
__name(_RequestLogger, "RequestLogger");
|
|
465
|
+
var RequestLogger = _RequestLogger;
|
|
466
|
+
function matchPatterns(value, patterns) {
|
|
467
|
+
return patterns.some((pattern) => {
|
|
468
|
+
return pattern.test(value);
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
__name(matchPatterns, "matchPatterns");
|
|
472
|
+
function skipEmptyValues(data) {
|
|
473
|
+
return Object.fromEntries(Object.entries(data).filter(([_, v]) => {
|
|
474
|
+
if (v == null || Number.isNaN(v)) return false;
|
|
475
|
+
if (Array.isArray(v) || Buffer3.isBuffer(v) || typeof v === "string") {
|
|
476
|
+
return v.length > 0;
|
|
477
|
+
}
|
|
478
|
+
return true;
|
|
479
|
+
}));
|
|
480
|
+
}
|
|
481
|
+
__name(skipEmptyValues, "skipEmptyValues");
|
|
482
|
+
function checkWritableFs() {
|
|
483
|
+
try {
|
|
484
|
+
const testPath = join2(tmpdir2(), `apitally-${randomUUID2()}`);
|
|
485
|
+
writeFileSync(testPath, "test");
|
|
486
|
+
unlinkSync2(testPath);
|
|
487
|
+
return true;
|
|
488
|
+
} catch (error) {
|
|
489
|
+
return false;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
__name(checkWritableFs, "checkWritableFs");
|
|
493
|
+
|
|
162
494
|
// src/common/serverErrorCounter.ts
|
|
163
495
|
import { createHash } from "crypto";
|
|
164
496
|
var MAX_MSG_LENGTH = 2048;
|
|
@@ -331,11 +663,12 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
331
663
|
startupData;
|
|
332
664
|
startupDataSent = false;
|
|
333
665
|
requestCounter;
|
|
666
|
+
requestLogger;
|
|
334
667
|
validationErrorCounter;
|
|
335
668
|
serverErrorCounter;
|
|
336
669
|
consumerRegistry;
|
|
337
670
|
logger;
|
|
338
|
-
constructor({ clientId, env = "dev", logger }) {
|
|
671
|
+
constructor({ clientId, env = "dev", requestLoggingConfig, logger }) {
|
|
339
672
|
if (_ApitallyClient.instance) {
|
|
340
673
|
throw new Error("Apitally client is already initialized");
|
|
341
674
|
}
|
|
@@ -348,9 +681,10 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
348
681
|
_ApitallyClient.instance = this;
|
|
349
682
|
this.clientId = clientId;
|
|
350
683
|
this.env = env;
|
|
351
|
-
this.instanceUuid =
|
|
684
|
+
this.instanceUuid = randomUUID3();
|
|
352
685
|
this.syncDataQueue = [];
|
|
353
686
|
this.requestCounter = new RequestCounter();
|
|
687
|
+
this.requestLogger = new RequestLogger(requestLoggingConfig);
|
|
354
688
|
this.validationErrorCounter = new ValidationErrorCounter();
|
|
355
689
|
this.serverErrorCounter = new ServerErrorCounter();
|
|
356
690
|
this.consumerRegistry = new ConsumerRegistry();
|
|
@@ -372,6 +706,8 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
372
706
|
async handleShutdown() {
|
|
373
707
|
this.stopSync();
|
|
374
708
|
await this.sendSyncData();
|
|
709
|
+
await this.sendLogData();
|
|
710
|
+
await this.requestLogger.close();
|
|
375
711
|
_ApitallyClient.instance = void 0;
|
|
376
712
|
}
|
|
377
713
|
getHubUrlPrefix() {
|
|
@@ -418,7 +754,8 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
418
754
|
async sync() {
|
|
419
755
|
try {
|
|
420
756
|
const promises = [
|
|
421
|
-
this.sendSyncData()
|
|
757
|
+
this.sendSyncData(),
|
|
758
|
+
this.sendLogData()
|
|
422
759
|
];
|
|
423
760
|
if (!this.startupDataSent) {
|
|
424
761
|
promises.push(this.sendStartupData());
|
|
@@ -446,7 +783,7 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
446
783
|
this.logger.debug("Sending startup data to Apitally Hub");
|
|
447
784
|
const payload = {
|
|
448
785
|
instance_uuid: this.instanceUuid,
|
|
449
|
-
message_uuid:
|
|
786
|
+
message_uuid: randomUUID3(),
|
|
450
787
|
...this.startupData
|
|
451
788
|
};
|
|
452
789
|
try {
|
|
@@ -468,7 +805,7 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
468
805
|
const newPayload = {
|
|
469
806
|
time_offset: 0,
|
|
470
807
|
instance_uuid: this.instanceUuid,
|
|
471
|
-
message_uuid:
|
|
808
|
+
message_uuid: randomUUID3(),
|
|
472
809
|
requests: this.requestCounter.getAndResetRequests(),
|
|
473
810
|
validation_errors: this.validationErrorCounter.getAndResetValidationErrors(),
|
|
474
811
|
server_errors: this.serverErrorCounter.getAndResetServerErrors(),
|
|
@@ -487,8 +824,7 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
487
824
|
const timeOffset = Date.now() - time;
|
|
488
825
|
if (timeOffset <= MAX_QUEUE_TIME) {
|
|
489
826
|
if (i > 0) {
|
|
490
|
-
|
|
491
|
-
await new Promise((resolve) => setTimeout(resolve, waitMs));
|
|
827
|
+
await this.randomDelay();
|
|
492
828
|
}
|
|
493
829
|
payload.time_offset = timeOffset / 1e3;
|
|
494
830
|
await this.sendData("sync", payload);
|
|
@@ -507,6 +843,52 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
507
843
|
}
|
|
508
844
|
}
|
|
509
845
|
}
|
|
846
|
+
async sendLogData() {
|
|
847
|
+
this.logger.debug("Sending request log data to Apitally Hub");
|
|
848
|
+
await this.requestLogger.rotateFile();
|
|
849
|
+
const fetchWithRetry = fetchRetry(fetch, {
|
|
850
|
+
retries: 3,
|
|
851
|
+
retryDelay: 1e3,
|
|
852
|
+
retryOn: [
|
|
853
|
+
408,
|
|
854
|
+
429,
|
|
855
|
+
500,
|
|
856
|
+
502,
|
|
857
|
+
503,
|
|
858
|
+
504
|
|
859
|
+
]
|
|
860
|
+
});
|
|
861
|
+
let i = 0;
|
|
862
|
+
let logFile;
|
|
863
|
+
while (logFile = this.requestLogger.getFile()) {
|
|
864
|
+
if (i > 0) {
|
|
865
|
+
await this.randomDelay();
|
|
866
|
+
}
|
|
867
|
+
try {
|
|
868
|
+
const response = await fetchWithRetry(`${this.getHubUrlPrefix()}log?uuid=${logFile.uuid}`, {
|
|
869
|
+
method: "POST",
|
|
870
|
+
body: await logFile.getContent()
|
|
871
|
+
});
|
|
872
|
+
if (response.status === 402 && response.headers.has("Retry-After")) {
|
|
873
|
+
const retryAfter = parseInt(response.headers.get("Retry-After") ?? "0");
|
|
874
|
+
if (retryAfter > 0) {
|
|
875
|
+
this.requestLogger.suspendUntil = Date.now() + retryAfter * 1e3;
|
|
876
|
+
this.requestLogger.clear();
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
if (!response.ok) {
|
|
881
|
+
throw new HTTPError(response);
|
|
882
|
+
}
|
|
883
|
+
logFile.delete();
|
|
884
|
+
} catch (error) {
|
|
885
|
+
this.requestLogger.retryFileLater(logFile);
|
|
886
|
+
break;
|
|
887
|
+
}
|
|
888
|
+
i++;
|
|
889
|
+
if (i >= 10) break;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
510
892
|
handleHubError(error) {
|
|
511
893
|
if (error instanceof HTTPError) {
|
|
512
894
|
if (error.response.status === 404) {
|
|
@@ -521,6 +903,10 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
521
903
|
}
|
|
522
904
|
return false;
|
|
523
905
|
}
|
|
906
|
+
async randomDelay() {
|
|
907
|
+
const delay = 100 + Math.random() * 200;
|
|
908
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
909
|
+
}
|
|
524
910
|
};
|
|
525
911
|
__name(_ApitallyClient, "ApitallyClient");
|
|
526
912
|
__publicField(_ApitallyClient, "instance");
|