logixia 2.0.11 → 2.1.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.
Files changed (177) hide show
  1. package/README.md +2 -1
  2. package/dist/{async-context-D8um9I5V.js → async-context-Dgl3ZLyb.js} +3 -3
  3. package/dist/{async-context-D8um9I5V.js.map → async-context-Dgl3ZLyb.js.map} +1 -1
  4. package/dist/{async-context-BGUCdYAa.mjs → async-context-fBqC5lNc.mjs} +2 -2
  5. package/dist/{async-context-BGUCdYAa.mjs.map → async-context-fBqC5lNc.mjs.map} +1 -1
  6. package/dist/{azure-monitor.transport-CbSHOnNX.d.mts → azure-monitor.transport-C5VjvREZ.d.mts} +2 -2
  7. package/dist/{azure-monitor.transport-CbSHOnNX.d.mts.map → azure-monitor.transport-C5VjvREZ.d.mts.map} +1 -1
  8. package/dist/{azure-monitor.transport-Bvf7Xegt.d.ts → azure-monitor.transport-CyHDjHS-.d.ts} +2 -2
  9. package/dist/{azure-monitor.transport-Bvf7Xegt.d.ts.map → azure-monitor.transport-CyHDjHS-.d.ts.map} +1 -1
  10. package/dist/{azure-monitor.transport-CTnfwA0F.mjs → azure-monitor.transport-DGiacfvT.mjs} +4 -4
  11. package/dist/{azure-monitor.transport-CTnfwA0F.mjs.map → azure-monitor.transport-DGiacfvT.mjs.map} +1 -1
  12. package/dist/{azure-monitor.transport-C8KdmsSw.js → azure-monitor.transport-DX3fuK2t.js} +4 -4
  13. package/dist/{azure-monitor.transport-C8KdmsSw.js.map → azure-monitor.transport-DX3fuK2t.js.map} +1 -1
  14. package/dist/azure.d.mts +1 -1
  15. package/dist/azure.d.ts +1 -1
  16. package/dist/azure.js +1 -1
  17. package/dist/azure.mjs +1 -1
  18. package/dist/{batch-buffer-BTQdAXwC.js → batch-buffer-BLmVvJAZ.js} +2 -2
  19. package/dist/{batch-buffer-BTQdAXwC.js.map → batch-buffer-BLmVvJAZ.js.map} +1 -1
  20. package/dist/{batch-buffer-BJqzpfpT.mjs → batch-buffer-CM-lK_Qy.mjs} +2 -2
  21. package/dist/{batch-buffer-BJqzpfpT.mjs.map → batch-buffer-CM-lK_Qy.mjs.map} +1 -1
  22. package/dist/browser.d.mts +2 -0
  23. package/dist/browser.d.mts.map +1 -1
  24. package/dist/browser.d.ts +2 -0
  25. package/dist/browser.d.ts.map +1 -1
  26. package/dist/browser.js +18 -4
  27. package/dist/browser.js.map +1 -1
  28. package/dist/browser.mjs +18 -4
  29. package/dist/browser.mjs.map +1 -1
  30. package/dist/{builder-C6kKEVrU.mjs → builder-CA_dokb4.mjs} +108 -61
  31. package/dist/builder-CA_dokb4.mjs.map +1 -0
  32. package/dist/{builder-Up4YxX7l.js → builder-jMlVYaQa.js} +114 -67
  33. package/dist/builder-jMlVYaQa.js.map +1 -0
  34. package/dist/cloudwatch.d.mts +1 -1
  35. package/dist/cloudwatch.d.ts +1 -1
  36. package/dist/cloudwatch.js +1 -1
  37. package/dist/cloudwatch.mjs +1 -1
  38. package/dist/{cloudwatch.transport-Bl1qzdBx.mjs → cloudwatch.transport-Cr0fEpko.mjs} +5 -5
  39. package/dist/{cloudwatch.transport-Bl1qzdBx.mjs.map → cloudwatch.transport-Cr0fEpko.mjs.map} +1 -1
  40. package/dist/{cloudwatch.transport-CQyT6U91.d.ts → cloudwatch.transport-DdSjUWvu.d.ts} +2 -2
  41. package/dist/{cloudwatch.transport-CQyT6U91.d.ts.map → cloudwatch.transport-DdSjUWvu.d.ts.map} +1 -1
  42. package/dist/{cloudwatch.transport-BoCyxNKO.js → cloudwatch.transport-Lst1Bbmr.js} +5 -5
  43. package/dist/{cloudwatch.transport-BoCyxNKO.js.map → cloudwatch.transport-Lst1Bbmr.js.map} +1 -1
  44. package/dist/{cloudwatch.transport-CjVrI6S4.d.mts → cloudwatch.transport-_hS7Mcc5.d.mts} +2 -2
  45. package/dist/{cloudwatch.transport-CjVrI6S4.d.mts.map → cloudwatch.transport-_hS7Mcc5.d.mts.map} +1 -1
  46. package/dist/correlation.js +2 -2
  47. package/dist/correlation.mjs +2 -2
  48. package/dist/{entry-fields-CJbeaoBs.js → entry-fields-BSLkzw18.js} +3 -3
  49. package/dist/{entry-fields-CJbeaoBs.js.map → entry-fields-BSLkzw18.js.map} +1 -1
  50. package/dist/{entry-fields-D_aNnjg0.mjs → entry-fields-J1OBi24o.mjs} +2 -2
  51. package/dist/{entry-fields-D_aNnjg0.mjs.map → entry-fields-J1OBi24o.mjs.map} +1 -1
  52. package/dist/gcp.d.mts +1 -1
  53. package/dist/gcp.d.ts +1 -1
  54. package/dist/gcp.js +1 -1
  55. package/dist/gcp.mjs +1 -1
  56. package/dist/{gcp.transport-D_NHVZrw.js → gcp.transport-5-ZIjN8r.js} +5 -5
  57. package/dist/{gcp.transport-D_NHVZrw.js.map → gcp.transport-5-ZIjN8r.js.map} +1 -1
  58. package/dist/{gcp.transport-D9SdLPwP.d.mts → gcp.transport-C8VJiEM7.d.mts} +2 -2
  59. package/dist/{gcp.transport-D9SdLPwP.d.mts.map → gcp.transport-C8VJiEM7.d.mts.map} +1 -1
  60. package/dist/{gcp.transport-BCIvdFV-.d.ts → gcp.transport-Ct0BtKFo.d.ts} +2 -2
  61. package/dist/{gcp.transport-BCIvdFV-.d.ts.map → gcp.transport-Ct0BtKFo.d.ts.map} +1 -1
  62. package/dist/{gcp.transport-DOH4bpWM.mjs → gcp.transport-Cw3Qke85.mjs} +5 -5
  63. package/dist/{gcp.transport-DOH4bpWM.mjs.map → gcp.transport-Cw3Qke85.mjs.map} +1 -1
  64. package/dist/{index-BAkPHp5D.d.mts → index-B3ajtXJd.d.mts} +2 -2
  65. package/dist/{index-BAkPHp5D.d.mts.map → index-B3ajtXJd.d.mts.map} +1 -1
  66. package/dist/{index-e7LowmAu.d.ts → index-oqD3WNxf.d.ts} +2 -2
  67. package/dist/{index-e7LowmAu.d.ts.map → index-oqD3WNxf.d.ts.map} +1 -1
  68. package/dist/index.d.mts +8 -7
  69. package/dist/index.d.mts.map +1 -1
  70. package/dist/index.d.ts +8 -7
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +16 -14
  73. package/dist/index.js.map +1 -1
  74. package/dist/index.mjs +9 -8
  75. package/dist/index.mjs.map +1 -1
  76. package/dist/{logitron-logger-DVUdgmBY.d.ts → logitron-logger-Csn3e6Qu.d.ts} +2 -2
  77. package/dist/{logitron-logger-DVUdgmBY.d.ts.map → logitron-logger-Csn3e6Qu.d.ts.map} +1 -1
  78. package/dist/{logitron-logger-DoWmMjYB.d.mts → logitron-logger-fMOkXr8H.d.mts} +2 -2
  79. package/dist/{logitron-logger-DoWmMjYB.d.mts.map → logitron-logger-fMOkXr8H.d.mts.map} +1 -1
  80. package/dist/middleware.d.mts +1 -1
  81. package/dist/middleware.d.ts +1 -1
  82. package/dist/middleware.js +5 -4
  83. package/dist/middleware.js.map +1 -1
  84. package/dist/middleware.mjs +3 -2
  85. package/dist/middleware.mjs.map +1 -1
  86. package/dist/nest.d.mts +47 -15
  87. package/dist/nest.d.mts.map +1 -1
  88. package/dist/nest.d.ts +47 -15
  89. package/dist/nest.d.ts.map +1 -1
  90. package/dist/nest.js +169 -48
  91. package/dist/nest.js.map +1 -1
  92. package/dist/nest.mjs +166 -45
  93. package/dist/nest.mjs.map +1 -1
  94. package/dist/{otel-DH6-G6DR.js → otel-8ypFGG19.js} +319 -66
  95. package/dist/otel-8ypFGG19.js.map +1 -0
  96. package/dist/{otel-DAVxpArV.mjs → otel-b-s2QbY4.mjs} +319 -66
  97. package/dist/otel-b-s2QbY4.mjs.map +1 -0
  98. package/dist/own-property-BWkibepN.js +40 -0
  99. package/dist/own-property-BWkibepN.js.map +1 -0
  100. package/dist/own-property-CjFw9qwZ.mjs +29 -0
  101. package/dist/own-property-CjFw9qwZ.mjs.map +1 -0
  102. package/dist/{safe-stringify-pZOnzGRJ.mjs → safe-stringify-B5p5ktFe.mjs} +2 -2
  103. package/dist/{safe-stringify-pZOnzGRJ.mjs.map → safe-stringify-B5p5ktFe.mjs.map} +1 -1
  104. package/dist/{safe-stringify-CJisLyZ3.js → safe-stringify-J3sh-7YM.js} +5 -5
  105. package/dist/{safe-stringify-CJisLyZ3.js.map → safe-stringify-J3sh-7YM.js.map} +1 -1
  106. package/dist/{search-Crf2IEoA.d.mts → search-B-hJe2N-.d.mts} +7 -3
  107. package/dist/{search-Crf2IEoA.d.mts.map → search-B-hJe2N-.d.mts.map} +1 -1
  108. package/dist/{search-B4eEzrhM.d.ts → search-BlKBLm5D.d.ts} +7 -3
  109. package/dist/{search-B4eEzrhM.d.ts.map → search-BlKBLm5D.d.ts.map} +1 -1
  110. package/dist/{search-CjYl-mo5.mjs → search-CTR4XNHq.mjs} +52 -14
  111. package/dist/search-CTR4XNHq.mjs.map +1 -0
  112. package/dist/{search-CJw_xoQl.js → search-_qx4YzRP.js} +52 -14
  113. package/dist/search-_qx4YzRP.js.map +1 -0
  114. package/dist/search.d.mts +1 -1
  115. package/dist/search.d.ts +1 -1
  116. package/dist/search.js +1 -1
  117. package/dist/search.mjs +1 -1
  118. package/dist/{secret-config-6hdODxBb.js → secret-config--cVTOWwp.js} +6 -5
  119. package/dist/{secret-config-6hdODxBb.js.map → secret-config--cVTOWwp.js.map} +1 -1
  120. package/dist/{secret-config-D1F4MW69.mjs → secret-config-GKmb15Me.mjs} +3 -2
  121. package/dist/{secret-config-D1F4MW69.mjs.map → secret-config-GKmb15Me.mjs.map} +1 -1
  122. package/dist/{sensitive-names-wv27qBQC.mjs → sensitive-names-BiBM6R1X.mjs} +2 -28
  123. package/dist/sensitive-names-BiBM6R1X.mjs.map +1 -0
  124. package/dist/{sensitive-names-CNgHaqv9.js → sensitive-names-NiKIRhp5.js} +1 -39
  125. package/dist/sensitive-names-NiKIRhp5.js.map +1 -0
  126. package/dist/{slack.transport-C6E0l4kw.d.ts → slack.transport-5OPL7H3u.d.mts} +76 -3
  127. package/dist/slack.transport-5OPL7H3u.d.mts.map +1 -0
  128. package/dist/{slack.transport-BDyENuR0.d.mts → slack.transport-BFpBD_Ri.d.ts} +76 -3
  129. package/dist/slack.transport-BFpBD_Ri.d.ts.map +1 -0
  130. package/dist/{slack.transport-CEYBVzUj.js → slack.transport-Cpx5fKga.js} +231 -8
  131. package/dist/slack.transport-Cpx5fKga.js.map +1 -0
  132. package/dist/{slack.transport-YvaLJxNv.mjs → slack.transport-Qwj9WkrJ.mjs} +226 -9
  133. package/dist/slack.transport-Qwj9WkrJ.mjs.map +1 -0
  134. package/dist/testing.d.mts +1 -1
  135. package/dist/testing.d.ts +1 -1
  136. package/dist/{transport.types-CzJq4IrF.d.ts → transport.types-B1ejJJP6.d.mts} +6 -1
  137. package/dist/transport.types-B1ejJJP6.d.mts.map +1 -0
  138. package/dist/{transport.types-CzJq4IrF.d.mts → transport.types-B1ejJJP6.d.ts} +6 -1
  139. package/dist/transport.types-B1ejJJP6.d.ts.map +1 -0
  140. package/dist/transports.d.mts +61 -11
  141. package/dist/transports.d.mts.map +1 -1
  142. package/dist/transports.d.ts +61 -11
  143. package/dist/transports.d.ts.map +1 -1
  144. package/dist/transports.js +7 -6
  145. package/dist/transports.mjs +7 -7
  146. package/dist/worker-entry.js +91 -11
  147. package/dist/worker.d.mts +1 -1
  148. package/dist/worker.d.ts +1 -1
  149. package/dist/worker.js +1 -1
  150. package/dist/worker.mjs +1 -1
  151. package/dist/{worker.transport-B9mCQSM1.d.ts → worker.transport-B7olL1Uh.d.ts} +12 -2
  152. package/dist/worker.transport-B7olL1Uh.d.ts.map +1 -0
  153. package/dist/{worker.transport-DgK_ZXlB.mjs → worker.transport-BHnWDXPH.mjs} +40 -2
  154. package/dist/worker.transport-BHnWDXPH.mjs.map +1 -0
  155. package/dist/{worker.transport-CwNpH98o.js → worker.transport-C7jNGhev.js} +40 -2
  156. package/dist/worker.transport-C7jNGhev.js.map +1 -0
  157. package/dist/{worker.transport-Bl8lFRck.d.mts → worker.transport-DnU0_9Bd.d.mts} +12 -2
  158. package/dist/worker.transport-DnU0_9Bd.d.mts.map +1 -0
  159. package/package.json +1 -1
  160. package/dist/builder-C6kKEVrU.mjs.map +0 -1
  161. package/dist/builder-Up4YxX7l.js.map +0 -1
  162. package/dist/otel-DAVxpArV.mjs.map +0 -1
  163. package/dist/otel-DH6-G6DR.js.map +0 -1
  164. package/dist/search-CJw_xoQl.js.map +0 -1
  165. package/dist/search-CjYl-mo5.mjs.map +0 -1
  166. package/dist/sensitive-names-CNgHaqv9.js.map +0 -1
  167. package/dist/sensitive-names-wv27qBQC.mjs.map +0 -1
  168. package/dist/slack.transport-BDyENuR0.d.mts.map +0 -1
  169. package/dist/slack.transport-C6E0l4kw.d.ts.map +0 -1
  170. package/dist/slack.transport-CEYBVzUj.js.map +0 -1
  171. package/dist/slack.transport-YvaLJxNv.mjs.map +0 -1
  172. package/dist/transport.types-CzJq4IrF.d.mts.map +0 -1
  173. package/dist/transport.types-CzJq4IrF.d.ts.map +0 -1
  174. package/dist/worker.transport-B9mCQSM1.d.ts.map +0 -1
  175. package/dist/worker.transport-Bl8lFRck.d.mts.map +0 -1
  176. package/dist/worker.transport-CwNpH98o.js.map +0 -1
  177. package/dist/worker.transport-DgK_ZXlB.mjs.map +0 -1
