logixia 2.0.11 → 2.2.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 +4 -3
- package/dist/{async-context-BGUCdYAa.mjs → async-context-1YMPGgJZ.mjs} +3 -3
- package/dist/{async-context-BGUCdYAa.mjs.map → async-context-1YMPGgJZ.mjs.map} +1 -1
- package/dist/{async-context-D8um9I5V.js → async-context-CoPhbRG0.js} +4 -4
- package/dist/{async-context-D8um9I5V.js.map → async-context-CoPhbRG0.js.map} +1 -1
- package/dist/{azure-monitor.transport-CTnfwA0F.mjs → azure-monitor.transport-B_dqSV_o.mjs} +4 -4
- package/dist/{azure-monitor.transport-CTnfwA0F.mjs.map → azure-monitor.transport-B_dqSV_o.mjs.map} +1 -1
- package/dist/{azure-monitor.transport-C8KdmsSw.js → azure-monitor.transport-Bl3xVvpN.js} +4 -4
- package/dist/{azure-monitor.transport-C8KdmsSw.js.map → azure-monitor.transport-Bl3xVvpN.js.map} +1 -1
- package/dist/{azure-monitor.transport-CbSHOnNX.d.mts → azure-monitor.transport-C5VjvREZ.d.mts} +2 -2
- package/dist/{azure-monitor.transport-CbSHOnNX.d.mts.map → azure-monitor.transport-C5VjvREZ.d.mts.map} +1 -1
- package/dist/{azure-monitor.transport-Bvf7Xegt.d.ts → azure-monitor.transport-CyHDjHS-.d.ts} +2 -2
- package/dist/{azure-monitor.transport-Bvf7Xegt.d.ts.map → azure-monitor.transport-CyHDjHS-.d.ts.map} +1 -1
- package/dist/azure.d.mts +1 -1
- package/dist/azure.d.ts +1 -1
- package/dist/azure.js +1 -1
- package/dist/azure.mjs +1 -1
- package/dist/{batch-buffer-BJqzpfpT.mjs → batch-buffer-BnmVCCwI.mjs} +2 -2
- package/dist/{batch-buffer-BJqzpfpT.mjs.map → batch-buffer-BnmVCCwI.mjs.map} +1 -1
- package/dist/{batch-buffer-BTQdAXwC.js → batch-buffer-C-ETEX3Y.js} +2 -2
- package/dist/{batch-buffer-BTQdAXwC.js.map → batch-buffer-C-ETEX3Y.js.map} +1 -1
- package/dist/browser.d.mts +2 -0
- package/dist/browser.d.mts.map +1 -1
- package/dist/browser.d.ts +2 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +33 -15
- package/dist/browser.js.map +1 -1
- package/dist/browser.mjs +33 -15
- package/dist/browser.mjs.map +1 -1
- package/dist/{builder-C6kKEVrU.mjs → builder-CbttbixM.mjs} +158 -279
- package/dist/builder-CbttbixM.mjs.map +1 -0
- package/dist/{builder-Up4YxX7l.js → builder-Ck1tsC5d.js} +160 -305
- package/dist/builder-Ck1tsC5d.js.map +1 -0
- package/dist/cloudwatch.d.mts +1 -1
- package/dist/cloudwatch.d.ts +1 -1
- package/dist/cloudwatch.js +1 -1
- package/dist/cloudwatch.mjs +1 -1
- package/dist/{cloudwatch.transport-Bl1qzdBx.mjs → cloudwatch.transport-Brh5fmRN.mjs} +5 -5
- package/dist/{cloudwatch.transport-Bl1qzdBx.mjs.map → cloudwatch.transport-Brh5fmRN.mjs.map} +1 -1
- package/dist/{cloudwatch.transport-BoCyxNKO.js → cloudwatch.transport-DO9e__Z-.js} +5 -5
- package/dist/{cloudwatch.transport-BoCyxNKO.js.map → cloudwatch.transport-DO9e__Z-.js.map} +1 -1
- package/dist/{cloudwatch.transport-CQyT6U91.d.ts → cloudwatch.transport-DdSjUWvu.d.ts} +2 -2
- package/dist/{cloudwatch.transport-CQyT6U91.d.ts.map → cloudwatch.transport-DdSjUWvu.d.ts.map} +1 -1
- package/dist/{cloudwatch.transport-CjVrI6S4.d.mts → cloudwatch.transport-_hS7Mcc5.d.mts} +2 -2
- package/dist/{cloudwatch.transport-CjVrI6S4.d.mts.map → cloudwatch.transport-_hS7Mcc5.d.mts.map} +1 -1
- package/dist/correlation.js +3 -3
- package/dist/correlation.mjs +3 -3
- package/dist/{entry-fields-CJbeaoBs.js → entry-fields-BSLkzw18.js} +3 -3
- package/dist/{entry-fields-CJbeaoBs.js.map → entry-fields-BSLkzw18.js.map} +1 -1
- package/dist/{entry-fields-D_aNnjg0.mjs → entry-fields-J1OBi24o.mjs} +2 -2
- package/dist/{entry-fields-D_aNnjg0.mjs.map → entry-fields-J1OBi24o.mjs.map} +1 -1
- package/dist/error.utils-B8_CwESF.mjs +189 -0
- package/dist/error.utils-B8_CwESF.mjs.map +1 -0
- package/dist/error.utils-fZkRExam.js +212 -0
- package/dist/error.utils-fZkRExam.js.map +1 -0
- package/dist/fastify.d.mts +89 -0
- package/dist/fastify.d.mts.map +1 -0
- package/dist/fastify.d.ts +89 -0
- package/dist/fastify.d.ts.map +1 -0
- package/dist/fastify.js +265 -0
- package/dist/fastify.js.map +1 -0
- package/dist/fastify.mjs +263 -0
- package/dist/fastify.mjs.map +1 -0
- package/dist/gcp.d.mts +1 -1
- package/dist/gcp.d.ts +1 -1
- package/dist/gcp.js +1 -1
- package/dist/gcp.mjs +1 -1
- package/dist/{gcp.transport-DOH4bpWM.mjs → gcp.transport-BY1Z3cS0.mjs} +5 -5
- package/dist/{gcp.transport-DOH4bpWM.mjs.map → gcp.transport-BY1Z3cS0.mjs.map} +1 -1
- package/dist/{gcp.transport-D9SdLPwP.d.mts → gcp.transport-C8VJiEM7.d.mts} +2 -2
- package/dist/{gcp.transport-D9SdLPwP.d.mts.map → gcp.transport-C8VJiEM7.d.mts.map} +1 -1
- package/dist/{gcp.transport-BCIvdFV-.d.ts → gcp.transport-Ct0BtKFo.d.ts} +2 -2
- package/dist/{gcp.transport-BCIvdFV-.d.ts.map → gcp.transport-Ct0BtKFo.d.ts.map} +1 -1
- package/dist/{gcp.transport-D_NHVZrw.js → gcp.transport-V9R4dwdT.js} +5 -5
- package/dist/{gcp.transport-D_NHVZrw.js.map → gcp.transport-V9R4dwdT.js.map} +1 -1
- package/dist/hono.d.mts +66 -0
- package/dist/hono.d.mts.map +1 -0
- package/dist/hono.d.ts +66 -0
- package/dist/hono.d.ts.map +1 -0
- package/dist/hono.js +512 -0
- package/dist/hono.js.map +1 -0
- package/dist/hono.mjs +511 -0
- package/dist/hono.mjs.map +1 -0
- package/dist/{index-BAkPHp5D.d.mts → index-B3ajtXJd.d.mts} +2 -2
- package/dist/{index-BAkPHp5D.d.mts.map → index-B3ajtXJd.d.mts.map} +1 -1
- package/dist/{index-e7LowmAu.d.ts → index-oqD3WNxf.d.ts} +2 -2
- package/dist/{index-e7LowmAu.d.ts.map → index-oqD3WNxf.d.ts.map} +1 -1
- package/dist/index.d.mts +8 -7
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +8 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +11 -9
- package/dist/index.mjs.map +1 -1
- package/dist/{logitron-logger-DVUdgmBY.d.ts → logitron-logger-Csn3e6Qu.d.ts} +2 -2
- package/dist/{logitron-logger-DVUdgmBY.d.ts.map → logitron-logger-Csn3e6Qu.d.ts.map} +1 -1
- package/dist/{logitron-logger-DoWmMjYB.d.mts → logitron-logger-fMOkXr8H.d.mts} +2 -2
- package/dist/{logitron-logger-DoWmMjYB.d.mts.map → logitron-logger-fMOkXr8H.d.mts.map} +1 -1
- package/dist/middleware.d.mts +1 -1
- package/dist/middleware.d.ts +1 -1
- package/dist/middleware.js +6 -5
- package/dist/middleware.js.map +1 -1
- package/dist/middleware.mjs +4 -3
- package/dist/middleware.mjs.map +1 -1
- package/dist/nest.d.mts +47 -15
- package/dist/nest.d.mts.map +1 -1
- package/dist/nest.d.ts +47 -15
- package/dist/nest.d.ts.map +1 -1
- package/dist/nest.js +172 -50
- package/dist/nest.js.map +1 -1
- package/dist/nest.mjs +168 -46
- package/dist/nest.mjs.map +1 -1
- package/dist/{otel-DH6-G6DR.js → otel-BrgvxLDW.js} +319 -66
- package/dist/otel-BrgvxLDW.js.map +1 -0
- package/dist/{otel-DAVxpArV.mjs → otel-C5jBV_l_.mjs} +319 -66
- package/dist/otel-C5jBV_l_.mjs.map +1 -0
- package/dist/own-property-BWkibepN.js +40 -0
- package/dist/own-property-BWkibepN.js.map +1 -0
- package/dist/own-property-CjFw9qwZ.mjs +29 -0
- package/dist/own-property-CjFw9qwZ.mjs.map +1 -0
- package/dist/{request-trace-C7kXMjx5.js → request-trace-6NBSw5lt.js} +14 -3
- package/dist/{request-trace-C7kXMjx5.js.map → request-trace-6NBSw5lt.js.map} +1 -1
- package/dist/{request-trace-Dekcnenb.mjs → request-trace-txUhyyre.mjs} +9 -4
- package/dist/{request-trace-Dekcnenb.mjs.map → request-trace-txUhyyre.mjs.map} +1 -1
- package/dist/{safe-stringify-pZOnzGRJ.mjs → safe-stringify-B5p5ktFe.mjs} +2 -2
- package/dist/{safe-stringify-pZOnzGRJ.mjs.map → safe-stringify-B5p5ktFe.mjs.map} +1 -1
- package/dist/{safe-stringify-CJisLyZ3.js → safe-stringify-J3sh-7YM.js} +5 -5
- package/dist/{safe-stringify-CJisLyZ3.js.map → safe-stringify-J3sh-7YM.js.map} +1 -1
- package/dist/{search-Crf2IEoA.d.mts → search-B-hJe2N-.d.mts} +7 -3
- package/dist/{search-Crf2IEoA.d.mts.map → search-B-hJe2N-.d.mts.map} +1 -1
- package/dist/{search-B4eEzrhM.d.ts → search-BlKBLm5D.d.ts} +7 -3
- package/dist/{search-B4eEzrhM.d.ts.map → search-BlKBLm5D.d.ts.map} +1 -1
- package/dist/{search-CjYl-mo5.mjs → search-CTR4XNHq.mjs} +52 -14
- package/dist/search-CTR4XNHq.mjs.map +1 -0
- package/dist/{search-CJw_xoQl.js → search-_qx4YzRP.js} +52 -14
- package/dist/search-_qx4YzRP.js.map +1 -0
- package/dist/search.d.mts +1 -1
- package/dist/search.d.ts +1 -1
- package/dist/search.js +1 -1
- package/dist/search.mjs +1 -1
- package/dist/{secret-config-D1F4MW69.mjs → secret-config-Cng7XPLx.mjs} +18 -13
- package/dist/secret-config-Cng7XPLx.mjs.map +1 -0
- package/dist/{secret-config-6hdODxBb.js → secret-config-OqmIPmpV.js} +21 -16
- package/dist/secret-config-OqmIPmpV.js.map +1 -0
- package/dist/{sensitive-names-wv27qBQC.mjs → sensitive-names-BiBM6R1X.mjs} +2 -28
- package/dist/sensitive-names-BiBM6R1X.mjs.map +1 -0
- package/dist/{sensitive-names-CNgHaqv9.js → sensitive-names-NiKIRhp5.js} +1 -39
- package/dist/sensitive-names-NiKIRhp5.js.map +1 -0
- package/dist/{slack.transport-C6E0l4kw.d.ts → slack.transport-5OPL7H3u.d.mts} +76 -3
- package/dist/slack.transport-5OPL7H3u.d.mts.map +1 -0
- package/dist/{slack.transport-BDyENuR0.d.mts → slack.transport-BFpBD_Ri.d.ts} +76 -3
- package/dist/slack.transport-BFpBD_Ri.d.ts.map +1 -0
- package/dist/{slack.transport-YvaLJxNv.mjs → slack.transport-C6dzPJHX.mjs} +226 -9
- package/dist/slack.transport-C6dzPJHX.mjs.map +1 -0
- package/dist/{slack.transport-CEYBVzUj.js → slack.transport-Ci0swStG.js} +231 -8
- package/dist/slack.transport-Ci0swStG.js.map +1 -0
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/{transport.types-CzJq4IrF.d.ts → transport.types-B1ejJJP6.d.mts} +6 -1
- package/dist/transport.types-B1ejJJP6.d.mts.map +1 -0
- package/dist/{transport.types-CzJq4IrF.d.mts → transport.types-B1ejJJP6.d.ts} +6 -1
- package/dist/transport.types-B1ejJJP6.d.ts.map +1 -0
- package/dist/transports.d.mts +61 -11
- package/dist/transports.d.mts.map +1 -1
- package/dist/transports.d.ts +61 -11
- package/dist/transports.d.ts.map +1 -1
- package/dist/transports.js +7 -6
- package/dist/transports.mjs +7 -7
- package/dist/worker-entry.js +106 -22
- package/dist/worker.d.mts +1 -1
- package/dist/worker.d.ts +1 -1
- package/dist/worker.js +1 -1
- package/dist/worker.mjs +1 -1
- package/dist/{worker.transport-B9mCQSM1.d.ts → worker.transport-B7olL1Uh.d.ts} +12 -2
- package/dist/worker.transport-B7olL1Uh.d.ts.map +1 -0
- package/dist/{worker.transport-CwNpH98o.js → worker.transport-CZOutlxC.js} +40 -2
- package/dist/worker.transport-CZOutlxC.js.map +1 -0
- package/dist/{worker.transport-DgK_ZXlB.mjs → worker.transport-CxFD8mvS.mjs} +40 -2
- package/dist/worker.transport-CxFD8mvS.mjs.map +1 -0
- package/dist/{worker.transport-Bl8lFRck.d.mts → worker.transport-DnU0_9Bd.d.mts} +12 -2
- package/dist/worker.transport-DnU0_9Bd.d.mts.map +1 -0
- package/package.json +37 -2
- package/dist/builder-C6kKEVrU.mjs.map +0 -1
- package/dist/builder-Up4YxX7l.js.map +0 -1
- package/dist/otel-DAVxpArV.mjs.map +0 -1
- package/dist/otel-DH6-G6DR.js.map +0 -1
- package/dist/search-CJw_xoQl.js.map +0 -1
- package/dist/search-CjYl-mo5.mjs.map +0 -1
- package/dist/secret-config-6hdODxBb.js.map +0 -1
- package/dist/secret-config-D1F4MW69.mjs.map +0 -1
- package/dist/sensitive-names-CNgHaqv9.js.map +0 -1
- package/dist/sensitive-names-wv27qBQC.mjs.map +0 -1
- package/dist/slack.transport-BDyENuR0.d.mts.map +0 -1
- package/dist/slack.transport-C6E0l4kw.d.ts.map +0 -1
- package/dist/slack.transport-CEYBVzUj.js.map +0 -1
- package/dist/slack.transport-YvaLJxNv.mjs.map +0 -1
- package/dist/transport.types-CzJq4IrF.d.mts.map +0 -1
- package/dist/transport.types-CzJq4IrF.d.ts.map +0 -1
- package/dist/worker.transport-B9mCQSM1.d.ts.map +0 -1
- package/dist/worker.transport-Bl8lFRck.d.mts.map +0 -1
- package/dist/worker.transport-CwNpH98o.js.map +0 -1
- package/dist/worker.transport-DgK_ZXlB.mjs.map +0 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { t as __require } from "./rolldown-runtime-D3PmRqjj.mjs";
|
|
2
|
-
import { n as protectSecrets, o as urlSecrets, r as scrubError, t as collectSecrets } from "./secret-config-
|
|
2
|
+
import { n as protectSecrets, o as urlSecrets, r as scrubError, t as collectSecrets } from "./secret-config-Cng7XPLx.mjs";
|
|
3
3
|
import { n as internalLog, r as internalWarn, t as internalError } from "./internal-log-Cy5nF1ZL.mjs";
|
|
4
|
+
import { i as stringifyForLog } from "./safe-stringify-B5p5ktFe.mjs";
|
|
4
5
|
import { n as safeToString, t as csvField$1 } from "./csv.utils-ZdxSod5g.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
6
|
+
import { t as mergeCoreFields } from "./entry-fields-J1OBi24o.mjs";
|
|
7
|
+
import { r as DEFAULT_REQUEST_TIMEOUT_MS } from "./batch-buffer-BnmVCCwI.mjs";
|
|
7
8
|
import { EventEmitter } from "node:events";
|
|
8
9
|
import { promisify } from "node:util";
|
|
9
10
|
import { createGzip, gzip } from "node:zlib";
|
|
@@ -249,6 +250,7 @@ function isDataError(type, error) {
|
|
|
249
250
|
return false;
|
|
250
251
|
}
|
|
251
252
|
/** A write that stored part of a batch: only `remaining` still needs to be written. */
|
|
253
|
+
var DatabaseUnavailableError = class extends Error {};
|
|
252
254
|
var PartialWriteError = class extends Error {
|
|
253
255
|
remaining;
|
|
254
256
|
constructor(message, remaining, cause) {
|
|
@@ -296,6 +298,8 @@ var DatabaseTransport = class {
|
|
|
296
298
|
connection;
|
|
297
299
|
isConnected = false;
|
|
298
300
|
connectionPromise;
|
|
301
|
+
connectFailures = 0;
|
|
302
|
+
nextConnectAt = 0;
|
|
299
303
|
cap;
|
|
300
304
|
constructor(config) {
|
|
301
305
|
this.config = config;
|
|
@@ -317,9 +321,12 @@ var DatabaseTransport = class {
|
|
|
317
321
|
];
|
|
318
322
|
}
|
|
319
323
|
async write(entry) {
|
|
320
|
-
if (!this.isConnected) await this.connect();
|
|
321
324
|
this.addToBatch(entry);
|
|
322
|
-
if (this.batch.length >= this.batchSize)
|
|
325
|
+
if (this.batch.length >= this.batchSize) try {
|
|
326
|
+
await this.flush();
|
|
327
|
+
} catch (error) {
|
|
328
|
+
if (!(error instanceof DatabaseUnavailableError)) throw error;
|
|
329
|
+
}
|
|
323
330
|
}
|
|
324
331
|
addToBatch(entry) {
|
|
325
332
|
this.batch.push(entry);
|
|
@@ -344,6 +351,7 @@ var DatabaseTransport = class {
|
|
|
344
351
|
*/
|
|
345
352
|
async drain() {
|
|
346
353
|
while (this.batch.length > 0) {
|
|
354
|
+
await this.ensureConnected();
|
|
347
355
|
const entries = this.batch.splice(0, this.batchSize);
|
|
348
356
|
try {
|
|
349
357
|
await this.writeEntries(entries);
|
|
@@ -441,6 +449,38 @@ var DatabaseTransport = class {
|
|
|
441
449
|
return false;
|
|
442
450
|
}
|
|
443
451
|
}
|
|
452
|
+
async ensureConnected() {
|
|
453
|
+
if (this.isConnected) return;
|
|
454
|
+
const wait = this.nextConnectAt - Date.now();
|
|
455
|
+
if (wait > 0) throw new DatabaseUnavailableError(`Database unavailable; next connect attempt in ${wait}ms`);
|
|
456
|
+
try {
|
|
457
|
+
await this.connect();
|
|
458
|
+
this.connectFailures = 0;
|
|
459
|
+
} catch (error) {
|
|
460
|
+
this.connectFailures += 1;
|
|
461
|
+
this.nextConnectAt = Date.now() + Math.min(3e4, 1e3 * 2 ** (this.connectFailures - 1));
|
|
462
|
+
internalError("Database connection error", error);
|
|
463
|
+
throw new DatabaseUnavailableError("Database unavailable", { cause: error });
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* The driver reported the connection gone (idle timeout, server restart,
|
|
468
|
+
* network drop). Forget it so the next flush reconnects; without an 'error'
|
|
469
|
+
* listener the driver's emitter would crash the process.
|
|
470
|
+
*/
|
|
471
|
+
onConnectionLost(connection, error) {
|
|
472
|
+
if (this.connection !== connection) return;
|
|
473
|
+
if (error) internalError("Database connection lost", error);
|
|
474
|
+
this.isConnected = false;
|
|
475
|
+
this.connectionPromise = void 0;
|
|
476
|
+
this.connection = void 0;
|
|
477
|
+
}
|
|
478
|
+
watchConnection(connection) {
|
|
479
|
+
var _connection$on, _connection$on2;
|
|
480
|
+
const lost = (error) => this.onConnectionLost(connection, error);
|
|
481
|
+
(_connection$on = connection.on) === null || _connection$on === void 0 || _connection$on.call(connection, "error", lost);
|
|
482
|
+
(_connection$on2 = connection.on) === null || _connection$on2 === void 0 || _connection$on2.call(connection, "end", () => lost());
|
|
483
|
+
}
|
|
444
484
|
async connect() {
|
|
445
485
|
if (this.connectionPromise) return this.connectionPromise;
|
|
446
486
|
this.connectionPromise = this.establishConnection().catch((error) => {
|
|
@@ -477,6 +517,7 @@ var DatabaseTransport = class {
|
|
|
477
517
|
});
|
|
478
518
|
const connectionString = this.config.connectionString || `mongodb://${this.config.host}:${this.config.port}/${this.config.database}`;
|
|
479
519
|
this.connection = new MongoClient(connectionString);
|
|
520
|
+
this.watchConnection(this.connection);
|
|
480
521
|
await this.connection.connect();
|
|
481
522
|
await this.connection.db(this.config.database).admin().ping();
|
|
482
523
|
} catch (error) {
|
|
@@ -498,6 +539,7 @@ var DatabaseTransport = class {
|
|
|
498
539
|
if (this.config.password) config.password = this.config.password;
|
|
499
540
|
if (this.config.ssl) config.ssl = typeof this.config.ssl === "boolean" ? {} : this.config.ssl;
|
|
500
541
|
this.connection = new Client(config);
|
|
542
|
+
this.watchConnection(this.connection);
|
|
501
543
|
await this.connection.connect();
|
|
502
544
|
await this.createPostgreSQLTable();
|
|
503
545
|
} catch (error) {
|
|
@@ -518,6 +560,7 @@ var DatabaseTransport = class {
|
|
|
518
560
|
if (this.config.password) config.password = this.config.password;
|
|
519
561
|
if (this.config.ssl) config.ssl = typeof this.config.ssl === "boolean" ? {} : this.config.ssl;
|
|
520
562
|
this.connection = await mysql.createConnection(config);
|
|
563
|
+
this.watchConnection(this.connection);
|
|
521
564
|
await this.createMySQLTable();
|
|
522
565
|
} catch (error) {
|
|
523
566
|
throw new Error(`MySQL connection failed: ${error}`, { cause: error });
|
|
@@ -740,6 +783,7 @@ var DatabaseTransport = class {
|
|
|
740
783
|
this.flushTimer = void 0;
|
|
741
784
|
}
|
|
742
785
|
const MAX_CLOSE_FLUSH_ATTEMPTS = 3;
|
|
786
|
+
this.nextConnectAt = 0;
|
|
743
787
|
if (this.flushPromise) await this.flushPromise.catch(() => {});
|
|
744
788
|
for (let attempt = 0; attempt < MAX_CLOSE_FLUSH_ATTEMPTS && this.batch.length > 0; attempt += 1) try {
|
|
745
789
|
await this.flush();
|
|
@@ -748,17 +792,19 @@ var DatabaseTransport = class {
|
|
|
748
792
|
}
|
|
749
793
|
if (this.batch.length > 0) internalError(`Database transport closing with ${this.batch.length} unflushed log entr${this.batch.length === 1 ? "y" : "ies"} after ${MAX_CLOSE_FLUSH_ATTEMPTS} attempts`);
|
|
750
794
|
this.cap.report(0);
|
|
751
|
-
|
|
795
|
+
const connection = this.connection;
|
|
796
|
+
this.connection = void 0;
|
|
797
|
+
if (connection) switch (this.config.type) {
|
|
752
798
|
case "mongodb":
|
|
753
|
-
await
|
|
799
|
+
await connection.close();
|
|
754
800
|
break;
|
|
755
801
|
case "postgresql":
|
|
756
|
-
await
|
|
802
|
+
await connection.end();
|
|
757
803
|
break;
|
|
758
804
|
case "mysql":
|
|
759
|
-
await
|
|
805
|
+
await connection.end();
|
|
760
806
|
break;
|
|
761
|
-
case "sqlite": await
|
|
807
|
+
case "sqlite": await connection.close();
|
|
762
808
|
}
|
|
763
809
|
this.isConnected = false;
|
|
764
810
|
}
|
|
@@ -833,6 +879,9 @@ var AnalyticsTransport = class {
|
|
|
833
879
|
/** Set on the first write. Subclass fields don't exist yet while the base constructor runs. */
|
|
834
880
|
initPromise;
|
|
835
881
|
cap;
|
|
882
|
+
/** Consecutive failed drains; drives the backoff that stops a failing provider being re-sent every Nth log. */
|
|
883
|
+
failures = 0;
|
|
884
|
+
retryAt = 0;
|
|
836
885
|
constructor(name, config) {
|
|
837
886
|
this.name = name;
|
|
838
887
|
this.config = {
|
|
@@ -865,12 +914,13 @@ var AnalyticsTransport = class {
|
|
|
865
914
|
addToBatch(entry) {
|
|
866
915
|
this.batch.push(entry);
|
|
867
916
|
this.cap.enforce(this.batch);
|
|
868
|
-
|
|
869
|
-
|
|
917
|
+
const backoff = this.retryAt - Date.now();
|
|
918
|
+
if (this.batch.length >= (this.config.batchSize || 50) && backoff <= 0) this.flush().catch((err) => internalError(`${this.name} batch flush failed`, err));
|
|
919
|
+
else if (!this.batchTimer && (this.config.flushInterval || backoff > 0)) {
|
|
870
920
|
var _this$batchTimer$unre, _this$batchTimer;
|
|
871
921
|
this.batchTimer = setTimeout(() => {
|
|
872
922
|
this.flush().catch((err) => internalError(`${this.name} interval flush failed`, err));
|
|
873
|
-
}, this.config.flushInterval);
|
|
923
|
+
}, Math.max(this.config.flushInterval || 0, backoff));
|
|
874
924
|
(_this$batchTimer$unre = (_this$batchTimer = this.batchTimer).unref) === null || _this$batchTimer$unre === void 0 || _this$batchTimer$unre.call(_this$batchTimer);
|
|
875
925
|
}
|
|
876
926
|
}
|
|
@@ -897,7 +947,11 @@ var AnalyticsTransport = class {
|
|
|
897
947
|
this.batch = [];
|
|
898
948
|
try {
|
|
899
949
|
await this.sendBatch(entriesToSend);
|
|
950
|
+
this.failures = 0;
|
|
951
|
+
this.retryAt = 0;
|
|
900
952
|
} catch (error) {
|
|
953
|
+
this.failures += 1;
|
|
954
|
+
this.retryAt = Date.now() + Math.min(6e4, 1e3 * 2 ** (this.failures - 1));
|
|
901
955
|
scrubError(error, this.secretValues());
|
|
902
956
|
internalError(`Analytics transport ${this.name} flush failed`, error);
|
|
903
957
|
this.batch.unshift(...error instanceof PartialBatchError ? error.unsent : entriesToSend);
|
|
@@ -960,6 +1014,28 @@ var AnalyticsTransport = class {
|
|
|
960
1014
|
await this.ensureReady();
|
|
961
1015
|
}
|
|
962
1016
|
};
|
|
1017
|
+
// src/transports/fetch-timeout.ts
|
|
1018
|
+
/**
|
|
1019
|
+
* fetch() with a hard deadline, so an endpoint that accepts the connection and
|
|
1020
|
+
* never answers cannot hang a flush (and with it close()) forever. Uses an
|
|
1021
|
+
* AbortController rather than AbortSignal.timeout(), which needs Node 17.3+
|
|
1022
|
+
* while `engines` allows 16; the timer is unref'd so it never holds the process.
|
|
1023
|
+
*/
|
|
1024
|
+
async function fetchWithTimeout(url, init, timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS) {
|
|
1025
|
+
var _timer$unref;
|
|
1026
|
+
const controller = new AbortController();
|
|
1027
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
1028
|
+
(_timer$unref = timer.unref) === null || _timer$unref === void 0 || _timer$unref.call(timer);
|
|
1029
|
+
try {
|
|
1030
|
+
return await fetch(url, {
|
|
1031
|
+
...init,
|
|
1032
|
+
signal: controller.signal
|
|
1033
|
+
});
|
|
1034
|
+
} catch (error) {
|
|
1035
|
+
if (controller.signal.aborted) throw new Error(`Request timed out after ${timeoutMs}ms`, { cause: error });
|
|
1036
|
+
throw error;
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
963
1039
|
// src/transports/datadog.transport.ts
|
|
964
1040
|
const gzipAsync = promisify(gzip);
|
|
965
1041
|
const MAX_LOGS_PER_REQUEST = 1e3;
|
|
@@ -1199,7 +1275,7 @@ var DataDogTransport = class extends AnalyticsTransport {
|
|
|
1199
1275
|
const url = `${this.logsUrl}${endpoint}`;
|
|
1200
1276
|
try {
|
|
1201
1277
|
const compress = this.datadogConfig.compress === true;
|
|
1202
|
-
const response = await
|
|
1278
|
+
const response = await fetchWithTimeout(url, {
|
|
1203
1279
|
method: "POST",
|
|
1204
1280
|
headers: {
|
|
1205
1281
|
"Content-Type": "application/json",
|
|
@@ -1216,7 +1292,7 @@ var DataDogTransport = class extends AnalyticsTransport {
|
|
|
1216
1292
|
async makeMetricsRequest(endpoint, data) {
|
|
1217
1293
|
const url = `${this.metricsUrl}${endpoint}`;
|
|
1218
1294
|
try {
|
|
1219
|
-
const response = await
|
|
1295
|
+
const response = await fetchWithTimeout(url, {
|
|
1220
1296
|
method: "POST",
|
|
1221
1297
|
headers: {
|
|
1222
1298
|
"Content-Type": "application/json",
|
|
@@ -1261,7 +1337,7 @@ var DataDogTransport = class extends AnalyticsTransport {
|
|
|
1261
1337
|
};
|
|
1262
1338
|
const url = `${this.baseUrl}/api/v1/events`;
|
|
1263
1339
|
try {
|
|
1264
|
-
const response = await
|
|
1340
|
+
const response = await fetchWithTimeout(url, {
|
|
1265
1341
|
method: "POST",
|
|
1266
1342
|
headers: {
|
|
1267
1343
|
"Content-Type": "application/json",
|
|
@@ -1373,6 +1449,8 @@ var FileTransport = class {
|
|
|
1373
1449
|
lastDropWarning = 0;
|
|
1374
1450
|
/** Gzip and pruning of rotated files run off the write path, one at a time. */
|
|
1375
1451
|
housekeeping = Promise.resolve();
|
|
1452
|
+
exitListenerAttached = false;
|
|
1453
|
+
onExit = () => this.flushSyncOnExit();
|
|
1376
1454
|
constructor(config) {
|
|
1377
1455
|
this.config = {
|
|
1378
1456
|
format: "json",
|
|
@@ -1461,6 +1539,7 @@ var FileTransport = class {
|
|
|
1461
1539
|
await done;
|
|
1462
1540
|
}
|
|
1463
1541
|
enqueue(entry) {
|
|
1542
|
+
this.attachExitListener();
|
|
1464
1543
|
if (this.queueFull()) {
|
|
1465
1544
|
if (this.queuePolicy === "drop-oldest" && this.batch.length > 0) {
|
|
1466
1545
|
this.batch.shift();
|
|
@@ -1472,6 +1551,30 @@ var FileTransport = class {
|
|
|
1472
1551
|
this.batch.push(entry);
|
|
1473
1552
|
this.enqueued += 1;
|
|
1474
1553
|
}
|
|
1554
|
+
attachExitListener() {
|
|
1555
|
+
if (this.exitListenerAttached) return;
|
|
1556
|
+
this.exitListenerAttached = true;
|
|
1557
|
+
process.on("exit", this.onExit);
|
|
1558
|
+
}
|
|
1559
|
+
detachExitListener() {
|
|
1560
|
+
if (!this.exitListenerAttached) return;
|
|
1561
|
+
this.exitListenerAttached = false;
|
|
1562
|
+
process.removeListener("exit", this.onExit);
|
|
1563
|
+
}
|
|
1564
|
+
/**
|
|
1565
|
+
* Last chance on process exit: async writes cannot finish, so whatever is still
|
|
1566
|
+
* batched is appended synchronously to the current file.
|
|
1567
|
+
*/
|
|
1568
|
+
flushSyncOnExit() {
|
|
1569
|
+
if (this.batch.length === 0) return;
|
|
1570
|
+
const pending = this.batch;
|
|
1571
|
+
this.batch = [];
|
|
1572
|
+
this.enqueued -= pending.length;
|
|
1573
|
+
try {
|
|
1574
|
+
const content = pending.map((entry) => this.formatEntry(entry)).join("\n") + "\n";
|
|
1575
|
+
fs.appendFileSync(this.currentFilePath, content, { mode: this.fileMode });
|
|
1576
|
+
} catch {}
|
|
1577
|
+
}
|
|
1475
1578
|
queueFull() {
|
|
1476
1579
|
return this.batch.length + this.inFlight >= this.maxQueue;
|
|
1477
1580
|
}
|
|
@@ -1556,7 +1659,11 @@ var FileTransport = class {
|
|
|
1556
1659
|
case "json": return stringifyForLog(mergeCoreFields({
|
|
1557
1660
|
timestamp: entry.timestamp.toISOString(),
|
|
1558
1661
|
level: entry.level,
|
|
1559
|
-
message: entry.message
|
|
1662
|
+
message: entry.message,
|
|
1663
|
+
context: entry.context,
|
|
1664
|
+
traceId: entry.traceId,
|
|
1665
|
+
appName: entry.appName,
|
|
1666
|
+
environment: entry.environment
|
|
1560
1667
|
}, entry.data));
|
|
1561
1668
|
case "csv": return [
|
|
1562
1669
|
entry.timestamp.toISOString(),
|
|
@@ -1578,9 +1685,12 @@ var FileTransport = class {
|
|
|
1578
1685
|
this.batchTimer = void 0;
|
|
1579
1686
|
}
|
|
1580
1687
|
this.startDrain();
|
|
1581
|
-
} else if (!this.batchTimer && this.config.flushInterval)
|
|
1582
|
-
this.
|
|
1583
|
-
|
|
1688
|
+
} else if (!this.batchTimer && this.config.flushInterval) {
|
|
1689
|
+
this.batchTimer = setTimeout(() => {
|
|
1690
|
+
this.flush().catch((err) => internalError("FileTransport interval flush failed", err));
|
|
1691
|
+
}, this.config.flushInterval);
|
|
1692
|
+
this.batchTimer.unref();
|
|
1693
|
+
}
|
|
1584
1694
|
}
|
|
1585
1695
|
/** Only ever called from drain(), so writes and rotations never overlap. */
|
|
1586
1696
|
async writeBatch(entries) {
|
|
@@ -1746,6 +1856,7 @@ var FileTransport = class {
|
|
|
1746
1856
|
this.batchTimer = void 0;
|
|
1747
1857
|
}
|
|
1748
1858
|
await this.flush();
|
|
1859
|
+
this.detachExitListener();
|
|
1749
1860
|
await this.housekeeping;
|
|
1750
1861
|
this.reportDropped(0);
|
|
1751
1862
|
}
|
|
@@ -1869,7 +1980,7 @@ var GoogleAnalyticsTransport = class extends AnalyticsTransport {
|
|
|
1869
1980
|
api_secret: this.gaConfig.apiSecret
|
|
1870
1981
|
});
|
|
1871
1982
|
try {
|
|
1872
|
-
const response = await
|
|
1983
|
+
const response = await fetchWithTimeout(`${url}?${params}`, {
|
|
1873
1984
|
method: "POST",
|
|
1874
1985
|
headers: { "Content-Type": "application/json" },
|
|
1875
1986
|
body: stringifyForLog(payload)
|
|
@@ -2087,7 +2198,7 @@ var MixpanelTransport = class extends AnalyticsTransport {
|
|
|
2087
2198
|
async makeRequest(endpoint, data) {
|
|
2088
2199
|
const url = `${this.mixpanelConfig.endpoint || this.baseUrl}${endpoint}`;
|
|
2089
2200
|
try {
|
|
2090
|
-
const response = await
|
|
2201
|
+
const response = await fetchWithTimeout(url, {
|
|
2091
2202
|
method: "POST",
|
|
2092
2203
|
headers: {
|
|
2093
2204
|
"Content-Type": "application/json",
|
|
@@ -2256,7 +2367,7 @@ var SegmentTransport = class extends AnalyticsTransport {
|
|
|
2256
2367
|
const url = `${this.baseUrl}${endpoint}`;
|
|
2257
2368
|
const auth = Buffer.from(`${this.segmentConfig.writeKey}:`).toString("base64");
|
|
2258
2369
|
try {
|
|
2259
|
-
const response = await
|
|
2370
|
+
const response = await fetchWithTimeout(url, {
|
|
2260
2371
|
method: "POST",
|
|
2261
2372
|
headers: {
|
|
2262
2373
|
"Content-Type": "application/json",
|
|
@@ -2426,15 +2537,16 @@ var SegmentTransport = class extends AnalyticsTransport {
|
|
|
2426
2537
|
}
|
|
2427
2538
|
};
|
|
2428
2539
|
// src/transports/transport.manager.ts
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
}
|
|
2540
|
+
const DEFAULT_MAX_PENDING_RETRIES = 1e3;
|
|
2541
|
+
const RETRY_WARN_INTERVAL_MS = 5e3;
|
|
2432
2542
|
var TransportManager = class extends EventEmitter {
|
|
2433
2543
|
transports = /* @__PURE__ */ new Map();
|
|
2434
2544
|
metrics = /* @__PURE__ */ new Map();
|
|
2435
2545
|
isShuttingDown = false;
|
|
2436
2546
|
transportLevelPreferences = /* @__PURE__ */ new Map();
|
|
2437
2547
|
warnedPromptDeprecated = false;
|
|
2548
|
+
closePromise;
|
|
2549
|
+
retryStates = /* @__PURE__ */ new Map();
|
|
2438
2550
|
levelValues;
|
|
2439
2551
|
/**
|
|
2440
2552
|
* @param config Transport configuration.
|
|
@@ -2515,8 +2627,9 @@ var TransportManager = class extends EventEmitter {
|
|
|
2515
2627
|
if (!transport) return false;
|
|
2516
2628
|
this.transports.delete(id);
|
|
2517
2629
|
this.metrics.delete(id);
|
|
2630
|
+
this.drainRetries(id, transport);
|
|
2518
2631
|
if (transport.close) transport.close().catch((error) => {
|
|
2519
|
-
|
|
2632
|
+
internalError(`Transport "${id}" failed to close`, error);
|
|
2520
2633
|
});
|
|
2521
2634
|
this.emit("transport:removed", id);
|
|
2522
2635
|
return true;
|
|
@@ -2532,7 +2645,10 @@ var TransportManager = class extends EventEmitter {
|
|
|
2532
2645
|
* sync path.
|
|
2533
2646
|
*/
|
|
2534
2647
|
write(entry) {
|
|
2535
|
-
if (this.isShuttingDown)
|
|
2648
|
+
if (this.isShuttingDown) {
|
|
2649
|
+
this.writeAfterClose(entry);
|
|
2650
|
+
return;
|
|
2651
|
+
}
|
|
2536
2652
|
const transportEntry = {
|
|
2537
2653
|
timestamp: typeof entry.timestamp === "string" ? new Date(entry.timestamp) : entry.timestamp,
|
|
2538
2654
|
level: entry.level,
|
|
@@ -2570,6 +2686,27 @@ var TransportManager = class extends EventEmitter {
|
|
|
2570
2686
|
}
|
|
2571
2687
|
});
|
|
2572
2688
|
}
|
|
2689
|
+
/**
|
|
2690
|
+
* Transports are gone once closed, but the app may still log (its own signal
|
|
2691
|
+
* handler, a late async callback). Emit such lines on stdout/stderr rather
|
|
2692
|
+
* than losing them silently.
|
|
2693
|
+
*/
|
|
2694
|
+
writeAfterClose(entry) {
|
|
2695
|
+
const line = `${stringifyForLog({
|
|
2696
|
+
timestamp: entry.timestamp,
|
|
2697
|
+
level: entry.level,
|
|
2698
|
+
message: entry.message,
|
|
2699
|
+
appName: entry.appName,
|
|
2700
|
+
context: entry.context,
|
|
2701
|
+
traceId: entry.traceId,
|
|
2702
|
+
...entry.payload
|
|
2703
|
+
})}\n`;
|
|
2704
|
+
const level = String(entry.level).toLowerCase();
|
|
2705
|
+
const stream = level === "error" || level === "warn" ? "stderr" : "stdout";
|
|
2706
|
+
try {
|
|
2707
|
+
process[stream].write(line);
|
|
2708
|
+
} catch {}
|
|
2709
|
+
}
|
|
2573
2710
|
writeToTransport(id, transport, entry) {
|
|
2574
2711
|
const startTime = Date.now();
|
|
2575
2712
|
const metrics = this.metrics.get(id);
|
|
@@ -2596,43 +2733,86 @@ var TransportManager = class extends EventEmitter {
|
|
|
2596
2733
|
onSuccess();
|
|
2597
2734
|
return;
|
|
2598
2735
|
}
|
|
2599
|
-
return this._writeWithRetry(transport, entry).then(
|
|
2736
|
+
return this._writeWithRetry(id, transport, entry).then((written) => {
|
|
2737
|
+
if (written) onSuccess();
|
|
2738
|
+
}, onError);
|
|
2600
2739
|
}
|
|
2601
2740
|
/**
|
|
2602
2741
|
* Feature 9: Multi-transport retry + failover.
|
|
2603
2742
|
*
|
|
2604
|
-
*
|
|
2605
|
-
*
|
|
2606
|
-
*
|
|
2743
|
+
* The first attempt is awaited by the caller. If it fails, the entry moves to
|
|
2744
|
+
* a bounded per-transport retry queue and the caller's promise resolves, so a
|
|
2745
|
+
* down transport never holds a log call across backoff. The queue retries up
|
|
2746
|
+
* to `retry.maxRetries` more times with the configured backoff, then routes
|
|
2747
|
+
* the entry to the fallback transport (if any) and calls `onExhausted`.
|
|
2748
|
+
* Returns true when the first attempt succeeded.
|
|
2607
2749
|
*/
|
|
2608
|
-
async _writeWithRetry(transport, entry) {
|
|
2609
|
-
|
|
2610
|
-
if (!retryCfg || !retryCfg.maxRetries) {
|
|
2750
|
+
async _writeWithRetry(id, transport, entry) {
|
|
2751
|
+
try {
|
|
2611
2752
|
await transport.write(entry);
|
|
2612
|
-
return;
|
|
2753
|
+
return true;
|
|
2754
|
+
} catch (err) {
|
|
2755
|
+
this.enqueueRetry(id, transport, entry, err instanceof Error ? err : new Error(String(err)));
|
|
2756
|
+
return false;
|
|
2613
2757
|
}
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2758
|
+
}
|
|
2759
|
+
enqueueRetry(id, transport, entry, error) {
|
|
2760
|
+
let state = this.retryStates.get(id);
|
|
2761
|
+
if (!state) {
|
|
2762
|
+
state = {
|
|
2763
|
+
queue: [],
|
|
2764
|
+
timer: void 0,
|
|
2765
|
+
running: false,
|
|
2766
|
+
dropped: 0,
|
|
2767
|
+
lastWarn: 0
|
|
2768
|
+
};
|
|
2769
|
+
this.retryStates.set(id, state);
|
|
2770
|
+
}
|
|
2771
|
+
const maxPending = transport.retry.maxPending ?? DEFAULT_MAX_PENDING_RETRIES;
|
|
2772
|
+
while (state.queue.length >= maxPending) {
|
|
2773
|
+
state.queue.shift();
|
|
2774
|
+
state.dropped++;
|
|
2775
|
+
}
|
|
2776
|
+
this.warnDropped(id, state);
|
|
2777
|
+
this.scheduleRetry(id, transport, state, {
|
|
2778
|
+
entry,
|
|
2779
|
+
attempt: 0,
|
|
2780
|
+
due: 0
|
|
2781
|
+
}, error);
|
|
2782
|
+
this.pumpRetries(id, transport, state);
|
|
2783
|
+
}
|
|
2784
|
+
warnDropped(id, state) {
|
|
2785
|
+
const now = Date.now();
|
|
2786
|
+
if (state.dropped > 0 && now - state.lastWarn >= RETRY_WARN_INTERVAL_MS) {
|
|
2787
|
+
internalWarn(`TransportManager: retry queue for "${id}" is full; dropped ${state.dropped} oldest log entr${state.dropped === 1 ? "y" : "ies"}`);
|
|
2788
|
+
state.dropped = 0;
|
|
2789
|
+
state.lastWarn = now;
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2792
|
+
/** Queues `item` for its next attempt, or finishes it when retries ran out. */
|
|
2793
|
+
scheduleRetry(id, transport, state, item, error) {
|
|
2794
|
+
const { maxRetries = 0, backoff = "exponential", delay = 500, maxDelay = 3e4 } = transport.retry;
|
|
2795
|
+
if (item.attempt >= maxRetries) {
|
|
2796
|
+
this.exhaust(id, transport, item.entry, error);
|
|
2618
2797
|
return;
|
|
2619
|
-
} catch (err) {
|
|
2620
|
-
lastError = err instanceof Error ? err : new Error(String(err));
|
|
2621
|
-
if (attempt < maxRetries) {
|
|
2622
|
-
let wait;
|
|
2623
|
-
switch (backoff) {
|
|
2624
|
-
case "fixed":
|
|
2625
|
-
wait = baseDelay;
|
|
2626
|
-
break;
|
|
2627
|
-
case "linear":
|
|
2628
|
-
wait = baseDelay * (attempt + 1);
|
|
2629
|
-
break;
|
|
2630
|
-
default: wait = Math.min(baseDelay * Math.pow(2, attempt), maxDelay);
|
|
2631
|
-
}
|
|
2632
|
-
this.emit("transport:retry", transport.name, attempt + 1, maxRetries, wait);
|
|
2633
|
-
await _sleep(wait);
|
|
2634
|
-
}
|
|
2635
2798
|
}
|
|
2799
|
+
let wait;
|
|
2800
|
+
switch (backoff) {
|
|
2801
|
+
case "fixed":
|
|
2802
|
+
wait = delay;
|
|
2803
|
+
break;
|
|
2804
|
+
case "linear":
|
|
2805
|
+
wait = delay * (item.attempt + 1);
|
|
2806
|
+
break;
|
|
2807
|
+
default: wait = Math.min(delay * Math.pow(2, item.attempt), maxDelay);
|
|
2808
|
+
}
|
|
2809
|
+
item.attempt++;
|
|
2810
|
+
item.due = Date.now() + wait;
|
|
2811
|
+
state.queue.push(item);
|
|
2812
|
+
this.emit("transport:retry", transport.name, item.attempt, maxRetries, wait);
|
|
2813
|
+
}
|
|
2814
|
+
async exhaust(id, transport, entry, error) {
|
|
2815
|
+
const { fallback, onExhausted } = transport.retry;
|
|
2636
2816
|
if (fallback) {
|
|
2637
2817
|
this.emit("transport:fallback", transport.name, fallback.name);
|
|
2638
2818
|
try {
|
|
@@ -2640,8 +2820,65 @@ var TransportManager = class extends EventEmitter {
|
|
|
2640
2820
|
return;
|
|
2641
2821
|
} catch {}
|
|
2642
2822
|
}
|
|
2643
|
-
|
|
2644
|
-
|
|
2823
|
+
const metrics = this.metrics.get(id);
|
|
2824
|
+
if (metrics) metrics.errors++;
|
|
2825
|
+
try {
|
|
2826
|
+
onExhausted === null || onExhausted === void 0 || onExhausted(error, entry);
|
|
2827
|
+
} catch (hookError) {
|
|
2828
|
+
internalWarn(`TransportManager: onExhausted for "${id}" threw: ${String(hookError)}`);
|
|
2829
|
+
}
|
|
2830
|
+
if (this.listenerCount("error") > 0) this.emit("error", error, id);
|
|
2831
|
+
}
|
|
2832
|
+
/** One serial worker per transport: the earliest-due entry is retried first. */
|
|
2833
|
+
pumpRetries(id, transport, state) {
|
|
2834
|
+
var _state$timer$unref, _state$timer;
|
|
2835
|
+
if (state.running || state.timer || state.queue.length === 0) return;
|
|
2836
|
+
let next = 0;
|
|
2837
|
+
for (let i = 1; i < state.queue.length; i++) if (state.queue[i].due < state.queue[next].due) next = i;
|
|
2838
|
+
const wait = Math.max(0, state.queue[next].due - Date.now());
|
|
2839
|
+
state.timer = setTimeout(() => {
|
|
2840
|
+
state.timer = void 0;
|
|
2841
|
+
this.runRetry(id, transport, state);
|
|
2842
|
+
}, wait);
|
|
2843
|
+
(_state$timer$unref = (_state$timer = state.timer).unref) === null || _state$timer$unref === void 0 || _state$timer$unref.call(_state$timer);
|
|
2844
|
+
}
|
|
2845
|
+
async runRetry(id, transport, state) {
|
|
2846
|
+
if (state.queue.length === 0) return;
|
|
2847
|
+
let next = 0;
|
|
2848
|
+
for (let i = 1; i < state.queue.length; i++) if (state.queue[i].due < state.queue[next].due) next = i;
|
|
2849
|
+
const [item] = state.queue.splice(next, 1);
|
|
2850
|
+
if (!item) return;
|
|
2851
|
+
state.running = true;
|
|
2852
|
+
try {
|
|
2853
|
+
await transport.write(item.entry);
|
|
2854
|
+
const metrics = this.metrics.get(id);
|
|
2855
|
+
if (metrics) {
|
|
2856
|
+
metrics.logsWritten++;
|
|
2857
|
+
metrics.lastWrite = /* @__PURE__ */ new Date();
|
|
2858
|
+
}
|
|
2859
|
+
this.emit("log", item.entry);
|
|
2860
|
+
} catch (err) {
|
|
2861
|
+
this.scheduleRetry(id, transport, state, item, err instanceof Error ? err : new Error(String(err)));
|
|
2862
|
+
} finally {
|
|
2863
|
+
state.running = false;
|
|
2864
|
+
}
|
|
2865
|
+
if (!this.isShuttingDown) this.pumpRetries(id, transport, state);
|
|
2866
|
+
}
|
|
2867
|
+
/** Stops a transport's retry worker and hands what is still queued to its fallback. */
|
|
2868
|
+
async drainRetries(id, transport) {
|
|
2869
|
+
var _transport$retry;
|
|
2870
|
+
const state = this.retryStates.get(id);
|
|
2871
|
+
if (!state) return;
|
|
2872
|
+
this.retryStates.delete(id);
|
|
2873
|
+
if (state.timer) clearTimeout(state.timer);
|
|
2874
|
+
state.timer = void 0;
|
|
2875
|
+
const fallback = transport === null || transport === void 0 || (_transport$retry = transport.retry) === null || _transport$retry === void 0 ? void 0 : _transport$retry.fallback;
|
|
2876
|
+
if (state.queue.length === 0) return;
|
|
2877
|
+
if (!fallback) {
|
|
2878
|
+
internalWarn(`TransportManager: "${id}" closed with ${state.queue.length} log entr${state.queue.length === 1 ? "y" : "ies"} still awaiting retry`);
|
|
2879
|
+
return;
|
|
2880
|
+
}
|
|
2881
|
+
await Promise.allSettled(state.queue.map((item) => fallback.write(item.entry)));
|
|
2645
2882
|
}
|
|
2646
2883
|
shouldTransportHandle(transport, level, transportId) {
|
|
2647
2884
|
if (transportId && this.transportLevelPreferences.has(transportId)) return this.transportLevelPreferences.get(transportId).includes(level.toLowerCase());
|
|
@@ -2660,19 +2897,35 @@ var TransportManager = class extends EventEmitter {
|
|
|
2660
2897
|
if (readyPromises.length > 0) await Promise.all(readyPromises);
|
|
2661
2898
|
}
|
|
2662
2899
|
async flush() {
|
|
2900
|
+
await this.flushTransports(false);
|
|
2901
|
+
}
|
|
2902
|
+
/**
|
|
2903
|
+
* @param skipClosable Leave out transports with a close(): close() flushes
|
|
2904
|
+
* them itself, and a second flush first would double the time a hung
|
|
2905
|
+
* endpoint can hold shutdown.
|
|
2906
|
+
*/
|
|
2907
|
+
async flushTransports(skipClosable) {
|
|
2663
2908
|
const flushPromises = [];
|
|
2664
|
-
for (const [id, transport] of this.transports)
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2909
|
+
for (const [id, transport] of this.transports) {
|
|
2910
|
+
if (skipClosable && transport.close) continue;
|
|
2911
|
+
if (this.isBatchTransport(transport)) {
|
|
2912
|
+
const flushPromise = transport.flush().catch((error) => {
|
|
2913
|
+
this.emit("error", error, id);
|
|
2914
|
+
});
|
|
2915
|
+
flushPromises.push(flushPromise);
|
|
2916
|
+
}
|
|
2669
2917
|
}
|
|
2670
2918
|
await Promise.allSettled(flushPromises);
|
|
2671
2919
|
this.emit("flush", "all", this.transports.size);
|
|
2672
2920
|
}
|
|
2673
|
-
|
|
2674
|
-
|
|
2921
|
+
close() {
|
|
2922
|
+
this.closePromise ??= this.closeOnce();
|
|
2923
|
+
return this.closePromise;
|
|
2924
|
+
}
|
|
2925
|
+
async closeOnce() {
|
|
2926
|
+
await this.flushTransports(true);
|
|
2675
2927
|
this.isShuttingDown = true;
|
|
2928
|
+
await Promise.allSettled([...this.retryStates.keys()].map((id) => this.drainRetries(id, this.transports.get(id))));
|
|
2676
2929
|
const closePromises = [];
|
|
2677
2930
|
for (const [id, transport] of this.transports) if (transport.close) {
|
|
2678
2931
|
const closePromise = transport.close().catch((error) => {
|
|
@@ -2889,4 +3142,4 @@ function disableOtelBridge() {
|
|
|
2889
3142
|
}
|
|
2890
3143
|
export { ConsoleTransport as _, getActiveOtelContext as a, TransportManager as c, GoogleAnalyticsTransport as d, FileTransport as f, BufferCap as g, DatabaseTransport as h, disableOtelBridge as i, SegmentTransport as l, AnalyticsTransport as m, _getOtelPayloadIfEnabled as n, getOtelMetaFields as o, DataDogTransport as p, _isOtelBridgeEnabled as r, initOtelBridge as s, _getOtelBridgeFieldNames as t, MixpanelTransport as u, stripControlChars as v };
|
|
2891
3144
|
|
|
2892
|
-
//# sourceMappingURL=otel-
|
|
3145
|
+
//# sourceMappingURL=otel-C5jBV_l_.mjs.map
|