logixia 1.13.3 → 2.0.4

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 (229) hide show
  1. package/README.md +117 -44
  2. package/dist/async-context-B05ArHgM.mjs +134 -0
  3. package/dist/async-context-B05ArHgM.mjs.map +1 -0
  4. package/dist/async-context-DTQgi8f7.js +150 -0
  5. package/dist/async-context-DTQgi8f7.js.map +1 -0
  6. package/dist/{azure-monitor.transport-CHnjVRF-.mjs → azure-monitor.transport-BPbgjATu.mjs} +27 -15
  7. package/dist/azure-monitor.transport-BPbgjATu.mjs.map +1 -0
  8. package/dist/{azure-monitor.transport-BDFO4F-i.d.ts → azure-monitor.transport-C7kYyZUW.d.mts} +3 -6
  9. package/dist/azure-monitor.transport-C7kYyZUW.d.mts.map +1 -0
  10. package/dist/{azure-monitor.transport-CrvfHd9C.js → azure-monitor.transport-CwbOLZHB.js} +32 -20
  11. package/dist/azure-monitor.transport-CwbOLZHB.js.map +1 -0
  12. package/dist/{azure-monitor.transport-D5wQEH04.d.mts → azure-monitor.transport-DV03Z5P4.d.ts} +3 -6
  13. package/dist/azure-monitor.transport-DV03Z5P4.d.ts.map +1 -0
  14. package/dist/azure.d.mts +1 -2
  15. package/dist/azure.d.ts +1 -2
  16. package/dist/azure.js +3 -6
  17. package/dist/azure.mjs +1 -6
  18. package/dist/{batch-buffer-PGvSgbmd.mjs → batch-buffer-0fgLmIPn.mjs} +21 -7
  19. package/dist/batch-buffer-0fgLmIPn.mjs.map +1 -0
  20. package/dist/{batch-buffer-BY-mRWIK.js → batch-buffer-DT4gdXmf.js} +53 -40
  21. package/dist/batch-buffer-DT4gdXmf.js.map +1 -0
  22. package/dist/browser.d.mts +52 -23
  23. package/dist/browser.d.mts.map +1 -1
  24. package/dist/browser.d.ts +52 -23
  25. package/dist/browser.d.ts.map +1 -1
  26. package/dist/browser.js +460 -62
  27. package/dist/browser.js.map +1 -1
  28. package/dist/browser.mjs +461 -65
  29. package/dist/browser.mjs.map +1 -1
  30. package/dist/{nestjs-extras-ImbuDhs1.mjs → builder-D70z6kjj.mjs} +279 -965
  31. package/dist/builder-D70z6kjj.mjs.map +1 -0
  32. package/dist/{nestjs-extras-DnJ6vrIC.js → builder-M7NoaugM.js} +421 -1177
  33. package/dist/builder-M7NoaugM.js.map +1 -0
  34. package/dist/cli/index.js +86 -67
  35. package/dist/cloudwatch.d.mts +1 -2
  36. package/dist/cloudwatch.d.ts +1 -2
  37. package/dist/cloudwatch.js +3 -7
  38. package/dist/cloudwatch.mjs +1 -7
  39. package/dist/{cloudwatch.transport-BO1ahxw-.js → cloudwatch.transport-B2wKQFF7.js} +61 -36
  40. package/dist/cloudwatch.transport-B2wKQFF7.js.map +1 -0
  41. package/dist/{cloudwatch.transport-DZ6ies7g.mjs → cloudwatch.transport-BTvYfLs9.mjs} +54 -28
  42. package/dist/cloudwatch.transport-BTvYfLs9.mjs.map +1 -0
  43. package/dist/{cloudwatch.transport-B00st6Xv.d.ts → cloudwatch.transport-Bf7L4I59.d.ts} +2 -6
  44. package/dist/cloudwatch.transport-Bf7L4I59.d.ts.map +1 -0
  45. package/dist/{cloudwatch.transport-Blc7Gtxt.d.mts → cloudwatch.transport-Rj4yTpRn.d.mts} +2 -6
  46. package/dist/cloudwatch.transport-Rj4yTpRn.d.mts.map +1 -0
  47. package/dist/{coerce.utils-Cu6IUTgX.mjs → coerce.utils-B_rEudCn.mjs} +3 -4
  48. package/dist/{coerce.utils-Cu6IUTgX.mjs.map → coerce.utils-B_rEudCn.mjs.map} +1 -1
  49. package/dist/{coerce.utils-B-LilukN.js → coerce.utils-C1C5sIX0.js} +8 -10
  50. package/dist/{coerce.utils-B-LilukN.js.map → coerce.utils-C1C5sIX0.js.map} +1 -1
  51. package/dist/correlation.d.mts +13 -16
  52. package/dist/correlation.d.mts.map +1 -1
  53. package/dist/correlation.d.ts +13 -16
  54. package/dist/correlation.d.ts.map +1 -1
  55. package/dist/correlation.js +58 -9
  56. package/dist/correlation.js.map +1 -1
  57. package/dist/correlation.mjs +56 -6
  58. package/dist/correlation.mjs.map +1 -1
  59. package/dist/{entry-fields-BJkuPnIg.mjs → entry-fields-CGuvT2R0.mjs} +5 -6
  60. package/dist/entry-fields-CGuvT2R0.mjs.map +1 -0
  61. package/dist/{entry-fields-BvOLFlJ4.js → entry-fields-RLd1jCoR.js} +10 -12
  62. package/dist/entry-fields-RLd1jCoR.js.map +1 -0
  63. package/dist/gcp.d.mts +1 -2
  64. package/dist/gcp.d.ts +1 -2
  65. package/dist/gcp.js +3 -7
  66. package/dist/gcp.mjs +1 -7
  67. package/dist/{gcp.transport-m4fVw0b1.d.ts → gcp.transport-C5D72b1g.d.mts} +3 -6
  68. package/dist/gcp.transport-C5D72b1g.d.mts.map +1 -0
  69. package/dist/{gcp.transport-zzNyIoih.d.mts → gcp.transport-CFQfdAOK.d.ts} +3 -6
  70. package/dist/gcp.transport-CFQfdAOK.d.ts.map +1 -0
  71. package/dist/{gcp.transport-DBX5TPIy.mjs → gcp.transport-CGKopAhQ.mjs} +55 -16
  72. package/dist/gcp.transport-CGKopAhQ.mjs.map +1 -0
  73. package/dist/{gcp.transport-CHV8MGgz.js → gcp.transport-KZe9hCAR.js} +60 -22
  74. package/dist/gcp.transport-KZe9hCAR.js.map +1 -0
  75. package/dist/{index-nZEeCr3X.d.ts → index-DwozbmB4.d.ts} +3 -8
  76. package/dist/index-DwozbmB4.d.ts.map +1 -0
  77. package/dist/{index-BPwEisy4.d.mts → index-xqaJtAZn.d.mts} +3 -8
  78. package/dist/index-xqaJtAZn.d.mts.map +1 -0
  79. package/dist/index.d.mts +141 -203
  80. package/dist/index.d.mts.map +1 -1
  81. package/dist/index.d.ts +140 -202
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +196 -381
  84. package/dist/index.js.map +1 -1
  85. package/dist/index.mjs +145 -294
  86. package/dist/index.mjs.map +1 -1
  87. package/dist/internal-log-b0Vp4qrB.js +183 -0
  88. package/dist/internal-log-b0Vp4qrB.js.map +1 -0
  89. package/dist/internal-log-uCSd1PMc.mjs +142 -0
  90. package/dist/internal-log-uCSd1PMc.mjs.map +1 -0
  91. package/dist/logitron-logger-D2B75Oc7.d.ts +365 -0
  92. package/dist/logitron-logger-D2B75Oc7.d.ts.map +1 -0
  93. package/dist/logitron-logger-oEd6wNhf.d.mts +365 -0
  94. package/dist/logitron-logger-oEd6wNhf.d.mts.map +1 -0
  95. package/dist/middleware.d.mts +10 -12
  96. package/dist/middleware.d.mts.map +1 -1
  97. package/dist/middleware.d.ts +10 -12
  98. package/dist/middleware.d.ts.map +1 -1
  99. package/dist/middleware.js +16 -47
  100. package/dist/middleware.js.map +1 -1
  101. package/dist/middleware.mjs +13 -45
  102. package/dist/middleware.mjs.map +1 -1
  103. package/dist/nest.d.mts +467 -10
  104. package/dist/nest.d.mts.map +1 -1
  105. package/dist/nest.d.ts +467 -10
  106. package/dist/nest.d.ts.map +1 -1
  107. package/dist/nest.js +889 -43
  108. package/dist/nest.js.map +1 -0
  109. package/dist/nest.mjs +850 -9
  110. package/dist/nest.mjs.map +1 -0
  111. package/dist/{trace.utils-CvXgaiQT.mjs → request-trace-C_fvIDv4.mjs} +44 -9
  112. package/dist/request-trace-C_fvIDv4.mjs.map +1 -0
  113. package/dist/{trace.utils-DpBOLDtq.js → request-trace-wTJdKp6-.js} +121 -77
  114. package/dist/request-trace-wTJdKp6-.js.map +1 -0
  115. package/dist/rolldown-runtime-D3PmRqjj.mjs +4 -0
  116. package/dist/{safe-stringify-DJ66tW5I.mjs → safe-stringify-BMRl3EX3.mjs} +3 -4
  117. package/dist/safe-stringify-BMRl3EX3.mjs.map +1 -0
  118. package/dist/{safe-stringify-DWo3aZp_.js → safe-stringify-DLz1Kz3o.js} +23 -25
  119. package/dist/safe-stringify-DLz1Kz3o.js.map +1 -0
  120. package/dist/{search-CHUZPl0h.d.ts → search-BH33XhuU.d.mts} +2 -22
  121. package/dist/search-BH33XhuU.d.mts.map +1 -0
  122. package/dist/{search-DjXSn6v5.mjs → search-CWMVYC-R.mjs} +34 -41
  123. package/dist/search-CWMVYC-R.mjs.map +1 -0
  124. package/dist/{search-BfBzDIT9.d.mts → search-CazwyX5Z.d.ts} +2 -22
  125. package/dist/search-CazwyX5Z.d.ts.map +1 -0
  126. package/dist/{search-B0MH1SJJ.js → search-DUfWuzFP.js} +64 -71
  127. package/dist/search-DUfWuzFP.js.map +1 -0
  128. package/dist/search.d.mts +2 -4
  129. package/dist/search.d.ts +2 -4
  130. package/dist/search.js +3 -4
  131. package/dist/search.mjs +1 -4
  132. package/dist/secret-config-BegMLkYl.mjs +209 -0
  133. package/dist/secret-config-BegMLkYl.mjs.map +1 -0
  134. package/dist/secret-config-CBZBs0p1.js +271 -0
  135. package/dist/secret-config-CBZBs0p1.js.map +1 -0
  136. package/dist/slack.transport-Ce96JBDk.mjs +824 -0
  137. package/dist/slack.transport-Ce96JBDk.mjs.map +1 -0
  138. package/dist/slack.transport-Dlx3xvb7.js +847 -0
  139. package/dist/slack.transport-Dlx3xvb7.js.map +1 -0
  140. package/dist/slack.transport-DrirgDNy.d.ts +159 -0
  141. package/dist/slack.transport-DrirgDNy.d.ts.map +1 -0
  142. package/dist/slack.transport-DxHOXlLu.d.mts +159 -0
  143. package/dist/slack.transport-DxHOXlLu.d.mts.map +1 -0
  144. package/dist/testing.d.mts +3 -8
  145. package/dist/testing.d.mts.map +1 -1
  146. package/dist/testing.d.ts +3 -8
  147. package/dist/testing.d.ts.map +1 -1
  148. package/dist/testing.js +3 -4
  149. package/dist/testing.js.map +1 -1
  150. package/dist/testing.mjs +2 -3
  151. package/dist/testing.mjs.map +1 -1
  152. package/dist/{transport.manager-Crau3Rle.js → transport.manager-DkcEOlqV.js} +331 -234
  153. package/dist/transport.manager-DkcEOlqV.js.map +1 -0
  154. package/dist/{transport.manager-CpdVHEGP.mjs → transport.manager-eZ_EeC00.mjs} +274 -178
  155. package/dist/transport.manager-eZ_EeC00.mjs.map +1 -0
  156. package/dist/{transport.types-CtNr3D7S.d.mts → transport.types-BJVL1QQl.d.mts} +5 -4
  157. package/dist/transport.types-BJVL1QQl.d.mts.map +1 -0
  158. package/dist/{transport.types-DqVLZTyf.d.ts → transport.types-BJVL1QQl.d.ts} +5 -4
  159. package/dist/transport.types-BJVL1QQl.d.ts.map +1 -0
  160. package/dist/transports.d.mts +32 -41
  161. package/dist/transports.d.mts.map +1 -1
  162. package/dist/transports.d.ts +32 -41
  163. package/dist/transports.d.ts.map +1 -1
  164. package/dist/transports.js +12 -12
  165. package/dist/transports.mjs +7 -12
  166. package/dist/worker-entry.js +337 -87
  167. package/dist/worker.d.mts +1 -2
  168. package/dist/worker.d.ts +1 -2
  169. package/dist/worker.js +3 -4
  170. package/dist/worker.mjs +1 -4
  171. package/dist/{worker.transport-Bj-i0P9V.d.ts → worker.transport-BuPwBi3d.d.ts} +2 -6
  172. package/dist/worker.transport-BuPwBi3d.d.ts.map +1 -0
  173. package/dist/{worker.transport-JP8YHBuU.js → worker.transport-C6GNl_r2.js} +44 -14
  174. package/dist/worker.transport-C6GNl_r2.js.map +1 -0
  175. package/dist/{worker.transport-otwhJ_Et.mjs → worker.transport-DLVA4y2e.mjs} +39 -9
  176. package/dist/worker.transport-DLVA4y2e.mjs.map +1 -0
  177. package/dist/{worker.transport-Bgv9heDI.d.mts → worker.transport-hJay1wxA.d.mts} +2 -6
  178. package/dist/worker.transport-hJay1wxA.d.mts.map +1 -0
  179. package/package.json +36 -19
  180. package/dist/async-context-BzJrbfQs.mjs +0 -72
  181. package/dist/async-context-BzJrbfQs.mjs.map +0 -1
  182. package/dist/async-context-DyQQYq3I.js +0 -92
  183. package/dist/async-context-DyQQYq3I.js.map +0 -1
  184. package/dist/azure-monitor.transport-BDFO4F-i.d.ts.map +0 -1
  185. package/dist/azure-monitor.transport-CHnjVRF-.mjs.map +0 -1
  186. package/dist/azure-monitor.transport-CrvfHd9C.js.map +0 -1
  187. package/dist/azure-monitor.transport-D5wQEH04.d.mts.map +0 -1
  188. package/dist/batch-buffer-BY-mRWIK.js.map +0 -1
  189. package/dist/batch-buffer-PGvSgbmd.mjs.map +0 -1
  190. package/dist/chunk-DLSkYcPk.mjs +0 -7
  191. package/dist/chunk-nOFOJqeH.js +0 -30
  192. package/dist/cloudwatch.transport-B00st6Xv.d.ts.map +0 -1
  193. package/dist/cloudwatch.transport-BO1ahxw-.js.map +0 -1
  194. package/dist/cloudwatch.transport-Blc7Gtxt.d.mts.map +0 -1
  195. package/dist/cloudwatch.transport-DZ6ies7g.mjs.map +0 -1
  196. package/dist/entry-fields-BJkuPnIg.mjs.map +0 -1
  197. package/dist/entry-fields-BvOLFlJ4.js.map +0 -1
  198. package/dist/gcp.transport-CHV8MGgz.js.map +0 -1
  199. package/dist/gcp.transport-DBX5TPIy.mjs.map +0 -1
  200. package/dist/gcp.transport-m4fVw0b1.d.ts.map +0 -1
  201. package/dist/gcp.transport-zzNyIoih.d.mts.map +0 -1
  202. package/dist/index-BPwEisy4.d.mts.map +0 -1
  203. package/dist/index-nZEeCr3X.d.ts.map +0 -1
  204. package/dist/internal-log-BUJYMZbE.js +0 -70
  205. package/dist/internal-log-BUJYMZbE.js.map +0 -1
  206. package/dist/internal-log-Cm8SOWSV.mjs +0 -52
  207. package/dist/internal-log-Cm8SOWSV.mjs.map +0 -1
  208. package/dist/nestjs-extras-DnJ6vrIC.js.map +0 -1
  209. package/dist/nestjs-extras-ImbuDhs1.mjs.map +0 -1
  210. package/dist/nestjs-extras-OkC796py.d.mts +0 -725
  211. package/dist/nestjs-extras-OkC796py.d.mts.map +0 -1
  212. package/dist/nestjs-extras-mKrHE9S6.d.ts +0 -725
  213. package/dist/nestjs-extras-mKrHE9S6.d.ts.map +0 -1
  214. package/dist/safe-stringify-DJ66tW5I.mjs.map +0 -1
  215. package/dist/safe-stringify-DWo3aZp_.js.map +0 -1
  216. package/dist/search-B0MH1SJJ.js.map +0 -1
  217. package/dist/search-BfBzDIT9.d.mts.map +0 -1
  218. package/dist/search-CHUZPl0h.d.ts.map +0 -1
  219. package/dist/search-DjXSn6v5.mjs.map +0 -1
  220. package/dist/trace.utils-CvXgaiQT.mjs.map +0 -1
  221. package/dist/trace.utils-DpBOLDtq.js.map +0 -1
  222. package/dist/transport.manager-CpdVHEGP.mjs.map +0 -1
  223. package/dist/transport.manager-Crau3Rle.js.map +0 -1
  224. package/dist/transport.types-CtNr3D7S.d.mts.map +0 -1
  225. package/dist/transport.types-DqVLZTyf.d.ts.map +0 -1
  226. package/dist/worker.transport-Bgv9heDI.d.mts.map +0 -1
  227. package/dist/worker.transport-Bj-i0P9V.d.ts.map +0 -1
  228. package/dist/worker.transport-JP8YHBuU.js.map +0 -1
  229. package/dist/worker.transport-otwhJ_Et.mjs.map +0 -1