@@ -1,8 +1,9 @@
1
- const require_secret_config = require("./secret-config-6hdODxBb.js");
1
+ const require_secret_config = require("./secret-config--cVTOWwp.js");
2
2
  const require_internal_log = require("./internal-log-DwqTjhpb.js");
3
+ const require_safe_stringify = require("./safe-stringify-J3sh-7YM.js");
3
4
  const require_csv_utils = require("./csv.utils-CbVHY1pd.js");
4
- const require_safe_stringify = require("./safe-stringify-CJisLyZ3.js");
5
- const require_entry_fields = require("./entry-fields-CJbeaoBs.js");
5
+ const require_entry_fields = require("./entry-fields-BSLkzw18.js");
6
+ const require_batch_buffer = require("./batch-buffer-BLmVvJAZ.js");
6
7
  let node_events = require("node:events");
7
8
  let node_util = require("node:util");
8
9
  let node_zlib = require("node:zlib");
@@ -250,6 +251,7 @@ function isDataError(type, error) {
250
251
  return false;
251
252
  }
252
253
  /** A write that stored part of a batch: only `remaining` still needs to be written. */
254
+ var DatabaseUnavailableError = class extends Error {};
253
255
  var PartialWriteError = class extends Error {
254
256
  remaining;
255
257
  constructor(message, remaining, cause) {
@@ -297,6 +299,8 @@ var DatabaseTransport = class {
297
299
  connection;
298
300
  isConnected = false;
299
301
  connectionPromise;
302
+ connectFailures = 0;
303
+ nextConnectAt = 0;
300
304
  cap;
301
305
  constructor(config) {
302
306
  this.config = config;
@@ -318,9 +322,12 @@ var DatabaseTransport = class {
318
322
  ];
319
323
  }
320
324
  async write(entry) {
321
- if (!this.isConnected) await this.connect();
322
325
  this.addToBatch(entry);
323
- if (this.batch.length >= this.batchSize) await this.flush();
326
+ if (this.batch.length >= this.batchSize) try {
327
+ await this.flush();
328
+ } catch (error) {
329
+ if (!(error instanceof DatabaseUnavailableError)) throw error;
330
+ }
324
331
  }
325
332
  addToBatch(entry) {
326
333
  this.batch.push(entry);
@@ -345,6 +352,7 @@ var DatabaseTransport = class {
345
352
  */
346
353
  async drain() {
347
354
  while (this.batch.length > 0) {
355
+ await this.ensureConnected();
348
356
  const entries = this.batch.splice(0, this.batchSize);
349
357
  try {
350
358
  await this.writeEntries(entries);
@@ -442,6 +450,38 @@ var DatabaseTransport = class {
442
450
  return false;
443
451
  }
444
452
  }
453
+ async ensureConnected() {
454
+ if (this.isConnected) return;
455
+ const wait = this.nextConnectAt - Date.now();
456
+ if (wait > 0) throw new DatabaseUnavailableError(`Database unavailable; next connect attempt in ${wait}ms`);
457
+ try {
458
+ await this.connect();
459
+ this.connectFailures = 0;
460
+ } catch (error) {
461
+ this.connectFailures += 1;
462
+ this.nextConnectAt = Date.now() + Math.min(3e4, 1e3 * 2 ** (this.connectFailures - 1));
463
+ require_internal_log.internalError("Database connection error", error);
464
+ throw new DatabaseUnavailableError("Database unavailable", { cause: error });
465
+ }
466
+ }
467
+ /**
468
+ * The driver reported the connection gone (idle timeout, server restart,
469
+ * network drop). Forget it so the next flush reconnects; without an 'error'
470
+ * listener the driver's emitter would crash the process.
471
+ */
472
+ onConnectionLost(connection, error) {
473
+ if (this.connection !== connection) return;
474
+ if (error) require_internal_log.internalError("Database connection lost", error);
475
+ this.isConnected = false;
476
+ this.connectionPromise = void 0;
477
+ this.connection = void 0;
478
+ }
479
+ watchConnection(connection) {
480
+ var _connection$on, _connection$on2;
481
+ const lost = (error) => this.onConnectionLost(connection, error);
482
+ (_connection$on = connection.on) === null || _connection$on === void 0 || _connection$on.call(connection, "error", lost);
483
+ (_connection$on2 = connection.on) === null || _connection$on2 === void 0 || _connection$on2.call(connection, "end", () => lost());
484
+ }
445
485
  async connect() {
446
486
  if (this.connectionPromise) return this.connectionPromise;
447
487
  this.connectionPromise = this.establishConnection().catch((error) => {
@@ -478,6 +518,7 @@ var DatabaseTransport = class {
478
518
  });
479
519
  const connectionString = this.config.connectionString || `mongodb://${this.config.host}:${this.config.port}/${this.config.database}`;
480
520
  this.connection = new MongoClient(connectionString);
521
+ this.watchConnection(this.connection);
481
522
  await this.connection.connect();
482
523
  await this.connection.db(this.config.database).admin().ping();
483
524
  } catch (error) {
@@ -499,6 +540,7 @@ var DatabaseTransport = class {
499
540
  if (this.config.password) config.password = this.config.password;
500
541
  if (this.config.ssl) config.ssl = typeof this.config.ssl === "boolean" ? {} : this.config.ssl;
501
542
  this.connection = new Client(config);
543
+ this.watchConnection(this.connection);
502
544
  await this.connection.connect();
503
545
  await this.createPostgreSQLTable();
504
546
  } catch (error) {
@@ -519,6 +561,7 @@ var DatabaseTransport = class {
519
561
  if (this.config.password) config.password = this.config.password;
520
562
  if (this.config.ssl) config.ssl = typeof this.config.ssl === "boolean" ? {} : this.config.ssl;
521
563
  this.connection = await mysql.createConnection(config);
564
+ this.watchConnection(this.connection);
522
565
  await this.createMySQLTable();
523
566
  } catch (error) {
524
567
  throw new Error(`MySQL connection failed: ${error}`, { cause: error });
@@ -741,6 +784,7 @@ var DatabaseTransport = class {
741
784
  this.flushTimer = void 0;
742
785
  }
743
786
  const MAX_CLOSE_FLUSH_ATTEMPTS = 3;
787
+ this.nextConnectAt = 0;
744
788
  if (this.flushPromise) await this.flushPromise.catch(() => {});
745
789
  for (let attempt = 0; attempt < MAX_CLOSE_FLUSH_ATTEMPTS && this.batch.length > 0; attempt += 1) try {
746
790
  await this.flush();
@@ -749,17 +793,19 @@ var DatabaseTransport = class {
749
793
  }
750
794
  if (this.batch.length > 0) require_internal_log.internalError(`Database transport closing with ${this.batch.length} unflushed log entr${this.batch.length === 1 ? "y" : "ies"} after ${MAX_CLOSE_FLUSH_ATTEMPTS} attempts`);
751
795
  this.cap.report(0);
752
- if (this.connection) switch (this.config.type) {
796
+ const connection = this.connection;
797
+ this.connection = void 0;
798
+ if (connection) switch (this.config.type) {
753
799
  case "mongodb":
754
- await this.connection.close();
800
+ await connection.close();
755
801
  break;
756
802
  case "postgresql":
757
- await this.connection.end();
803
+ await connection.end();
758
804
  break;
759
805
  case "mysql":
760
- await this.connection.end();
806
+ await connection.end();
761
807
  break;
762
- case "sqlite": await this.connection.close();
808
+ case "sqlite": await connection.close();
763
809
  }
764
810
  this.isConnected = false;
765
811
  }
@@ -834,6 +880,9 @@ var AnalyticsTransport = class {
834
880
  /** Set on the first write. Subclass fields don't exist yet while the base constructor runs. */
835
881
  initPromise;
836
882
  cap;
883
+ /** Consecutive failed drains; drives the backoff that stops a failing provider being re-sent every Nth log. */
884
+ failures = 0;
885
+ retryAt = 0;
837
886
  constructor(name, config) {
838
887
  this.name = name;
839
888
  this.config = {
@@ -866,12 +915,13 @@ var AnalyticsTransport = class {
866
915
  addToBatch(entry) {
867
916
  this.batch.push(entry);
868
917
  this.cap.enforce(this.batch);
869
- if (this.batch.length >= (this.config.batchSize || 50)) this.flush().catch((err) => require_internal_log.internalError(`${this.name} batch flush failed`, err));
870
- else if (!this.batchTimer && this.config.flushInterval) {
918
+ const backoff = this.retryAt - Date.now();
919
+ if (this.batch.length >= (this.config.batchSize || 50) && backoff <= 0) this.flush().catch((err) => require_internal_log.internalError(`${this.name} batch flush failed`, err));
920
+ else if (!this.batchTimer && (this.config.flushInterval || backoff > 0)) {
871
921
  var _this$batchTimer$unre, _this$batchTimer;
872
922
  this.batchTimer = setTimeout(() => {
873
923
  this.flush().catch((err) => require_internal_log.internalError(`${this.name} interval flush failed`, err));
874
- }, this.config.flushInterval);
924
+ }, Math.max(this.config.flushInterval || 0, backoff));
875
925
  (_this$batchTimer$unre = (_this$batchTimer = this.batchTimer).unref) === null || _this$batchTimer$unre === void 0 || _this$batchTimer$unre.call(_this$batchTimer);
876
926
  }
877
927
  }
@@ -898,7 +948,11 @@ var AnalyticsTransport = class {
898
948
  this.batch = [];
899
949
  try {
900
950
  await this.sendBatch(entriesToSend);
951
+ this.failures = 0;
952
+ this.retryAt = 0;
901
953
  } catch (error) {
954
+ this.failures += 1;
955
+ this.retryAt = Date.now() + Math.min(6e4, 1e3 * 2 ** (this.failures - 1));
902
956
  require_secret_config.scrubError(error, this.secretValues());
903
957
  require_internal_log.internalError(`Analytics transport ${this.name} flush failed`, error);
904
958
  this.batch.unshift(...error instanceof PartialBatchError ? error.unsent : entriesToSend);
@@ -961,6 +1015,28 @@ var AnalyticsTransport = class {
961
1015
  await this.ensureReady();
962
1016
  }
963
1017
  };
1018
+ // src/transports/fetch-timeout.ts
1019
+ /**
1020
+ * fetch() with a hard deadline, so an endpoint that accepts the connection and
1021
+ * never answers cannot hang a flush (and with it close()) forever. Uses an
1022
+ * AbortController rather than AbortSignal.timeout(), which needs Node 17.3+
1023
+ * while `engines` allows 16; the timer is unref'd so it never holds the process.
1024
+ */
1025
+ async function fetchWithTimeout(url, init, timeoutMs = require_batch_buffer.DEFAULT_REQUEST_TIMEOUT_MS) {
1026
+ var _timer$unref;
1027
+ const controller = new AbortController();
1028
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
1029
+ (_timer$unref = timer.unref) === null || _timer$unref === void 0 || _timer$unref.call(timer);
1030
+ try {
1031
+ return await fetch(url, {
1032
+ ...init,
1033
+ signal: controller.signal
1034
+ });
1035
+ } catch (error) {
1036
+ if (controller.signal.aborted) throw new Error(`Request timed out after ${timeoutMs}ms`, { cause: error });
1037
+ throw error;
1038
+ }
1039
+ }
964
1040
  // src/transports/datadog.transport.ts
965
1041
  const gzipAsync = (0, node_util.promisify)(node_zlib.gzip);
966
1042
  const MAX_LOGS_PER_REQUEST = 1e3;
@@ -1200,7 +1276,7 @@ var DataDogTransport = class extends AnalyticsTransport {
1200
1276
  const url = `${this.logsUrl}${endpoint}`;
1201
1277
  try {
1202
1278
  const compress = this.datadogConfig.compress === true;
1203
- const response = await fetch(url, {
1279
+ const response = await fetchWithTimeout(url, {
1204
1280
  method: "POST",
1205
1281
  headers: {
1206
1282
  "Content-Type": "application/json",
@@ -1217,7 +1293,7 @@ var DataDogTransport = class extends AnalyticsTransport {
1217
1293
  async makeMetricsRequest(endpoint, data) {
1218
1294
  const url = `${this.metricsUrl}${endpoint}`;
1219
1295
  try {
1220
- const response = await fetch(url, {
1296
+ const response = await fetchWithTimeout(url, {
1221
1297
  method: "POST",
1222
1298
  headers: {
1223
1299
  "Content-Type": "application/json",
@@ -1262,7 +1338,7 @@ var DataDogTransport = class extends AnalyticsTransport {
1262
1338
  };
1263
1339
  const url = `${this.baseUrl}/api/v1/events`;
1264
1340
  try {
1265
- const response = await fetch(url, {
1341
+ const response = await fetchWithTimeout(url, {
1266
1342
  method: "POST",
1267
1343
  headers: {
1268
1344
  "Content-Type": "application/json",
@@ -1374,6 +1450,8 @@ var FileTransport = class {
1374
1450
  lastDropWarning = 0;
1375
1451
  /** Gzip and pruning of rotated files run off the write path, one at a time. */
1376
1452
  housekeeping = Promise.resolve();
1453
+ exitListenerAttached = false;
1454
+ onExit = () => this.flushSyncOnExit();
1377
1455
  constructor(config) {
1378
1456
  this.config = {
1379
1457
  format: "json",
@@ -1462,6 +1540,7 @@ var FileTransport = class {
1462
1540
  await done;
1463
1541
  }
1464
1542
  enqueue(entry) {
1543
+ this.attachExitListener();
1465
1544
  if (this.queueFull()) {
1466
1545
  if (this.queuePolicy === "drop-oldest" && this.batch.length > 0) {
1467
1546
  this.batch.shift();
@@ -1473,6 +1552,30 @@ var FileTransport = class {
1473
1552
  this.batch.push(entry);
1474
1553
  this.enqueued += 1;
1475
1554
  }
1555
+ attachExitListener() {
1556
+ if (this.exitListenerAttached) return;
1557
+ this.exitListenerAttached = true;
1558
+ process.on("exit", this.onExit);
1559
+ }
1560
+ detachExitListener() {
1561
+ if (!this.exitListenerAttached) return;
1562
+ this.exitListenerAttached = false;
1563
+ process.removeListener("exit", this.onExit);
1564
+ }
1565
+ /**
1566
+ * Last chance on process exit: async writes cannot finish, so whatever is still
1567
+ * batched is appended synchronously to the current file.
1568
+ */
1569
+ flushSyncOnExit() {
1570
+ if (this.batch.length === 0) return;
1571
+ const pending = this.batch;
1572
+ this.batch = [];
1573
+ this.enqueued -= pending.length;
1574
+ try {
1575
+ const content = pending.map((entry) => this.formatEntry(entry)).join("\n") + "\n";
1576
+ node_fs.appendFileSync(this.currentFilePath, content, { mode: this.fileMode });
1577
+ } catch {}
1578
+ }
1476
1579
  queueFull() {
1477
1580
  return this.batch.length + this.inFlight >= this.maxQueue;
1478
1581
  }
@@ -1557,7 +1660,11 @@ var FileTransport = class {
1557
1660
  case "json": return require_safe_stringify.stringifyForLog(require_entry_fields.mergeCoreFields({
1558
1661
  timestamp: entry.timestamp.toISOString(),
1559
1662
  level: entry.level,
1560
- message: entry.message
1663
+ message: entry.message,
1664
+ context: entry.context,
1665
+ traceId: entry.traceId,
1666
+ appName: entry.appName,
1667
+ environment: entry.environment
1561
1668
  }, entry.data));
1562
1669
  case "csv": return [
1563
1670
  entry.timestamp.toISOString(),
@@ -1579,9 +1686,12 @@ var FileTransport = class {
1579
1686
  this.batchTimer = void 0;
1580
1687
  }
1581
1688
  this.startDrain();
1582
- } else if (!this.batchTimer && this.config.flushInterval) this.batchTimer = setTimeout(() => {
1583
- this.flush().catch((err) => require_internal_log.internalError("FileTransport interval flush failed", err));
1584
- }, this.config.flushInterval);
1689
+ } else if (!this.batchTimer && this.config.flushInterval) {
1690
+ this.batchTimer = setTimeout(() => {
1691
+ this.flush().catch((err) => require_internal_log.internalError("FileTransport interval flush failed", err));
1692
+ }, this.config.flushInterval);
1693
+ this.batchTimer.unref();
1694
+ }
1585
1695
  }
1586
1696
  /** Only ever called from drain(), so writes and rotations never overlap. */
1587
1697
  async writeBatch(entries) {
@@ -1747,6 +1857,7 @@ var FileTransport = class {
1747
1857
  this.batchTimer = void 0;
1748
1858
  }
1749
1859
  await this.flush();
1860
+ this.detachExitListener();
1750
1861
  await this.housekeeping;
1751
1862
  this.reportDropped(0);
1752
1863
  }
@@ -1870,7 +1981,7 @@ var GoogleAnalyticsTransport = class extends AnalyticsTransport {
1870
1981
  api_secret: this.gaConfig.apiSecret
1871
1982
  });
1872
1983
  try {
1873
- const response = await fetch(`${url}?${params}`, {
1984
+ const response = await fetchWithTimeout(`${url}?${params}`, {
1874
1985
  method: "POST",
1875
1986
  headers: { "Content-Type": "application/json" },
1876
1987
  body: require_safe_stringify.stringifyForLog(payload)
@@ -2088,7 +2199,7 @@ var MixpanelTransport = class extends AnalyticsTransport {
2088
2199
  async makeRequest(endpoint, data) {
2089
2200
  const url = `${this.mixpanelConfig.endpoint || this.baseUrl}${endpoint}`;
2090
2201
  try {
2091
- const response = await fetch(url, {
2202
+ const response = await fetchWithTimeout(url, {
2092
2203
  method: "POST",
2093
2204
  headers: {
2094
2205
  "Content-Type": "application/json",
@@ -2257,7 +2368,7 @@ var SegmentTransport = class extends AnalyticsTransport {
2257
2368
  const url = `${this.baseUrl}${endpoint}`;
2258
2369
  const auth = Buffer.from(`${this.segmentConfig.writeKey}:`).toString("base64");
2259
2370
  try {
2260
- const response = await fetch(url, {
2371
+ const response = await fetchWithTimeout(url, {
2261
2372
  method: "POST",
2262
2373
  headers: {
2263
2374
  "Content-Type": "application/json",
@@ -2427,15 +2538,16 @@ var SegmentTransport = class extends AnalyticsTransport {
2427
2538
  }
2428
2539
  };
2429
2540
  // src/transports/transport.manager.ts
2430
- function _sleep(ms) {
2431
- return new Promise((resolve) => setTimeout(resolve, ms));
2432
- }
2541
+ const DEFAULT_MAX_PENDING_RETRIES = 1e3;
2542
+ const RETRY_WARN_INTERVAL_MS = 5e3;
2433
2543
  var TransportManager = class extends node_events.EventEmitter {
2434
2544
  transports = /* @__PURE__ */ new Map();
2435
2545
  metrics = /* @__PURE__ */ new Map();
2436
2546
  isShuttingDown = false;
2437
2547
  transportLevelPreferences = /* @__PURE__ */ new Map();
2438
2548
  warnedPromptDeprecated = false;
2549
+ closePromise;
2550
+ retryStates = /* @__PURE__ */ new Map();
2439
2551
  levelValues;
2440
2552
  /**
2441
2553
  * @param config Transport configuration.
@@ -2516,8 +2628,9 @@ var TransportManager = class extends node_events.EventEmitter {
2516
2628
  if (!transport) return false;
2517
2629
  this.transports.delete(id);
2518
2630
  this.metrics.delete(id);
2631
+ this.drainRetries(id, transport);
2519
2632
  if (transport.close) transport.close().catch((error) => {
2520
- this.emit("error", error, id);
2633
+ require_internal_log.internalError(`Transport "${id}" failed to close`, error);
2521
2634
  });
2522
2635
  this.emit("transport:removed", id);
2523
2636
  return true;
@@ -2533,7 +2646,10 @@ var TransportManager = class extends node_events.EventEmitter {
2533
2646
  * sync path.
2534
2647
  */
2535
2648
  write(entry) {
2536
- if (this.isShuttingDown) return;
2649
+ if (this.isShuttingDown) {
2650
+ this.writeAfterClose(entry);
2651
+ return;
2652
+ }
2537
2653
  const transportEntry = {
2538
2654
  timestamp: typeof entry.timestamp === "string" ? new Date(entry.timestamp) : entry.timestamp,
2539
2655
  level: entry.level,
@@ -2571,6 +2687,27 @@ var TransportManager = class extends node_events.EventEmitter {
2571
2687
  }
2572
2688
  });
2573
2689
  }
2690
+ /**
2691
+ * Transports are gone once closed, but the app may still log (its own signal
2692
+ * handler, a late async callback). Emit such lines on stdout/stderr rather
2693
+ * than losing them silently.
2694
+ */
2695
+ writeAfterClose(entry) {
2696
+ const line = `${require_safe_stringify.stringifyForLog({
2697
+ timestamp: entry.timestamp,
2698
+ level: entry.level,
2699
+ message: entry.message,
2700
+ appName: entry.appName,
2701
+ context: entry.context,
2702
+ traceId: entry.traceId,
2703
+ ...entry.payload
2704
+ })}\n`;
2705
+ const level = String(entry.level).toLowerCase();
2706
+ const stream = level === "error" || level === "warn" ? "stderr" : "stdout";
2707
+ try {
2708
+ process[stream].write(line);
2709
+ } catch {}
2710
+ }
2574
2711
  writeToTransport(id, transport, entry) {
2575
2712
  const startTime = Date.now();
2576
2713
  const metrics = this.metrics.get(id);
@@ -2597,43 +2734,86 @@ var TransportManager = class extends node_events.EventEmitter {
2597
2734
  onSuccess();
2598
2735
  return;
2599
2736
  }
2600
- return this._writeWithRetry(transport, entry).then(onSuccess, onError);
2737
+ return this._writeWithRetry(id, transport, entry).then((written) => {
2738
+ if (written) onSuccess();
2739
+ }, onError);
2601
2740
  }
2602
2741
  /**
2603
2742
  * Feature 9: Multi-transport retry + failover.
2604
2743
  *
2605
- * Attempts `transport.write()` up to `retry.maxRetries + 1` times with the
2606
- * configured backoff strategy. If all attempts fail and a fallback transport
2607
- * is configured, routes the entry there instead.
2744
+ * The first attempt is awaited by the caller. If it fails, the entry moves to
2745
+ * a bounded per-transport retry queue and the caller's promise resolves, so a
2746
+ * down transport never holds a log call across backoff. The queue retries up
2747
+ * to `retry.maxRetries` more times with the configured backoff, then routes
2748
+ * the entry to the fallback transport (if any) and calls `onExhausted`.
2749
+ * Returns true when the first attempt succeeded.
2608
2750
  */
2609
- async _writeWithRetry(transport, entry) {
2610
- const retryCfg = transport.retry;
2611
- if (!retryCfg || !retryCfg.maxRetries) {
2751
+ async _writeWithRetry(id, transport, entry) {
2752
+ try {
2612
2753
  await transport.write(entry);
2613
- return;
2754
+ return true;
2755
+ } catch (err) {
2756
+ this.enqueueRetry(id, transport, entry, err instanceof Error ? err : new Error(String(err)));
2757
+ return false;
2614
2758
  }
2615
- const { maxRetries, backoff = "exponential", delay: baseDelay = 500, maxDelay = 3e4, fallback, onExhausted } = retryCfg;
2616
- let lastError = /* @__PURE__ */ new Error("Unknown transport error");
2617
- for (let attempt = 0; attempt <= maxRetries; attempt++) try {
2618
- await transport.write(entry);
2759
+ }
2760
+ enqueueRetry(id, transport, entry, error) {
2761
+ let state = this.retryStates.get(id);
2762
+ if (!state) {
2763
+ state = {
2764
+ queue: [],
2765
+ timer: void 0,
2766
+ running: false,
2767
+ dropped: 0,
2768
+ lastWarn: 0
2769
+ };
2770
+ this.retryStates.set(id, state);
2771
+ }
2772
+ const maxPending = transport.retry.maxPending ?? DEFAULT_MAX_PENDING_RETRIES;
2773
+ while (state.queue.length >= maxPending) {
2774
+ state.queue.shift();
2775
+ state.dropped++;
2776
+ }
2777
+ this.warnDropped(id, state);
2778
+ this.scheduleRetry(id, transport, state, {
2779
+ entry,
2780
+ attempt: 0,
2781
+ due: 0
2782
+ }, error);
2783
+ this.pumpRetries(id, transport, state);
2784
+ }
2785
+ warnDropped(id, state) {
2786
+ const now = Date.now();
2787
+ if (state.dropped > 0 && now - state.lastWarn >= RETRY_WARN_INTERVAL_MS) {
2788
+ require_internal_log.internalWarn(`TransportManager: retry queue for "${id}" is full; dropped ${state.dropped} oldest log entr${state.dropped === 1 ? "y" : "ies"}`);
2789
+ state.dropped = 0;
2790
+ state.lastWarn = now;
2791
+ }
2792
+ }
2793
+ /** Queues `item` for its next attempt, or finishes it when retries ran out. */
2794
+ scheduleRetry(id, transport, state, item, error) {
2795
+ const { maxRetries = 0, backoff = "exponential", delay = 500, maxDelay = 3e4 } = transport.retry;
2796
+ if (item.attempt >= maxRetries) {
2797
+ this.exhaust(id, transport, item.entry, error);
2619
2798
  return;
2620
- } catch (err) {
2621
- lastError = err instanceof Error ? err : new Error(String(err));
2622
- if (attempt < maxRetries) {
2623
- let wait;
2624
- switch (backoff) {
2625
- case "fixed":
2626
- wait = baseDelay;
2627
- break;
2628
- case "linear":
2629
- wait = baseDelay * (attempt + 1);
2630
- break;
2631
- default: wait = Math.min(baseDelay * Math.pow(2, attempt), maxDelay);
2632
- }
2633
- this.emit("transport:retry", transport.name, attempt + 1, maxRetries, wait);
2634
- await _sleep(wait);
2635
- }
2636
2799
  }
2800
+ let wait;
2801
+ switch (backoff) {
2802
+ case "fixed":
2803
+ wait = delay;
2804
+ break;
2805
+ case "linear":
2806
+ wait = delay * (item.attempt + 1);
2807
+ break;
2808
+ default: wait = Math.min(delay * Math.pow(2, item.attempt), maxDelay);
2809
+ }
2810
+ item.attempt++;
2811
+ item.due = Date.now() + wait;
2812
+ state.queue.push(item);
2813
+ this.emit("transport:retry", transport.name, item.attempt, maxRetries, wait);
2814
+ }
2815
+ async exhaust(id, transport, entry, error) {
2816
+ const { fallback, onExhausted } = transport.retry;
2637
2817
  if (fallback) {
2638
2818
  this.emit("transport:fallback", transport.name, fallback.name);
2639
2819
  try {
@@ -2641,8 +2821,65 @@ var TransportManager = class extends node_events.EventEmitter {
2641
2821
  return;
2642
2822
  } catch {}
2643
2823
  }
2644
- onExhausted === null || onExhausted === void 0 || onExhausted(lastError, entry);
2645
- throw lastError;
2824
+ const metrics = this.metrics.get(id);
2825
+ if (metrics) metrics.errors++;
2826
+ try {
2827
+ onExhausted === null || onExhausted === void 0 || onExhausted(error, entry);
2828
+ } catch (hookError) {
2829
+ require_internal_log.internalWarn(`TransportManager: onExhausted for "${id}" threw: ${String(hookError)}`);
2830
+ }
2831
+ if (this.listenerCount("error") > 0) this.emit("error", error, id);
2832
+ }
2833
+ /** One serial worker per transport: the earliest-due entry is retried first. */
2834
+ pumpRetries(id, transport, state) {
2835
+ var _state$timer$unref, _state$timer;
2836
+ if (state.running || state.timer || state.queue.length === 0) return;
2837
+ let next = 0;
2838
+ for (let i = 1; i < state.queue.length; i++) if (state.queue[i].due < state.queue[next].due) next = i;
2839
+ const wait = Math.max(0, state.queue[next].due - Date.now());
2840
+ state.timer = setTimeout(() => {
2841
+ state.timer = void 0;
2842
+ this.runRetry(id, transport, state);
2843
+ }, wait);
2844
+ (_state$timer$unref = (_state$timer = state.timer).unref) === null || _state$timer$unref === void 0 || _state$timer$unref.call(_state$timer);
2845
+ }
2846
+ async runRetry(id, transport, state) {
2847
+ if (state.queue.length === 0) return;
2848
+ let next = 0;
2849
+ for (let i = 1; i < state.queue.length; i++) if (state.queue[i].due < state.queue[next].due) next = i;
2850
+ const [item] = state.queue.splice(next, 1);
2851
+ if (!item) return;
2852
+ state.running = true;
2853
+ try {
2854
+ await transport.write(item.entry);
2855
+ const metrics = this.metrics.get(id);
2856
+ if (metrics) {
2857
+ metrics.logsWritten++;
2858
+ metrics.lastWrite = /* @__PURE__ */ new Date();
2859
+ }
2860
+ this.emit("log", item.entry);
2861
+ } catch (err) {
2862
+ this.scheduleRetry(id, transport, state, item, err instanceof Error ? err : new Error(String(err)));
2863
+ } finally {
2864
+ state.running = false;
2865
+ }
2866
+ if (!this.isShuttingDown) this.pumpRetries(id, transport, state);
2867
+ }
2868
+ /** Stops a transport's retry worker and hands what is still queued to its fallback. */
2869
+ async drainRetries(id, transport) {
2870
+ var _transport$retry;
2871
+ const state = this.retryStates.get(id);
2872
+ if (!state) return;
2873
+ this.retryStates.delete(id);
2874
+ if (state.timer) clearTimeout(state.timer);
2875
+ state.timer = void 0;
2876
+ const fallback = transport === null || transport === void 0 || (_transport$retry = transport.retry) === null || _transport$retry === void 0 ? void 0 : _transport$retry.fallback;
2877
+ if (state.queue.length === 0) return;
2878
+ if (!fallback) {
2879
+ require_internal_log.internalWarn(`TransportManager: "${id}" closed with ${state.queue.length} log entr${state.queue.length === 1 ? "y" : "ies"} still awaiting retry`);
2880
+ return;
2881
+ }
2882
+ await Promise.allSettled(state.queue.map((item) => fallback.write(item.entry)));
2646
2883
  }
2647
2884
  shouldTransportHandle(transport, level, transportId) {
2648
2885
  if (transportId && this.transportLevelPreferences.has(transportId)) return this.transportLevelPreferences.get(transportId).includes(level.toLowerCase());
@@ -2661,19 +2898,35 @@ var TransportManager = class extends node_events.EventEmitter {
2661
2898
  if (readyPromises.length > 0) await Promise.all(readyPromises);
2662
2899
  }
2663
2900
  async flush() {
2901
+ await this.flushTransports(false);
2902
+ }
2903
+ /**
2904
+ * @param skipClosable Leave out transports with a close(): close() flushes
2905
+ * them itself, and a second flush first would double the time a hung
2906
+ * endpoint can hold shutdown.
2907
+ */
2908
+ async flushTransports(skipClosable) {
2664
2909
  const flushPromises = [];
2665
- for (const [id, transport] of this.transports) if (this.isBatchTransport(transport)) {
2666
- const flushPromise = transport.flush().catch((error) => {
2667
- this.emit("error", error, id);
2668
- });
2669
- flushPromises.push(flushPromise);
2910
+ for (const [id, transport] of this.transports) {
2911
+ if (skipClosable && transport.close) continue;
2912
+ if (this.isBatchTransport(transport)) {
2913
+ const flushPromise = transport.flush().catch((error) => {
2914
+ this.emit("error", error, id);
2915
+ });
2916
+ flushPromises.push(flushPromise);
2917
+ }
2670
2918
  }
2671
2919
  await Promise.allSettled(flushPromises);
2672
2920
  this.emit("flush", "all", this.transports.size);
2673
2921
  }
2674
- async close() {
2675
- await this.flush();
2922
+ close() {
2923
+ this.closePromise ??= this.closeOnce();
2924
+ return this.closePromise;
2925
+ }
2926
+ async closeOnce() {
2927
+ await this.flushTransports(true);
2676
2928
  this.isShuttingDown = true;
2929
+ await Promise.allSettled([...this.retryStates.keys()].map((id) => this.drainRetries(id, this.transports.get(id))));
2677
2930
  const closePromises = [];
2678
2931
  for (const [id, transport] of this.transports) if (transport.close) {
2679
2932
  const closePromise = transport.close().catch((error) => {
@@ -2997,4 +3250,4 @@ Object.defineProperty(exports, "stripControlChars", {
2997
3250
  }
2998
3251
  });
2999
3252
 
3000
- //# sourceMappingURL=otel-DH6-G6DR.js.map
3253
+ //# sourceMappingURL=otel-8ypFGG19.js.map