@@ -1,8 +1,8 @@
1
- import { r as internalWarn, t as internalError } from "./internal-log-Cm8SOWSV.mjs";
2
- import { i as stringifyForLog } from "./safe-stringify-DJ66tW5I.mjs";
3
- import { a as httpRequest, n as DEFAULT_MAX_BUFFER_SIZE, r as DEFAULT_REQUEST_TIMEOUT_MS, t as BatchBuffer } from "./batch-buffer-PGvSgbmd.mjs";
4
-
5
- //#region src/transports/azure-monitor.transport.ts
1
+ import { r as internalWarn, t as internalError } from "./internal-log-uCSd1PMc.mjs";
2
+ import { i as scrubSecrets, n as protectSecrets, o as urlSecrets, r as scrubError } from "./secret-config-BegMLkYl.mjs";
3
+ import { i as stringifyForLog } from "./safe-stringify-BMRl3EX3.mjs";
4
+ import { a as httpRequest, t as BatchBuffer } from "./batch-buffer-0fgLmIPn.mjs";
5
+ // src/transports/azure-monitor.transport.ts
6
6
  /**
7
7
  * Azure AD tenant IDs are either a GUID or a verified domain (e.g. `contoso.onmicrosoft.com`).
8
8
  * This pattern is deliberately permissive on structure but strict on character
@@ -32,6 +32,7 @@ var AzureMonitorTransport = class {
32
32
  this.flushTimer = null;
33
33
  this.accessToken = null;
34
34
  this.tokenExpiry = 0;
35
+ protectSecrets(this, ["clientSecret", "accessToken"]);
35
36
  this.endpoint = config.endpoint.replace(/\/$/, "");
36
37
  this.ruleId = config.ruleId;
37
38
  this.streamName = config.streamName;
@@ -41,12 +42,13 @@ var AzureMonitorTransport = class {
41
42
  this.batchSize = config.batchSize ?? 200;
42
43
  this.flushInterval = config.flushIntervalMs ?? 5e3;
43
44
  this.level = config.level;
44
- this.requestTimeoutMs = config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
45
+ this.requestTimeoutMs = config.requestTimeoutMs ?? 1e4;
45
46
  this.buffer = new BatchBuffer({
46
47
  name: "AzureMonitorTransport",
47
48
  batchSize: this.batchSize,
48
- maxBufferSize: config.maxBufferSize ?? DEFAULT_MAX_BUFFER_SIZE,
49
- send: (entries) => this.sendEntries(entries)
49
+ maxBufferSize: config.maxBufferSize ?? 1e4,
50
+ send: (entries) => this.sendEntries(entries),
51
+ secrets: () => this.secretValues()
50
52
  });
51
53
  this.flushTimer = setInterval(() => {
52
54
  this.flush().catch(() => {});
@@ -83,6 +85,14 @@ var AzureMonitorTransport = class {
83
85
  Properties: stringifyForLog(entry.data ?? {})
84
86
  };
85
87
  }
88
+ secretValues(token) {
89
+ return [
90
+ this.clientSecret,
91
+ this.accessToken ?? void 0,
92
+ token,
93
+ ...urlSecrets(this.endpoint)
94
+ ];
95
+ }
86
96
  async getAccessToken() {
87
97
  if (this.accessToken && Date.now() < this.tokenExpiry) return this.accessToken;
88
98
  if (!this.tenantId || !this.clientId || !this.clientSecret) {
@@ -107,7 +117,8 @@ var AzureMonitorTransport = class {
107
117
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
108
118
  body,
109
119
  timeoutMs: this.requestTimeoutMs,
110
- label: "Azure token request"
120
+ label: "Azure token request",
121
+ secrets: () => this.secretValues()
111
122
  });
112
123
  const parsed = JSON.parse(res.body);
113
124
  if (!parsed.access_token) return null;
@@ -122,12 +133,13 @@ var AzureMonitorTransport = class {
122
133
  async sendEntries(entries) {
123
134
  const token = await this.getAccessToken();
124
135
  if (!token) throw new Error("AzureMonitorTransport: no access token available");
125
- const body = stringifyForLog(entries.map((e) => this.toAzureRecord(e)));
136
+ const records = entries.map((e) => this.toAzureRecord(e));
137
+ const body = stringifyForLog(records);
126
138
  let reqUrl;
127
139
  try {
128
140
  reqUrl = new URL(`dataCollectionRules/${encodeURIComponent(this.ruleId)}/streams/${encodeURIComponent(this.streamName)}?api-version=2023-01-01`, this.endpoint.endsWith("/") ? this.endpoint : `${this.endpoint}/`);
129
141
  } catch (error) {
130
- internalError(`AzureMonitorTransport: invalid endpoint "${this.endpoint}"`, error);
142
+ internalError(`AzureMonitorTransport: invalid endpoint "${scrubSecrets(this.endpoint, urlSecrets(this.endpoint))}"`, scrubError(error, urlSecrets(this.endpoint)));
131
143
  return;
132
144
  }
133
145
  if (reqUrl.protocol !== "https:") {
@@ -142,11 +154,11 @@ var AzureMonitorTransport = class {
142
154
  },
143
155
  body,
144
156
  timeoutMs: this.requestTimeoutMs,
145
- label: "Azure Monitor API"
157
+ label: "Azure Monitor API",
158
+ secrets: () => this.secretValues(token)
146
159
  });
147
160
  }
148
161
  };
149
-
150
- //#endregion
151
162
  export { AzureMonitorTransport as t };
152
- //# sourceMappingURL=azure-monitor.transport-CHnjVRF-.mjs.map
163
+
164
+ //# sourceMappingURL=azure-monitor.transport-BPbgjATu.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-monitor.transport-BPbgjATu.mjs","names":[],"sources":["../src/transports/azure-monitor.transport.ts"],"sourcesContent":["/**\n * logixia — Azure Monitor / Application Insights transport\n *\n * Sends log entries to Azure Monitor via the Data Collection Rules (DCR) API\n * using the Logs Ingestion API (the modern replacement for the legacy HTTP\n * Data Collector API).\n *\n * Maps logixia levels to Application Insights severity levels:\n * verbose → 0, debug → 1, info → 1, warn → 2, error → 3, critical → 4\n *\n * @example\n * ```ts\n * import { AzureMonitorTransport } from 'logixia';\n *\n * const logger = createLogger({\n * transports: {\n * azure: new AzureMonitorTransport({\n * // Logs Ingestion API endpoint (from your DCR)\n * endpoint: 'https://<dce>.ingest.monitor.azure.com',\n * ruleId: 'dcr-xxxxxxxxxxxxxxxx',\n * streamName: 'Custom-LogixiaLogs',\n * // Client credentials (or managed identity via no-credential mode)\n * tenantId: process.env.AZURE_TENANT_ID,\n * clientId: process.env.AZURE_CLIENT_ID,\n * clientSecret: process.env.AZURE_CLIENT_SECRET,\n * }),\n * },\n * });\n * ```\n */\n\nimport type { IAsyncTransport, TransportLogEntry } from '../types/transport.types';\nimport { internalError, internalWarn } from '../utils/internal-log';\nimport { stringifyForLog } from '../utils/safe-stringify';\nimport {\n BatchBuffer,\n DEFAULT_MAX_BUFFER_SIZE,\n DEFAULT_REQUEST_TIMEOUT_MS,\n httpRequest,\n} from './batch-buffer';\nimport { protectSecrets, scrubError, scrubSecrets, urlSecrets } from './secret-config';\n\n/**\n * Azure AD tenant IDs are either a GUID or a verified domain (e.g. `contoso.onmicrosoft.com`).\n * This pattern is deliberately permissive on structure but strict on character\n * set — it rejects the breakout characters (`/`, `@`, `:`, `?`, `#`, whitespace)\n * that would let a hostile config smuggle a different host, path, or query into\n * the OAuth token URL.\n */\nconst AZURE_TENANT_RE = /^[a-z0-9][a-z0-9.-]{1,253}$/i;\n\nexport interface AzureMonitorTransportConfig {\n /** DCE (Data Collection Endpoint) URL, e.g. `https://<name>.ingest.monitor.azure.com`. */\n endpoint: string;\n /** Data Collection Rule immutable ID (from Azure portal). */\n ruleId: string;\n /** Stream name defined in the DCR, e.g. `'Custom-LogixiaLogs_CL'`. */\n streamName: string;\n /** Azure AD tenant ID for OAuth2 client-credentials flow. */\n tenantId?: string;\n /** Azure AD app (service principal) client ID. */\n clientId?: string;\n /** Azure AD app client secret. */\n clientSecret?: string;\n /** Number of entries to batch. @default 200 */\n batchSize?: number;\n /** Flush interval in ms. @default 5000 */\n flushIntervalMs?: number;\n /** Abort a request that has not finished after this many ms. @default 10000 */\n requestTimeoutMs?: number;\n /** Max buffered entries; the oldest are dropped past this. @default 10000 */\n maxBufferSize?: number;\n level?: string;\n}\n\nconst SEVERITY_MAP: Record<string, number> = {\n verbose: 0,\n trace: 0,\n debug: 1,\n info: 1,\n log: 1,\n warn: 2,\n warning: 2,\n error: 3,\n critical: 4,\n fatal: 4,\n};\n\n/**\n * Azure Monitor Logs Ingestion transport.\n */\nexport class AzureMonitorTransport implements IAsyncTransport {\n public readonly name = 'azure-monitor';\n public readonly batchSize: number;\n public readonly flushInterval: number;\n public readonly level: string | undefined;\n\n private readonly buffer: BatchBuffer<TransportLogEntry>;\n private readonly requestTimeoutMs: number;\n private flushTimer: NodeJS.Timeout | null = null;\n private accessToken: string | null = null;\n private tokenExpiry = 0;\n\n private readonly endpoint: string;\n private readonly ruleId: string;\n private readonly streamName: string;\n private readonly tenantId: string | undefined;\n private readonly clientId: string | undefined;\n private readonly clientSecret: string | undefined;\n\n constructor(config: AzureMonitorTransportConfig) {\n protectSecrets(this, ['clientSecret', 'accessToken']);\n this.endpoint = config.endpoint.replace(/\\/$/, '');\n this.ruleId = config.ruleId;\n this.streamName = config.streamName;\n this.tenantId = config.tenantId ?? process.env['AZURE_TENANT_ID'];\n this.clientId = config.clientId ?? process.env['AZURE_CLIENT_ID'];\n this.clientSecret = config.clientSecret ?? process.env['AZURE_CLIENT_SECRET'];\n this.batchSize = config.batchSize ?? 200;\n this.flushInterval = config.flushIntervalMs ?? 5000;\n this.level = config.level;\n this.requestTimeoutMs = config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n this.buffer = new BatchBuffer<TransportLogEntry>({\n name: 'AzureMonitorTransport',\n batchSize: this.batchSize,\n maxBufferSize: config.maxBufferSize ?? DEFAULT_MAX_BUFFER_SIZE,\n send: (entries) => this.sendEntries(entries),\n secrets: () => this.secretValues(),\n });\n\n this.flushTimer = setInterval(() => {\n this.flush().catch(() => {});\n }, this.flushInterval);\n if (this.flushTimer.unref) this.flushTimer.unref();\n }\n\n write(entry: TransportLogEntry): void {\n this.buffer.push(entry);\n this.buffer.flushIfFull();\n }\n\n flush(): Promise<void> {\n return this.buffer.flush();\n }\n\n /**\n * Flush remaining entries and stop the interval timer on shutdown. Without\n * this the manager's close() skipped the transport (close was undefined) and\n * buffered entries were lost on deploy. Waits for any in-flight send first.\n */\n async close(): Promise<void> {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n await this.buffer.close();\n }\n\n private toAzureRecord(entry: TransportLogEntry): Record<string, unknown> {\n return {\n TimeGenerated: entry.timestamp ?? new Date().toISOString(),\n SeverityLevel: SEVERITY_MAP[entry.level.toLowerCase()] ?? 1,\n Message: entry.message,\n AppName: entry.appName,\n Context: entry.context ?? '',\n TraceId: entry.traceId ?? '',\n Properties: stringifyForLog(entry.data ?? {}),\n };\n }\n\n private secretValues(token?: string): (string | undefined)[] {\n return [this.clientSecret, this.accessToken ?? undefined, token, ...urlSecrets(this.endpoint)];\n }\n\n private async getAccessToken(): Promise<string | null> {\n if (this.accessToken && Date.now() < this.tokenExpiry) return this.accessToken;\n\n if (!this.tenantId || !this.clientId || !this.clientSecret) {\n internalWarn(\n 'AzureMonitorTransport: missing credentials — set tenantId, clientId, clientSecret'\n );\n return null;\n }\n\n const body = new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: this.clientId,\n client_secret: this.clientSecret,\n scope: 'https://monitor.azure.com/.default',\n }).toString();\n\n const tenantId = this.tenantId;\n if (!AZURE_TENANT_RE.test(tenantId)) {\n internalWarn(\n `AzureMonitorTransport: refusing to request token — tenantId \"${tenantId}\" is not a valid GUID or domain`\n );\n return null;\n }\n\n const reqUrl = new URL(\n `https://login.microsoftonline.com/${encodeURIComponent(tenantId)}/oauth2/v2.0/token`\n );\n try {\n const res = await httpRequest({\n url: reqUrl,\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body,\n timeoutMs: this.requestTimeoutMs,\n label: 'Azure token request',\n secrets: () => this.secretValues(),\n });\n const parsed = JSON.parse(res.body) as { access_token?: string; expires_in?: number };\n if (!parsed.access_token) return null;\n this.accessToken = parsed.access_token;\n this.tokenExpiry = Date.now() + (parsed.expires_in ?? 3600) * 1000 - 60_000;\n return this.accessToken;\n } catch (err) {\n internalError('AzureMonitorTransport token request failed', err);\n return null;\n }\n }\n\n private async sendEntries(entries: TransportLogEntry[]): Promise<void> {\n const token = await this.getAccessToken();\n if (!token) throw new Error('AzureMonitorTransport: no access token available');\n\n const records = entries.map((e) => this.toAzureRecord(e));\n const body = stringifyForLog(records);\n let reqUrl: URL;\n try {\n // Build from the user-configured DCE endpoint; encodeURIComponent-ing the\n // ruleId/streamName stops a hostile config from smuggling extra path\n // segments or query params into the request.\n reqUrl = new URL(\n `dataCollectionRules/${encodeURIComponent(this.ruleId)}/streams/${encodeURIComponent(this.streamName)}?api-version=2023-01-01`,\n this.endpoint.endsWith('/') ? this.endpoint : `${this.endpoint}/`\n );\n } catch (error) {\n internalError(\n `AzureMonitorTransport: invalid endpoint \"${scrubSecrets(this.endpoint, urlSecrets(this.endpoint))}\"`,\n scrubError(error, urlSecrets(this.endpoint))\n );\n return;\n }\n if (reqUrl.protocol !== 'https:') {\n internalError(`AzureMonitorTransport: endpoint must use https (got ${reqUrl.protocol})`);\n return;\n }\n\n await httpRequest({\n url: reqUrl,\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n body,\n timeoutMs: this.requestTimeoutMs,\n label: 'Azure Monitor API',\n secrets: () => this.secretValues(token),\n });\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,4 @@
1
- import { p as TransportLogEntry, s as IAsyncTransport } from "./transport.types-DqVLZTyf.js";
2
-
3
- //#region src/transports/azure-monitor.transport.d.ts
4
-
1
+ import { p as TransportLogEntry, s as IAsyncTransport } from "./transport.types-BJVL1QQl.mjs";
5
2
  interface AzureMonitorTransportConfig {
6
3
  /** DCE (Data Collection Endpoint) URL, e.g. `https://<name>.ingest.monitor.azure.com`. */
7
4
  endpoint: string;
@@ -54,9 +51,9 @@ declare class AzureMonitorTransport implements IAsyncTransport {
54
51
  */
55
52
  close(): Promise<void>;
56
53
  private toAzureRecord;
54
+ private secretValues;
57
55
  private getAccessToken;
58
56
  private sendEntries;
59
57
  }
60
- //#endregion
61
58
  export { AzureMonitorTransportConfig as n, AzureMonitorTransport as t };
62
- //# sourceMappingURL=azure-monitor.transport-BDFO4F-i.d.ts.map
59
+ //# sourceMappingURL=azure-monitor.transport-C7kYyZUW.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-monitor.transport-C7kYyZUW.d.mts","names":[],"sources":["../src/transports/azure-monitor.transport.ts"],"mappings":";UAmDiB;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;EACA;;;;;cAmBW,iCAAiC;WAC5B;WACA;WACA;WACA;mBAEC;mBACA;UACT;UACA;UACA;mBAES;mBACA;mBACA;mBACA;mBACA;mBACA;EAEL,YAAA,QAAQ;EA0BpB,MAAM,OAAO;EAKb,SAAS;;;;;;EASH,SAAS;UAQP;UAYA;UAIM;UAgDA"}
@@ -1,8 +1,8 @@
1
- const require_internal_log = require('./internal-log-BUJYMZbE.js');
2
- const require_safe_stringify = require('./safe-stringify-DWo3aZp_.js');
3
- const require_batch_buffer = require('./batch-buffer-BY-mRWIK.js');
4
-
5
- //#region src/transports/azure-monitor.transport.ts
1
+ const require_secret_config = require("./secret-config-CBZBs0p1.js");
2
+ const require_internal_log = require("./internal-log-b0Vp4qrB.js");
3
+ const require_safe_stringify = require("./safe-stringify-DLz1Kz3o.js");
4
+ const require_batch_buffer = require("./batch-buffer-DT4gdXmf.js");
5
+ // src/transports/azure-monitor.transport.ts
6
6
  /**
7
7
  * Azure AD tenant IDs are either a GUID or a verified domain (e.g. `contoso.onmicrosoft.com`).
8
8
  * This pattern is deliberately permissive on structure but strict on character
@@ -32,6 +32,7 @@ var AzureMonitorTransport = class {
32
32
  this.flushTimer = null;
33
33
  this.accessToken = null;
34
34
  this.tokenExpiry = 0;
35
+ require_secret_config.protectSecrets(this, ["clientSecret", "accessToken"]);
35
36
  this.endpoint = config.endpoint.replace(/\/$/, "");
36
37
  this.ruleId = config.ruleId;
37
38
  this.streamName = config.streamName;
@@ -41,12 +42,13 @@ var AzureMonitorTransport = class {
41
42
  this.batchSize = config.batchSize ?? 200;
42
43
  this.flushInterval = config.flushIntervalMs ?? 5e3;
43
44
  this.level = config.level;
44
- this.requestTimeoutMs = config.requestTimeoutMs ?? require_batch_buffer.DEFAULT_REQUEST_TIMEOUT_MS;
45
+ this.requestTimeoutMs = config.requestTimeoutMs ?? 1e4;
45
46
  this.buffer = new require_batch_buffer.BatchBuffer({
46
47
  name: "AzureMonitorTransport",
47
48
  batchSize: this.batchSize,
48
- maxBufferSize: config.maxBufferSize ?? require_batch_buffer.DEFAULT_MAX_BUFFER_SIZE,
49
- send: (entries) => this.sendEntries(entries)
49
+ maxBufferSize: config.maxBufferSize ?? 1e4,
50
+ send: (entries) => this.sendEntries(entries),
51
+ secrets: () => this.secretValues()
50
52
  });
51
53
  this.flushTimer = setInterval(() => {
52
54
  this.flush().catch(() => {});
@@ -83,6 +85,14 @@ var AzureMonitorTransport = class {
83
85
  Properties: require_safe_stringify.stringifyForLog(entry.data ?? {})
84
86
  };
85
87
  }
88
+ secretValues(token) {
89
+ return [
90
+ this.clientSecret,
91
+ this.accessToken ?? void 0,
92
+ token,
93
+ ...require_secret_config.urlSecrets(this.endpoint)
94
+ ];
95
+ }
86
96
  async getAccessToken() {
87
97
  if (this.accessToken && Date.now() < this.tokenExpiry) return this.accessToken;
88
98
  if (!this.tenantId || !this.clientId || !this.clientSecret) {
@@ -107,7 +117,8 @@ var AzureMonitorTransport = class {
107
117
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
108
118
  body,
109
119
  timeoutMs: this.requestTimeoutMs,
110
- label: "Azure token request"
120
+ label: "Azure token request",
121
+ secrets: () => this.secretValues()
111
122
  });
112
123
  const parsed = JSON.parse(res.body);
113
124
  if (!parsed.access_token) return null;
@@ -122,12 +133,13 @@ var AzureMonitorTransport = class {
122
133
  async sendEntries(entries) {
123
134
  const token = await this.getAccessToken();
124
135
  if (!token) throw new Error("AzureMonitorTransport: no access token available");
125
- const body = require_safe_stringify.stringifyForLog(entries.map((e) => this.toAzureRecord(e)));
136
+ const records = entries.map((e) => this.toAzureRecord(e));
137
+ const body = require_safe_stringify.stringifyForLog(records);
126
138
  let reqUrl;
127
139
  try {
128
140
  reqUrl = new URL(`dataCollectionRules/${encodeURIComponent(this.ruleId)}/streams/${encodeURIComponent(this.streamName)}?api-version=2023-01-01`, this.endpoint.endsWith("/") ? this.endpoint : `${this.endpoint}/`);
129
141
  } catch (error) {
130
- require_internal_log.internalError(`AzureMonitorTransport: invalid endpoint "${this.endpoint}"`, error);
142
+ require_internal_log.internalError(`AzureMonitorTransport: invalid endpoint "${require_secret_config.scrubSecrets(this.endpoint, require_secret_config.urlSecrets(this.endpoint))}"`, require_secret_config.scrubError(error, require_secret_config.urlSecrets(this.endpoint)));
131
143
  return;
132
144
  }
133
145
  if (reqUrl.protocol !== "https:") {
@@ -142,16 +154,16 @@ var AzureMonitorTransport = class {
142
154
  },
143
155
  body,
144
156
  timeoutMs: this.requestTimeoutMs,
145
- label: "Azure Monitor API"
157
+ label: "Azure Monitor API",
158
+ secrets: () => this.secretValues(token)
146
159
  });
147
160
  }
148
161
  };
149
-
150
- //#endregion
151
- Object.defineProperty(exports, 'AzureMonitorTransport', {
152
- enumerable: true,
153
- get: function () {
154
- return AzureMonitorTransport;
155
- }
162
+ Object.defineProperty(exports, "AzureMonitorTransport", {
163
+ enumerable: true,
164
+ get: function() {
165
+ return AzureMonitorTransport;
166
+ }
156
167
  });
157
- //# sourceMappingURL=azure-monitor.transport-CrvfHd9C.js.map
168
+
169
+ //# sourceMappingURL=azure-monitor.transport-CwbOLZHB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-monitor.transport-CwbOLZHB.js","names":["BatchBuffer","stringifyForLog","urlSecrets","httpRequest","scrubSecrets","scrubError"],"sources":["../src/transports/azure-monitor.transport.ts"],"sourcesContent":["/**\n * logixia — Azure Monitor / Application Insights transport\n *\n * Sends log entries to Azure Monitor via the Data Collection Rules (DCR) API\n * using the Logs Ingestion API (the modern replacement for the legacy HTTP\n * Data Collector API).\n *\n * Maps logixia levels to Application Insights severity levels:\n * verbose → 0, debug → 1, info → 1, warn → 2, error → 3, critical → 4\n *\n * @example\n * ```ts\n * import { AzureMonitorTransport } from 'logixia';\n *\n * const logger = createLogger({\n * transports: {\n * azure: new AzureMonitorTransport({\n * // Logs Ingestion API endpoint (from your DCR)\n * endpoint: 'https://<dce>.ingest.monitor.azure.com',\n * ruleId: 'dcr-xxxxxxxxxxxxxxxx',\n * streamName: 'Custom-LogixiaLogs',\n * // Client credentials (or managed identity via no-credential mode)\n * tenantId: process.env.AZURE_TENANT_ID,\n * clientId: process.env.AZURE_CLIENT_ID,\n * clientSecret: process.env.AZURE_CLIENT_SECRET,\n * }),\n * },\n * });\n * ```\n */\n\nimport type { IAsyncTransport, TransportLogEntry } from '../types/transport.types';\nimport { internalError, internalWarn } from '../utils/internal-log';\nimport { stringifyForLog } from '../utils/safe-stringify';\nimport {\n BatchBuffer,\n DEFAULT_MAX_BUFFER_SIZE,\n DEFAULT_REQUEST_TIMEOUT_MS,\n httpRequest,\n} from './batch-buffer';\nimport { protectSecrets, scrubError, scrubSecrets, urlSecrets } from './secret-config';\n\n/**\n * Azure AD tenant IDs are either a GUID or a verified domain (e.g. `contoso.onmicrosoft.com`).\n * This pattern is deliberately permissive on structure but strict on character\n * set — it rejects the breakout characters (`/`, `@`, `:`, `?`, `#`, whitespace)\n * that would let a hostile config smuggle a different host, path, or query into\n * the OAuth token URL.\n */\nconst AZURE_TENANT_RE = /^[a-z0-9][a-z0-9.-]{1,253}$/i;\n\nexport interface AzureMonitorTransportConfig {\n /** DCE (Data Collection Endpoint) URL, e.g. `https://<name>.ingest.monitor.azure.com`. */\n endpoint: string;\n /** Data Collection Rule immutable ID (from Azure portal). */\n ruleId: string;\n /** Stream name defined in the DCR, e.g. `'Custom-LogixiaLogs_CL'`. */\n streamName: string;\n /** Azure AD tenant ID for OAuth2 client-credentials flow. */\n tenantId?: string;\n /** Azure AD app (service principal) client ID. */\n clientId?: string;\n /** Azure AD app client secret. */\n clientSecret?: string;\n /** Number of entries to batch. @default 200 */\n batchSize?: number;\n /** Flush interval in ms. @default 5000 */\n flushIntervalMs?: number;\n /** Abort a request that has not finished after this many ms. @default 10000 */\n requestTimeoutMs?: number;\n /** Max buffered entries; the oldest are dropped past this. @default 10000 */\n maxBufferSize?: number;\n level?: string;\n}\n\nconst SEVERITY_MAP: Record<string, number> = {\n verbose: 0,\n trace: 0,\n debug: 1,\n info: 1,\n log: 1,\n warn: 2,\n warning: 2,\n error: 3,\n critical: 4,\n fatal: 4,\n};\n\n/**\n * Azure Monitor Logs Ingestion transport.\n */\nexport class AzureMonitorTransport implements IAsyncTransport {\n public readonly name = 'azure-monitor';\n public readonly batchSize: number;\n public readonly flushInterval: number;\n public readonly level: string | undefined;\n\n private readonly buffer: BatchBuffer<TransportLogEntry>;\n private readonly requestTimeoutMs: number;\n private flushTimer: NodeJS.Timeout | null = null;\n private accessToken: string | null = null;\n private tokenExpiry = 0;\n\n private readonly endpoint: string;\n private readonly ruleId: string;\n private readonly streamName: string;\n private readonly tenantId: string | undefined;\n private readonly clientId: string | undefined;\n private readonly clientSecret: string | undefined;\n\n constructor(config: AzureMonitorTransportConfig) {\n protectSecrets(this, ['clientSecret', 'accessToken']);\n this.endpoint = config.endpoint.replace(/\\/$/, '');\n this.ruleId = config.ruleId;\n this.streamName = config.streamName;\n this.tenantId = config.tenantId ?? process.env['AZURE_TENANT_ID'];\n this.clientId = config.clientId ?? process.env['AZURE_CLIENT_ID'];\n this.clientSecret = config.clientSecret ?? process.env['AZURE_CLIENT_SECRET'];\n this.batchSize = config.batchSize ?? 200;\n this.flushInterval = config.flushIntervalMs ?? 5000;\n this.level = config.level;\n this.requestTimeoutMs = config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n this.buffer = new BatchBuffer<TransportLogEntry>({\n name: 'AzureMonitorTransport',\n batchSize: this.batchSize,\n maxBufferSize: config.maxBufferSize ?? DEFAULT_MAX_BUFFER_SIZE,\n send: (entries) => this.sendEntries(entries),\n secrets: () => this.secretValues(),\n });\n\n this.flushTimer = setInterval(() => {\n this.flush().catch(() => {});\n }, this.flushInterval);\n if (this.flushTimer.unref) this.flushTimer.unref();\n }\n\n write(entry: TransportLogEntry): void {\n this.buffer.push(entry);\n this.buffer.flushIfFull();\n }\n\n flush(): Promise<void> {\n return this.buffer.flush();\n }\n\n /**\n * Flush remaining entries and stop the interval timer on shutdown. Without\n * this the manager's close() skipped the transport (close was undefined) and\n * buffered entries were lost on deploy. Waits for any in-flight send first.\n */\n async close(): Promise<void> {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n await this.buffer.close();\n }\n\n private toAzureRecord(entry: TransportLogEntry): Record<string, unknown> {\n return {\n TimeGenerated: entry.timestamp ?? new Date().toISOString(),\n SeverityLevel: SEVERITY_MAP[entry.level.toLowerCase()] ?? 1,\n Message: entry.message,\n AppName: entry.appName,\n Context: entry.context ?? '',\n TraceId: entry.traceId ?? '',\n Properties: stringifyForLog(entry.data ?? {}),\n };\n }\n\n private secretValues(token?: string): (string | undefined)[] {\n return [this.clientSecret, this.accessToken ?? undefined, token, ...urlSecrets(this.endpoint)];\n }\n\n private async getAccessToken(): Promise<string | null> {\n if (this.accessToken && Date.now() < this.tokenExpiry) return this.accessToken;\n\n if (!this.tenantId || !this.clientId || !this.clientSecret) {\n internalWarn(\n 'AzureMonitorTransport: missing credentials — set tenantId, clientId, clientSecret'\n );\n return null;\n }\n\n const body = new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: this.clientId,\n client_secret: this.clientSecret,\n scope: 'https://monitor.azure.com/.default',\n }).toString();\n\n const tenantId = this.tenantId;\n if (!AZURE_TENANT_RE.test(tenantId)) {\n internalWarn(\n `AzureMonitorTransport: refusing to request token — tenantId \"${tenantId}\" is not a valid GUID or domain`\n );\n return null;\n }\n\n const reqUrl = new URL(\n `https://login.microsoftonline.com/${encodeURIComponent(tenantId)}/oauth2/v2.0/token`\n );\n try {\n const res = await httpRequest({\n url: reqUrl,\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body,\n timeoutMs: this.requestTimeoutMs,\n label: 'Azure token request',\n secrets: () => this.secretValues(),\n });\n const parsed = JSON.parse(res.body) as { access_token?: string; expires_in?: number };\n if (!parsed.access_token) return null;\n this.accessToken = parsed.access_token;\n this.tokenExpiry = Date.now() + (parsed.expires_in ?? 3600) * 1000 - 60_000;\n return this.accessToken;\n } catch (err) {\n internalError('AzureMonitorTransport token request failed', err);\n return null;\n }\n }\n\n private async sendEntries(entries: TransportLogEntry[]): Promise<void> {\n const token = await this.getAccessToken();\n if (!token) throw new Error('AzureMonitorTransport: no access token available');\n\n const records = entries.map((e) => this.toAzureRecord(e));\n const body = stringifyForLog(records);\n let reqUrl: URL;\n try {\n // Build from the user-configured DCE endpoint; encodeURIComponent-ing the\n // ruleId/streamName stops a hostile config from smuggling extra path\n // segments or query params into the request.\n reqUrl = new URL(\n `dataCollectionRules/${encodeURIComponent(this.ruleId)}/streams/${encodeURIComponent(this.streamName)}?api-version=2023-01-01`,\n this.endpoint.endsWith('/') ? this.endpoint : `${this.endpoint}/`\n );\n } catch (error) {\n internalError(\n `AzureMonitorTransport: invalid endpoint \"${scrubSecrets(this.endpoint, urlSecrets(this.endpoint))}\"`,\n scrubError(error, urlSecrets(this.endpoint))\n );\n return;\n }\n if (reqUrl.protocol !== 'https:') {\n internalError(`AzureMonitorTransport: endpoint must use https (got ${reqUrl.protocol})`);\n return;\n }\n\n await httpRequest({\n url: reqUrl,\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n body,\n timeoutMs: this.requestTimeoutMs,\n label: 'Azure Monitor API',\n secrets: () => this.secretValues(token),\n });\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,4 @@
1
- import { p as TransportLogEntry, s as IAsyncTransport } from "./transport.types-CtNr3D7S.mjs";
2
-
3
- //#region src/transports/azure-monitor.transport.d.ts
4
-
1
+ import { p as TransportLogEntry, s as IAsyncTransport } from "./transport.types-BJVL1QQl.js";
5
2
  interface AzureMonitorTransportConfig {
6
3
  /** DCE (Data Collection Endpoint) URL, e.g. `https://<name>.ingest.monitor.azure.com`. */
7
4
  endpoint: string;
@@ -54,9 +51,9 @@ declare class AzureMonitorTransport implements IAsyncTransport {
54
51
  */
55
52
  close(): Promise<void>;
56
53
  private toAzureRecord;
54
+ private secretValues;
57
55
  private getAccessToken;
58
56
  private sendEntries;
59
57
  }
60
- //#endregion
61
58
  export { AzureMonitorTransportConfig as n, AzureMonitorTransport as t };
62
- //# sourceMappingURL=azure-monitor.transport-D5wQEH04.d.mts.map
59
+ //# sourceMappingURL=azure-monitor.transport-DV03Z5P4.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-monitor.transport-DV03Z5P4.d.ts","names":[],"sources":["../src/transports/azure-monitor.transport.ts"],"mappings":";UAmDiB;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;EACA;;;;;cAmBW,iCAAiC;WAC5B;WACA;WACA;WACA;mBAEC;mBACA;UACT;UACA;UACA;mBAES;mBACA;mBACA;mBACA;mBACA;mBACA;EAEL,YAAA,QAAQ;EA0BpB,MAAM,OAAO;EAKb,SAAS;;;;;;EASH,SAAS;UAQP;UAYA;UAIM;UAgDA"}
package/dist/azure.d.mts CHANGED
@@ -1,3 +1,2 @@
1
- import "./transport.types-CtNr3D7S.mjs";
2
- import { n as AzureMonitorTransportConfig, t as AzureMonitorTransport } from "./azure-monitor.transport-D5wQEH04.mjs";
1
+ import { n as AzureMonitorTransportConfig, t as AzureMonitorTransport } from "./azure-monitor.transport-C7kYyZUW.mjs";
3
2
  export { AzureMonitorTransport, AzureMonitorTransportConfig };
package/dist/azure.d.ts CHANGED
@@ -1,3 +1,2 @@
1
- import "./transport.types-DqVLZTyf.js";
2
- import { n as AzureMonitorTransportConfig, t as AzureMonitorTransport } from "./azure-monitor.transport-BDFO4F-i.js";
1
+ import { n as AzureMonitorTransportConfig, t as AzureMonitorTransport } from "./azure-monitor.transport-DV03Z5P4.js";
3
2
  export { AzureMonitorTransport, AzureMonitorTransportConfig };
package/dist/azure.js CHANGED
@@ -1,6 +1,3 @@
1
- require('./internal-log-BUJYMZbE.js');
2
- require('./safe-stringify-DWo3aZp_.js');
3
- require('./batch-buffer-BY-mRWIK.js');
4
- const require_azure_monitor_transport = require('./azure-monitor.transport-CrvfHd9C.js');
5
-
6
- exports.AzureMonitorTransport = require_azure_monitor_transport.AzureMonitorTransport;
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_azure_monitor_transport = require("./azure-monitor.transport-CwbOLZHB.js");
3
+ exports.AzureMonitorTransport = require_azure_monitor_transport.AzureMonitorTransport;
package/dist/azure.mjs CHANGED
@@ -1,6 +1 @@
1
- import "./internal-log-Cm8SOWSV.mjs";
2
- import "./safe-stringify-DJ66tW5I.mjs";
3
- import "./batch-buffer-PGvSgbmd.mjs";
4
- import { t as AzureMonitorTransport } from "./azure-monitor.transport-CHnjVRF-.mjs";
5
-
6
- export { AzureMonitorTransport };
1
+ export { t as AzureMonitorTransport } from "./azure-monitor.transport-BPbgjATu.mjs";
@@ -1,8 +1,18 @@
1
- import { r as internalWarn, t as internalError } from "./internal-log-Cm8SOWSV.mjs";
1
+ import { r as internalWarn, t as internalError } from "./internal-log-uCSd1PMc.mjs";
2
+ import { a as scrubbing, r as scrubError } from "./secret-config-BegMLkYl.mjs";
2
3
  import * as http from "node:http";
3
4
  import * as https from "node:https";
4
-
5
- //#region src/transports/batch-buffer.ts
5
+ // src/transports/batch-buffer.ts
6
+ /**
7
+ * Shared batching core for the network transports (OTLP, CloudWatch, GCP, Azure).
8
+ *
9
+ * - one send in flight at a time; flush() and close() join it instead of
10
+ * racing it, so close() cannot return while a request is still on the wire
11
+ * - a failed batch goes back to the front in its original order
12
+ * - 4xx responses other than 429 drop the batch with a warning instead of
13
+ * retrying a request the server will never accept
14
+ * - the buffer is capped; when full the oldest entries are dropped
15
+ */
6
16
  const DEFAULT_REQUEST_TIMEOUT_MS = 1e4;
7
17
  const DEFAULT_MAX_BUFFER_SIZE = 1e4;
8
18
  const WARN_INTERVAL_MS = 1e4;
@@ -22,6 +32,9 @@ function isPermanentHttpError(err) {
22
32
  }
23
33
  /** One request with a hard timeout. Rejects with HttpError on any non-2xx status. */
24
34
  function httpRequest(opts) {
35
+ return sendRequest(opts).catch(scrubbing(opts.secrets ?? (() => [])));
36
+ }
37
+ function sendRequest(opts) {
25
38
  const { url, method = "POST", headers = {}, body, timeoutMs, label } = opts;
26
39
  const transport = url.protocol === "http:" ? http : https;
27
40
  return new Promise((resolve, reject) => {
@@ -99,6 +112,8 @@ var BatchBuffer = class {
99
112
  await this.opts.send(batch);
100
113
  this.failures = 0;
101
114
  } catch (err) {
115
+ var _this$opts$secrets, _this$opts;
116
+ scrubError(err, ((_this$opts$secrets = (_this$opts = this.opts).secrets) === null || _this$opts$secrets === void 0 ? void 0 : _this$opts$secrets.call(_this$opts)) ?? []);
102
117
  if (!(this.opts.shouldRetry ? this.opts.shouldRetry(err) : !isPermanentHttpError(err))) {
103
118
  internalWarn(`${this.opts.name}: dropping ${batch.length} entr${batch.length === 1 ? "y" : "ies"} the server rejected (${err instanceof Error ? err.message : String(err)})`);
104
119
  continue;
@@ -113,7 +128,7 @@ var BatchBuffer = class {
113
128
  }
114
129
  }
115
130
  enforceCap() {
116
- const max = this.opts.maxBufferSize ?? DEFAULT_MAX_BUFFER_SIZE;
131
+ const max = this.opts.maxBufferSize ?? 1e4;
117
132
  const excess = this.items.length - max;
118
133
  if (excess <= 0) return;
119
134
  this.items.splice(0, excess);
@@ -126,7 +141,6 @@ var BatchBuffer = class {
126
141
  }
127
142
  }
128
143
  };
129
-
130
- //#endregion
131
144
  export { httpRequest as a, HttpError as i, DEFAULT_MAX_BUFFER_SIZE as n, isPermanentHttpError as o, DEFAULT_REQUEST_TIMEOUT_MS as r, BatchBuffer as t };
132
- //# sourceMappingURL=batch-buffer-PGvSgbmd.mjs.map
145
+
146
+ //# sourceMappingURL=batch-buffer-0fgLmIPn.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-buffer-0fgLmIPn.mjs","names":[],"sources":["../src/transports/batch-buffer.ts"],"sourcesContent":["/**\n * Shared batching core for the network transports (OTLP, CloudWatch, GCP, Azure).\n *\n * - one send in flight at a time; flush() and close() join it instead of\n * racing it, so close() cannot return while a request is still on the wire\n * - a failed batch goes back to the front in its original order\n * - 4xx responses other than 429 drop the batch with a warning instead of\n * retrying a request the server will never accept\n * - the buffer is capped; when full the oldest entries are dropped\n */\n\nimport * as http from 'node:http';\nimport * as https from 'node:https';\n\nimport { internalError, internalWarn } from '../utils/internal-log';\nimport { scrubbing, scrubError } from './secret-config';\n\nexport const DEFAULT_REQUEST_TIMEOUT_MS = 10_000;\nexport const DEFAULT_MAX_BUFFER_SIZE = 10_000;\nconst WARN_INTERVAL_MS = 10_000;\nconst MAX_ERROR_BODY = 500;\nconst MAX_BACKOFF_MS = 30_000;\n\nexport class HttpError extends Error {\n constructor(\n public readonly status: number,\n public readonly body: string,\n label: string\n ) {\n const detail = body ? `: ${body.slice(0, MAX_ERROR_BODY)}` : '';\n super(`${label} returned HTTP ${status}${detail}`);\n this.name = 'HttpError';\n }\n}\n\nexport function isPermanentHttpError(err: unknown): boolean {\n return err instanceof HttpError && err.status >= 400 && err.status < 500 && err.status !== 429;\n}\n\nexport interface HttpRequestOptions {\n url: URL;\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n timeoutMs: number;\n label: string;\n /** Secret values to scrub from any error this request raises. URL userinfo is always scrubbed. */\n secrets?: () => (string | undefined)[];\n}\n\nexport interface HttpResult {\n status: number;\n body: string;\n}\n\n/** One request with a hard timeout. Rejects with HttpError on any non-2xx status. */\nexport function httpRequest(opts: HttpRequestOptions): Promise<HttpResult> {\n return sendRequest(opts).catch(scrubbing(opts.secrets ?? (() => [])));\n}\n\nfunction sendRequest(opts: HttpRequestOptions): Promise<HttpResult> {\n const { url, method = 'POST', headers = {}, body, timeoutMs, label } = opts;\n const transport = url.protocol === 'http:' ? http : https;\n return new Promise<HttpResult>((resolve, reject) => {\n const req = transport.request(\n {\n protocol: url.protocol,\n hostname: url.hostname,\n port: url.port || undefined,\n path: `${url.pathname}${url.search}`,\n method,\n headers:\n body === undefined ? headers : { ...headers, 'Content-Length': Buffer.byteLength(body) },\n },\n (res) => {\n let raw = '';\n res.on('data', (c: Buffer) => (raw += c.toString()));\n res.on('end', () => {\n const status = res.statusCode ?? 0;\n if (status >= 200 && status < 300) resolve({ status, body: raw });\n else reject(new HttpError(status, raw, label));\n });\n res.on('error', reject);\n }\n );\n req.setTimeout(timeoutMs, () => {\n req.destroy(new Error(`${label} timed out after ${timeoutMs}ms`));\n });\n req.on('error', reject);\n if (body !== undefined) req.write(body);\n req.end();\n });\n}\n\nexport interface BatchBufferOptions<T> {\n name: string;\n batchSize: number;\n maxBufferSize?: number;\n send: (items: T[]) => Promise<void>;\n /** Secret values to scrub from send errors before they are stored or logged. */\n secrets?: () => (string | undefined)[];\n /** Overrides the default drop-on-4xx rule. Return true to keep and retry the batch. */\n shouldRetry?: (err: unknown) => boolean;\n}\n\nexport class BatchBuffer<T> {\n private items: T[] = [];\n private inFlight: Promise<void> | undefined;\n private dropped = 0;\n private lastDropWarn = 0;\n private failures = 0;\n private retryAfter = 0;\n\n constructor(private readonly opts: BatchBufferOptions<T>) {}\n\n get length(): number {\n return this.items.length;\n }\n\n get batchSize(): number {\n return this.opts.batchSize;\n }\n\n push(item: T): void {\n this.items.push(item);\n this.enforceCap();\n }\n\n /** Threshold flush for write(): skipped while a send is running or the endpoint is backing off. */\n flushIfFull(): void {\n if (this.items.length < this.opts.batchSize || this.inFlight || Date.now() < this.retryAfter) {\n return;\n }\n this.flush().catch(() => {});\n }\n\n flush(): Promise<void> {\n if (!this.inFlight) {\n this.inFlight = this.drain().finally(() => {\n this.inFlight = undefined;\n });\n }\n return this.inFlight;\n }\n\n /** Flush up to `attempts` times, then report whatever is still undelivered. */\n async close(attempts = 3): Promise<void> {\n await this.inFlight;\n for (let i = 0; i < attempts && this.items.length > 0; i += 1) {\n await this.flush();\n }\n if (this.items.length > 0) {\n internalError(\n `${this.opts.name} closing with ${this.items.length} undelivered entr${this.items.length === 1 ? 'y' : 'ies'}`\n );\n }\n }\n\n private async drain(): Promise<void> {\n while (this.items.length > 0) {\n const batch = this.items.splice(0, this.opts.batchSize);\n try {\n await this.opts.send(batch);\n this.failures = 0;\n } catch (err) {\n scrubError(err, this.opts.secrets?.() ?? []);\n const retry = this.opts.shouldRetry\n ? this.opts.shouldRetry(err)\n : !isPermanentHttpError(err);\n if (!retry) {\n internalWarn(\n `${this.opts.name}: dropping ${batch.length} entr${batch.length === 1 ? 'y' : 'ies'} the server rejected (${err instanceof Error ? err.message : String(err)})`\n );\n continue;\n }\n internalError(`${this.opts.name} flush error`, err);\n this.items.unshift(...batch);\n this.enforceCap();\n this.failures += 1;\n this.retryAfter = Date.now() + Math.min(MAX_BACKOFF_MS, 1000 * 2 ** (this.failures - 1));\n return;\n }\n }\n }\n\n private enforceCap(): void {\n const max = this.opts.maxBufferSize ?? DEFAULT_MAX_BUFFER_SIZE;\n const excess = this.items.length - max;\n if (excess <= 0) return;\n this.items.splice(0, excess);\n this.dropped += excess;\n const now = Date.now();\n if (now - this.lastDropWarn >= WARN_INTERVAL_MS) {\n internalWarn(\n `${this.opts.name}: buffer full (${max}), dropped ${this.dropped} oldest entr${this.dropped === 1 ? 'y' : 'ies'}`\n );\n this.dropped = 0;\n this.lastDropWarn = now;\n }\n }\n}\n"],"mappings":"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"}
@@ -1,11 +1,20 @@
1
- const require_chunk = require('./chunk-nOFOJqeH.js');
2
- const require_internal_log = require('./internal-log-BUJYMZbE.js');
1
+ const require_secret_config = require("./secret-config-CBZBs0p1.js");
2
+ const require_internal_log = require("./internal-log-b0Vp4qrB.js");
3
3
  let node_http = require("node:http");
4
- node_http = require_chunk.__toESM(node_http);
4
+ node_http = require_secret_config.__toESM(node_http);
5
5
  let node_https = require("node:https");
6
- node_https = require_chunk.__toESM(node_https);
7
-
8
- //#region src/transports/batch-buffer.ts
6
+ node_https = require_secret_config.__toESM(node_https);
7
+ // src/transports/batch-buffer.ts
8
+ /**
9
+ * Shared batching core for the network transports (OTLP, CloudWatch, GCP, Azure).
10
+ *
11
+ * - one send in flight at a time; flush() and close() join it instead of
12
+ * racing it, so close() cannot return while a request is still on the wire
13
+ * - a failed batch goes back to the front in its original order
14
+ * - 4xx responses other than 429 drop the batch with a warning instead of
15
+ * retrying a request the server will never accept
16
+ * - the buffer is capped; when full the oldest entries are dropped
17
+ */
9
18
  const DEFAULT_REQUEST_TIMEOUT_MS = 1e4;
10
19
  const DEFAULT_MAX_BUFFER_SIZE = 1e4;
11
20
  const WARN_INTERVAL_MS = 1e4;
@@ -25,6 +34,9 @@ function isPermanentHttpError(err) {
25
34
  }
26
35
  /** One request with a hard timeout. Rejects with HttpError on any non-2xx status. */
27
36
  function httpRequest(opts) {
37
+ return sendRequest(opts).catch(require_secret_config.scrubbing(opts.secrets ?? (() => [])));
38
+ }
39
+ function sendRequest(opts) {
28
40
  const { url, method = "POST", headers = {}, body, timeoutMs, label } = opts;
29
41
  const transport = url.protocol === "http:" ? node_http : node_https;
30
42
  return new Promise((resolve, reject) => {
@@ -102,6 +114,8 @@ var BatchBuffer = class {
102
114
  await this.opts.send(batch);
103
115
  this.failures = 0;
104
116
  } catch (err) {
117
+ var _this$opts$secrets, _this$opts;
118
+ require_secret_config.scrubError(err, ((_this$opts$secrets = (_this$opts = this.opts).secrets) === null || _this$opts$secrets === void 0 ? void 0 : _this$opts$secrets.call(_this$opts)) ?? []);
105
119
  if (!(this.opts.shouldRetry ? this.opts.shouldRetry(err) : !isPermanentHttpError(err))) {
106
120
  require_internal_log.internalWarn(`${this.opts.name}: dropping ${batch.length} entr${batch.length === 1 ? "y" : "ies"} the server rejected (${err instanceof Error ? err.message : String(err)})`);
107
121
  continue;
@@ -116,7 +130,7 @@ var BatchBuffer = class {
116
130
  }
117
131
  }
118
132
  enforceCap() {
119
- const max = this.opts.maxBufferSize ?? DEFAULT_MAX_BUFFER_SIZE;
133
+ const max = this.opts.maxBufferSize ?? 1e4;
120
134
  const excess = this.items.length - max;
121
135
  if (excess <= 0) return;
122
136
  this.items.splice(0, excess);
@@ -129,42 +143,41 @@ var BatchBuffer = class {
129
143
  }
130
144
  }
131
145
  };
132
-
133
- //#endregion
134
- Object.defineProperty(exports, 'BatchBuffer', {
135
- enumerable: true,
136
- get: function () {
137
- return BatchBuffer;
138
- }
146
+ Object.defineProperty(exports, "BatchBuffer", {
147
+ enumerable: true,
148
+ get: function() {
149
+ return BatchBuffer;
150
+ }
139
151
  });
140
- Object.defineProperty(exports, 'DEFAULT_MAX_BUFFER_SIZE', {
141
- enumerable: true,
142
- get: function () {
143
- return DEFAULT_MAX_BUFFER_SIZE;
144
- }
152
+ Object.defineProperty(exports, "DEFAULT_MAX_BUFFER_SIZE", {
153
+ enumerable: true,
154
+ get: function() {
155
+ return DEFAULT_MAX_BUFFER_SIZE;
156
+ }
145
157
  });
146
- Object.defineProperty(exports, 'DEFAULT_REQUEST_TIMEOUT_MS', {
147
- enumerable: true,
148
- get: function () {
149
- return DEFAULT_REQUEST_TIMEOUT_MS;
150
- }
158
+ Object.defineProperty(exports, "DEFAULT_REQUEST_TIMEOUT_MS", {
159
+ enumerable: true,
160
+ get: function() {
161
+ return DEFAULT_REQUEST_TIMEOUT_MS;
162
+ }
151
163
  });
152
- Object.defineProperty(exports, 'HttpError', {
153
- enumerable: true,
154
- get: function () {
155
- return HttpError;
156
- }
164
+ Object.defineProperty(exports, "HttpError", {
165
+ enumerable: true,
166
+ get: function() {
167
+ return HttpError;
168
+ }
157
169
  });
158
- Object.defineProperty(exports, 'httpRequest', {
159
- enumerable: true,
160
- get: function () {
161
- return httpRequest;
162
- }
170
+ Object.defineProperty(exports, "httpRequest", {
171
+ enumerable: true,
172
+ get: function() {
173
+ return httpRequest;
174
+ }
163
175
  });
164
- Object.defineProperty(exports, 'isPermanentHttpError', {
165
- enumerable: true,
166
- get: function () {
167
- return isPermanentHttpError;
168
- }
176
+ Object.defineProperty(exports, "isPermanentHttpError", {
177
+ enumerable: true,
178
+ get: function() {
179
+ return isPermanentHttpError;
180
+ }
169
181
  });
170
- //# sourceMappingURL=batch-buffer-BY-mRWIK.js.map
182
+
183
+ //# sourceMappingURL=batch-buffer-DT4gdXmf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-buffer-DT4gdXmf.js","names":["scrubbing","http","https"],"sources":["../src/transports/batch-buffer.ts"],"sourcesContent":["/**\n * Shared batching core for the network transports (OTLP, CloudWatch, GCP, Azure).\n *\n * - one send in flight at a time; flush() and close() join it instead of\n * racing it, so close() cannot return while a request is still on the wire\n * - a failed batch goes back to the front in its original order\n * - 4xx responses other than 429 drop the batch with a warning instead of\n * retrying a request the server will never accept\n * - the buffer is capped; when full the oldest entries are dropped\n */\n\nimport * as http from 'node:http';\nimport * as https from 'node:https';\n\nimport { internalError, internalWarn } from '../utils/internal-log';\nimport { scrubbing, scrubError } from './secret-config';\n\nexport const DEFAULT_REQUEST_TIMEOUT_MS = 10_000;\nexport const DEFAULT_MAX_BUFFER_SIZE = 10_000;\nconst WARN_INTERVAL_MS = 10_000;\nconst MAX_ERROR_BODY = 500;\nconst MAX_BACKOFF_MS = 30_000;\n\nexport class HttpError extends Error {\n constructor(\n public readonly status: number,\n public readonly body: string,\n label: string\n ) {\n const detail = body ? `: ${body.slice(0, MAX_ERROR_BODY)}` : '';\n super(`${label} returned HTTP ${status}${detail}`);\n this.name = 'HttpError';\n }\n}\n\nexport function isPermanentHttpError(err: unknown): boolean {\n return err instanceof HttpError && err.status >= 400 && err.status < 500 && err.status !== 429;\n}\n\nexport interface HttpRequestOptions {\n url: URL;\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n timeoutMs: number;\n label: string;\n /** Secret values to scrub from any error this request raises. URL userinfo is always scrubbed. */\n secrets?: () => (string | undefined)[];\n}\n\nexport interface HttpResult {\n status: number;\n body: string;\n}\n\n/** One request with a hard timeout. Rejects with HttpError on any non-2xx status. */\nexport function httpRequest(opts: HttpRequestOptions): Promise<HttpResult> {\n return sendRequest(opts).catch(scrubbing(opts.secrets ?? (() => [])));\n}\n\nfunction sendRequest(opts: HttpRequestOptions): Promise<HttpResult> {\n const { url, method = 'POST', headers = {}, body, timeoutMs, label } = opts;\n const transport = url.protocol === 'http:' ? http : https;\n return new Promise<HttpResult>((resolve, reject) => {\n const req = transport.request(\n {\n protocol: url.protocol,\n hostname: url.hostname,\n port: url.port || undefined,\n path: `${url.pathname}${url.search}`,\n method,\n headers:\n body === undefined ? headers : { ...headers, 'Content-Length': Buffer.byteLength(body) },\n },\n (res) => {\n let raw = '';\n res.on('data', (c: Buffer) => (raw += c.toString()));\n res.on('end', () => {\n const status = res.statusCode ?? 0;\n if (status >= 200 && status < 300) resolve({ status, body: raw });\n else reject(new HttpError(status, raw, label));\n });\n res.on('error', reject);\n }\n );\n req.setTimeout(timeoutMs, () => {\n req.destroy(new Error(`${label} timed out after ${timeoutMs}ms`));\n });\n req.on('error', reject);\n if (body !== undefined) req.write(body);\n req.end();\n });\n}\n\nexport interface BatchBufferOptions<T> {\n name: string;\n batchSize: number;\n maxBufferSize?: number;\n send: (items: T[]) => Promise<void>;\n /** Secret values to scrub from send errors before they are stored or logged. */\n secrets?: () => (string | undefined)[];\n /** Overrides the default drop-on-4xx rule. Return true to keep and retry the batch. */\n shouldRetry?: (err: unknown) => boolean;\n}\n\nexport class BatchBuffer<T> {\n private items: T[] = [];\n private inFlight: Promise<void> | undefined;\n private dropped = 0;\n private lastDropWarn = 0;\n private failures = 0;\n private retryAfter = 0;\n\n constructor(private readonly opts: BatchBufferOptions<T>) {}\n\n get length(): number {\n return this.items.length;\n }\n\n get batchSize(): number {\n return this.opts.batchSize;\n }\n\n push(item: T): void {\n this.items.push(item);\n this.enforceCap();\n }\n\n /** Threshold flush for write(): skipped while a send is running or the endpoint is backing off. */\n flushIfFull(): void {\n if (this.items.length < this.opts.batchSize || this.inFlight || Date.now() < this.retryAfter) {\n return;\n }\n this.flush().catch(() => {});\n }\n\n flush(): Promise<void> {\n if (!this.inFlight) {\n this.inFlight = this.drain().finally(() => {\n this.inFlight = undefined;\n });\n }\n return this.inFlight;\n }\n\n /** Flush up to `attempts` times, then report whatever is still undelivered. */\n async close(attempts = 3): Promise<void> {\n await this.inFlight;\n for (let i = 0; i < attempts && this.items.length > 0; i += 1) {\n await this.flush();\n }\n if (this.items.length > 0) {\n internalError(\n `${this.opts.name} closing with ${this.items.length} undelivered entr${this.items.length === 1 ? 'y' : 'ies'}`\n );\n }\n }\n\n private async drain(): Promise<void> {\n while (this.items.length > 0) {\n const batch = this.items.splice(0, this.opts.batchSize);\n try {\n await this.opts.send(batch);\n this.failures = 0;\n } catch (err) {\n scrubError(err, this.opts.secrets?.() ?? []);\n const retry = this.opts.shouldRetry\n ? this.opts.shouldRetry(err)\n : !isPermanentHttpError(err);\n if (!retry) {\n internalWarn(\n `${this.opts.name}: dropping ${batch.length} entr${batch.length === 1 ? 'y' : 'ies'} the server rejected (${err instanceof Error ? err.message : String(err)})`\n );\n continue;\n }\n internalError(`${this.opts.name} flush error`, err);\n this.items.unshift(...batch);\n this.enforceCap();\n this.failures += 1;\n this.retryAfter = Date.now() + Math.min(MAX_BACKOFF_MS, 1000 * 2 ** (this.failures - 1));\n return;\n }\n }\n }\n\n private enforceCap(): void {\n const max = this.opts.maxBufferSize ?? DEFAULT_MAX_BUFFER_SIZE;\n const excess = this.items.length - max;\n if (excess <= 0) return;\n this.items.splice(0, excess);\n this.dropped += excess;\n const now = Date.now();\n if (now - this.lastDropWarn >= WARN_INTERVAL_MS) {\n internalWarn(\n `${this.opts.name}: buffer full (${max}), dropped ${this.dropped} oldest entr${this.dropped === 1 ? 'y' : 'ies'}`\n );\n this.dropped = 0;\n this.lastDropWarn = now;\n }\n }\n}\n"],"mappings":"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"}