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.
- package/README.md +117 -44
- package/dist/async-context-B05ArHgM.mjs +134 -0
- package/dist/async-context-B05ArHgM.mjs.map +1 -0
- package/dist/async-context-DTQgi8f7.js +150 -0
- package/dist/async-context-DTQgi8f7.js.map +1 -0
- package/dist/{azure-monitor.transport-CHnjVRF-.mjs → azure-monitor.transport-BPbgjATu.mjs} +27 -15
- package/dist/azure-monitor.transport-BPbgjATu.mjs.map +1 -0
- package/dist/{azure-monitor.transport-BDFO4F-i.d.ts → azure-monitor.transport-C7kYyZUW.d.mts} +3 -6
- package/dist/azure-monitor.transport-C7kYyZUW.d.mts.map +1 -0
- package/dist/{azure-monitor.transport-CrvfHd9C.js → azure-monitor.transport-CwbOLZHB.js} +32 -20
- package/dist/azure-monitor.transport-CwbOLZHB.js.map +1 -0
- package/dist/{azure-monitor.transport-D5wQEH04.d.mts → azure-monitor.transport-DV03Z5P4.d.ts} +3 -6
- package/dist/azure-monitor.transport-DV03Z5P4.d.ts.map +1 -0
- package/dist/azure.d.mts +1 -2
- package/dist/azure.d.ts +1 -2
- package/dist/azure.js +3 -6
- package/dist/azure.mjs +1 -6
- package/dist/{batch-buffer-PGvSgbmd.mjs → batch-buffer-0fgLmIPn.mjs} +21 -7
- package/dist/batch-buffer-0fgLmIPn.mjs.map +1 -0
- package/dist/{batch-buffer-BY-mRWIK.js → batch-buffer-DT4gdXmf.js} +53 -40
- package/dist/batch-buffer-DT4gdXmf.js.map +1 -0
- package/dist/browser.d.mts +52 -23
- package/dist/browser.d.mts.map +1 -1
- package/dist/browser.d.ts +52 -23
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +460 -62
- package/dist/browser.js.map +1 -1
- package/dist/browser.mjs +461 -65
- package/dist/browser.mjs.map +1 -1
- package/dist/{nestjs-extras-ImbuDhs1.mjs → builder-D70z6kjj.mjs} +279 -965
- package/dist/builder-D70z6kjj.mjs.map +1 -0
- package/dist/{nestjs-extras-DnJ6vrIC.js → builder-M7NoaugM.js} +421 -1177
- package/dist/builder-M7NoaugM.js.map +1 -0
- package/dist/cli/index.js +86 -67
- package/dist/cloudwatch.d.mts +1 -2
- package/dist/cloudwatch.d.ts +1 -2
- package/dist/cloudwatch.js +3 -7
- package/dist/cloudwatch.mjs +1 -7
- package/dist/{cloudwatch.transport-BO1ahxw-.js → cloudwatch.transport-B2wKQFF7.js} +61 -36
- package/dist/cloudwatch.transport-B2wKQFF7.js.map +1 -0
- package/dist/{cloudwatch.transport-DZ6ies7g.mjs → cloudwatch.transport-BTvYfLs9.mjs} +54 -28
- package/dist/cloudwatch.transport-BTvYfLs9.mjs.map +1 -0
- package/dist/{cloudwatch.transport-B00st6Xv.d.ts → cloudwatch.transport-Bf7L4I59.d.ts} +2 -6
- package/dist/cloudwatch.transport-Bf7L4I59.d.ts.map +1 -0
- package/dist/{cloudwatch.transport-Blc7Gtxt.d.mts → cloudwatch.transport-Rj4yTpRn.d.mts} +2 -6
- package/dist/cloudwatch.transport-Rj4yTpRn.d.mts.map +1 -0
- package/dist/{coerce.utils-Cu6IUTgX.mjs → coerce.utils-B_rEudCn.mjs} +3 -4
- package/dist/{coerce.utils-Cu6IUTgX.mjs.map → coerce.utils-B_rEudCn.mjs.map} +1 -1
- package/dist/{coerce.utils-B-LilukN.js → coerce.utils-C1C5sIX0.js} +8 -10
- package/dist/{coerce.utils-B-LilukN.js.map → coerce.utils-C1C5sIX0.js.map} +1 -1
- package/dist/correlation.d.mts +13 -16
- package/dist/correlation.d.mts.map +1 -1
- package/dist/correlation.d.ts +13 -16
- package/dist/correlation.d.ts.map +1 -1
- package/dist/correlation.js +58 -9
- package/dist/correlation.js.map +1 -1
- package/dist/correlation.mjs +56 -6
- package/dist/correlation.mjs.map +1 -1
- package/dist/{entry-fields-BJkuPnIg.mjs → entry-fields-CGuvT2R0.mjs} +5 -6
- package/dist/entry-fields-CGuvT2R0.mjs.map +1 -0
- package/dist/{entry-fields-BvOLFlJ4.js → entry-fields-RLd1jCoR.js} +10 -12
- package/dist/entry-fields-RLd1jCoR.js.map +1 -0
- package/dist/gcp.d.mts +1 -2
- package/dist/gcp.d.ts +1 -2
- package/dist/gcp.js +3 -7
- package/dist/gcp.mjs +1 -7
- package/dist/{gcp.transport-m4fVw0b1.d.ts → gcp.transport-C5D72b1g.d.mts} +3 -6
- package/dist/gcp.transport-C5D72b1g.d.mts.map +1 -0
- package/dist/{gcp.transport-zzNyIoih.d.mts → gcp.transport-CFQfdAOK.d.ts} +3 -6
- package/dist/gcp.transport-CFQfdAOK.d.ts.map +1 -0
- package/dist/{gcp.transport-DBX5TPIy.mjs → gcp.transport-CGKopAhQ.mjs} +55 -16
- package/dist/gcp.transport-CGKopAhQ.mjs.map +1 -0
- package/dist/{gcp.transport-CHV8MGgz.js → gcp.transport-KZe9hCAR.js} +60 -22
- package/dist/gcp.transport-KZe9hCAR.js.map +1 -0
- package/dist/{index-nZEeCr3X.d.ts → index-DwozbmB4.d.ts} +3 -8
- package/dist/index-DwozbmB4.d.ts.map +1 -0
- package/dist/{index-BPwEisy4.d.mts → index-xqaJtAZn.d.mts} +3 -8
- package/dist/index-xqaJtAZn.d.mts.map +1 -0
- package/dist/index.d.mts +141 -203
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +140 -202
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +196 -381
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +145 -294
- package/dist/index.mjs.map +1 -1
- package/dist/internal-log-b0Vp4qrB.js +183 -0
- package/dist/internal-log-b0Vp4qrB.js.map +1 -0
- package/dist/internal-log-uCSd1PMc.mjs +142 -0
- package/dist/internal-log-uCSd1PMc.mjs.map +1 -0
- package/dist/logitron-logger-D2B75Oc7.d.ts +365 -0
- package/dist/logitron-logger-D2B75Oc7.d.ts.map +1 -0
- package/dist/logitron-logger-oEd6wNhf.d.mts +365 -0
- package/dist/logitron-logger-oEd6wNhf.d.mts.map +1 -0
- package/dist/middleware.d.mts +10 -12
- package/dist/middleware.d.mts.map +1 -1
- package/dist/middleware.d.ts +10 -12
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +16 -47
- package/dist/middleware.js.map +1 -1
- package/dist/middleware.mjs +13 -45
- package/dist/middleware.mjs.map +1 -1
- package/dist/nest.d.mts +467 -10
- package/dist/nest.d.mts.map +1 -1
- package/dist/nest.d.ts +467 -10
- package/dist/nest.d.ts.map +1 -1
- package/dist/nest.js +889 -43
- package/dist/nest.js.map +1 -0
- package/dist/nest.mjs +850 -9
- package/dist/nest.mjs.map +1 -0
- package/dist/{trace.utils-CvXgaiQT.mjs → request-trace-C_fvIDv4.mjs} +44 -9
- package/dist/request-trace-C_fvIDv4.mjs.map +1 -0
- package/dist/{trace.utils-DpBOLDtq.js → request-trace-wTJdKp6-.js} +121 -77
- package/dist/request-trace-wTJdKp6-.js.map +1 -0
- package/dist/rolldown-runtime-D3PmRqjj.mjs +4 -0
- package/dist/{safe-stringify-DJ66tW5I.mjs → safe-stringify-BMRl3EX3.mjs} +3 -4
- package/dist/safe-stringify-BMRl3EX3.mjs.map +1 -0
- package/dist/{safe-stringify-DWo3aZp_.js → safe-stringify-DLz1Kz3o.js} +23 -25
- package/dist/safe-stringify-DLz1Kz3o.js.map +1 -0
- package/dist/{search-CHUZPl0h.d.ts → search-BH33XhuU.d.mts} +2 -22
- package/dist/search-BH33XhuU.d.mts.map +1 -0
- package/dist/{search-DjXSn6v5.mjs → search-CWMVYC-R.mjs} +34 -41
- package/dist/search-CWMVYC-R.mjs.map +1 -0
- package/dist/{search-BfBzDIT9.d.mts → search-CazwyX5Z.d.ts} +2 -22
- package/dist/search-CazwyX5Z.d.ts.map +1 -0
- package/dist/{search-B0MH1SJJ.js → search-DUfWuzFP.js} +64 -71
- package/dist/search-DUfWuzFP.js.map +1 -0
- package/dist/search.d.mts +2 -4
- package/dist/search.d.ts +2 -4
- package/dist/search.js +3 -4
- package/dist/search.mjs +1 -4
- package/dist/secret-config-BegMLkYl.mjs +209 -0
- package/dist/secret-config-BegMLkYl.mjs.map +1 -0
- package/dist/secret-config-CBZBs0p1.js +271 -0
- package/dist/secret-config-CBZBs0p1.js.map +1 -0
- package/dist/slack.transport-Ce96JBDk.mjs +824 -0
- package/dist/slack.transport-Ce96JBDk.mjs.map +1 -0
- package/dist/slack.transport-Dlx3xvb7.js +847 -0
- package/dist/slack.transport-Dlx3xvb7.js.map +1 -0
- package/dist/slack.transport-DrirgDNy.d.ts +159 -0
- package/dist/slack.transport-DrirgDNy.d.ts.map +1 -0
- package/dist/slack.transport-DxHOXlLu.d.mts +159 -0
- package/dist/slack.transport-DxHOXlLu.d.mts.map +1 -0
- package/dist/testing.d.mts +3 -8
- package/dist/testing.d.mts.map +1 -1
- package/dist/testing.d.ts +3 -8
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +3 -4
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +2 -3
- package/dist/testing.mjs.map +1 -1
- package/dist/{transport.manager-Crau3Rle.js → transport.manager-DkcEOlqV.js} +331 -234
- package/dist/transport.manager-DkcEOlqV.js.map +1 -0
- package/dist/{transport.manager-CpdVHEGP.mjs → transport.manager-eZ_EeC00.mjs} +274 -178
- package/dist/transport.manager-eZ_EeC00.mjs.map +1 -0
- package/dist/{transport.types-CtNr3D7S.d.mts → transport.types-BJVL1QQl.d.mts} +5 -4
- package/dist/transport.types-BJVL1QQl.d.mts.map +1 -0
- package/dist/{transport.types-DqVLZTyf.d.ts → transport.types-BJVL1QQl.d.ts} +5 -4
- package/dist/transport.types-BJVL1QQl.d.ts.map +1 -0
- package/dist/transports.d.mts +32 -41
- package/dist/transports.d.mts.map +1 -1
- package/dist/transports.d.ts +32 -41
- package/dist/transports.d.ts.map +1 -1
- package/dist/transports.js +12 -12
- package/dist/transports.mjs +7 -12
- package/dist/worker-entry.js +337 -87
- package/dist/worker.d.mts +1 -2
- package/dist/worker.d.ts +1 -2
- package/dist/worker.js +3 -4
- package/dist/worker.mjs +1 -4
- package/dist/{worker.transport-Bj-i0P9V.d.ts → worker.transport-BuPwBi3d.d.ts} +2 -6
- package/dist/worker.transport-BuPwBi3d.d.ts.map +1 -0
- package/dist/{worker.transport-JP8YHBuU.js → worker.transport-C6GNl_r2.js} +44 -14
- package/dist/worker.transport-C6GNl_r2.js.map +1 -0
- package/dist/{worker.transport-otwhJ_Et.mjs → worker.transport-DLVA4y2e.mjs} +39 -9
- package/dist/worker.transport-DLVA4y2e.mjs.map +1 -0
- package/dist/{worker.transport-Bgv9heDI.d.mts → worker.transport-hJay1wxA.d.mts} +2 -6
- package/dist/worker.transport-hJay1wxA.d.mts.map +1 -0
- package/package.json +36 -19
- package/dist/async-context-BzJrbfQs.mjs +0 -72
- package/dist/async-context-BzJrbfQs.mjs.map +0 -1
- package/dist/async-context-DyQQYq3I.js +0 -92
- package/dist/async-context-DyQQYq3I.js.map +0 -1
- package/dist/azure-monitor.transport-BDFO4F-i.d.ts.map +0 -1
- package/dist/azure-monitor.transport-CHnjVRF-.mjs.map +0 -1
- package/dist/azure-monitor.transport-CrvfHd9C.js.map +0 -1
- package/dist/azure-monitor.transport-D5wQEH04.d.mts.map +0 -1
- package/dist/batch-buffer-BY-mRWIK.js.map +0 -1
- package/dist/batch-buffer-PGvSgbmd.mjs.map +0 -1
- package/dist/chunk-DLSkYcPk.mjs +0 -7
- package/dist/chunk-nOFOJqeH.js +0 -30
- package/dist/cloudwatch.transport-B00st6Xv.d.ts.map +0 -1
- package/dist/cloudwatch.transport-BO1ahxw-.js.map +0 -1
- package/dist/cloudwatch.transport-Blc7Gtxt.d.mts.map +0 -1
- package/dist/cloudwatch.transport-DZ6ies7g.mjs.map +0 -1
- package/dist/entry-fields-BJkuPnIg.mjs.map +0 -1
- package/dist/entry-fields-BvOLFlJ4.js.map +0 -1
- package/dist/gcp.transport-CHV8MGgz.js.map +0 -1
- package/dist/gcp.transport-DBX5TPIy.mjs.map +0 -1
- package/dist/gcp.transport-m4fVw0b1.d.ts.map +0 -1
- package/dist/gcp.transport-zzNyIoih.d.mts.map +0 -1
- package/dist/index-BPwEisy4.d.mts.map +0 -1
- package/dist/index-nZEeCr3X.d.ts.map +0 -1
- package/dist/internal-log-BUJYMZbE.js +0 -70
- package/dist/internal-log-BUJYMZbE.js.map +0 -1
- package/dist/internal-log-Cm8SOWSV.mjs +0 -52
- package/dist/internal-log-Cm8SOWSV.mjs.map +0 -1
- package/dist/nestjs-extras-DnJ6vrIC.js.map +0 -1
- package/dist/nestjs-extras-ImbuDhs1.mjs.map +0 -1
- package/dist/nestjs-extras-OkC796py.d.mts +0 -725
- package/dist/nestjs-extras-OkC796py.d.mts.map +0 -1
- package/dist/nestjs-extras-mKrHE9S6.d.ts +0 -725
- package/dist/nestjs-extras-mKrHE9S6.d.ts.map +0 -1
- package/dist/safe-stringify-DJ66tW5I.mjs.map +0 -1
- package/dist/safe-stringify-DWo3aZp_.js.map +0 -1
- package/dist/search-B0MH1SJJ.js.map +0 -1
- package/dist/search-BfBzDIT9.d.mts.map +0 -1
- package/dist/search-CHUZPl0h.d.ts.map +0 -1
- package/dist/search-DjXSn6v5.mjs.map +0 -1
- package/dist/trace.utils-CvXgaiQT.mjs.map +0 -1
- package/dist/trace.utils-DpBOLDtq.js.map +0 -1
- package/dist/transport.manager-CpdVHEGP.mjs.map +0 -1
- package/dist/transport.manager-Crau3Rle.js.map +0 -1
- package/dist/transport.types-CtNr3D7S.d.mts.map +0 -1
- package/dist/transport.types-DqVLZTyf.d.ts.map +0 -1
- package/dist/worker.transport-Bgv9heDI.d.mts.map +0 -1
- package/dist/worker.transport-Bj-i0P9V.d.ts.map +0 -1
- package/dist/worker.transport-JP8YHBuU.js.map +0 -1
- package/dist/worker.transport-otwhJ_Et.mjs.map +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
// \0rolldown/runtime.js
|
|
3
4
|
var __create = Object.create;
|
|
4
5
|
var __defProp = Object.defineProperty;
|
|
5
6
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -16,22 +17,18 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
17
|
}
|
|
17
18
|
return to;
|
|
18
19
|
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
20
21
|
value: mod,
|
|
21
22
|
enumerable: true
|
|
22
23
|
}) : target, mod));
|
|
23
|
-
|
|
24
|
-
//#endregion
|
|
25
24
|
let node_fs = require("node:fs");
|
|
26
25
|
node_fs = __toESM(node_fs);
|
|
27
26
|
let node_path = require("node:path");
|
|
28
27
|
node_path = __toESM(node_path);
|
|
29
28
|
let commander = require("commander");
|
|
30
|
-
commander = __toESM(commander);
|
|
31
29
|
let picocolors = require("picocolors");
|
|
32
30
|
picocolors = __toESM(picocolors);
|
|
33
|
-
|
|
34
|
-
//#region src/utils/csv.utils.ts
|
|
31
|
+
// src/utils/csv.utils.ts
|
|
35
32
|
const CSV_FORMULA_PREFIX = /^[=+\-@\t\r]/;
|
|
36
33
|
/**
|
|
37
34
|
* Render one CSV field. String values that a spreadsheet would treat as a
|
|
@@ -48,9 +45,7 @@ function csvField(value, alwaysQuote = false) {
|
|
|
48
45
|
if (alwaysQuote || /[",\r\n]/.test(str)) return `"${str.replace(/"/g, "\"\"")}"`;
|
|
49
46
|
return str;
|
|
50
47
|
}
|
|
51
|
-
|
|
52
|
-
//#endregion
|
|
53
|
-
//#region src/cli/utils.ts
|
|
48
|
+
// src/cli/utils.ts
|
|
54
49
|
/**
|
|
55
50
|
* Render a single cell value. Uses a null/undefined check rather than `||` so
|
|
56
51
|
* falsy-but-real values (0, false, '') still render — a `count=0` or
|
|
@@ -101,9 +96,7 @@ function safeParseLogs(raw) {
|
|
|
101
96
|
}
|
|
102
97
|
return parsed;
|
|
103
98
|
}
|
|
104
|
-
|
|
105
|
-
//#endregion
|
|
106
|
-
//#region src/cli/commands/analyze.ts
|
|
99
|
+
// src/cli/commands/analyze.ts
|
|
107
100
|
function parseDurationToMs(input) {
|
|
108
101
|
if (!input) return;
|
|
109
102
|
const m = input.match(/^(\d+)([smhd])$/i);
|
|
@@ -157,16 +150,10 @@ const analyzeCommand = new commander.Command("analyze").description("Analyze log
|
|
|
157
150
|
}
|
|
158
151
|
console.log(result);
|
|
159
152
|
});
|
|
160
|
-
|
|
161
|
-
//#endregion
|
|
162
|
-
//#region src/cli/commands/explore.ts
|
|
153
|
+
// src/cli/commands/explore.ts
|
|
163
154
|
const CSI = "\x1B[";
|
|
164
|
-
const clearScreen =
|
|
165
|
-
const clearLine =
|
|
166
|
-
const hideCursor = CSI + "?25l";
|
|
167
|
-
const showCursor = CSI + "?25h";
|
|
168
|
-
const altScreen = CSI + "?1049h";
|
|
169
|
-
const mainScreen = CSI + "?1049l";
|
|
155
|
+
const clearScreen = "\x1B[2J";
|
|
156
|
+
const clearLine = "\x1B[K";
|
|
170
157
|
function moveTo(row, col) {
|
|
171
158
|
return `${CSI}${row};${col}H`;
|
|
172
159
|
}
|
|
@@ -243,7 +230,7 @@ function coloriseStackFrame(frame) {
|
|
|
243
230
|
function buildDetailLines(entry) {
|
|
244
231
|
if (!entry) return [picocolors.default.dim(" No entry selected")];
|
|
245
232
|
const lines = [];
|
|
246
|
-
const { stack
|
|
233
|
+
const { stack, ...rest } = entry;
|
|
247
234
|
const jsonText = sanitizeForTerminal(JSON.stringify(rest, null, 2));
|
|
248
235
|
for (const l of jsonText.split("\n")) lines.push(" " + syntaxColorJson(l));
|
|
249
236
|
if (stack) {
|
|
@@ -280,7 +267,7 @@ var TUIExplorer = class {
|
|
|
280
267
|
this.STATUS_ROWS = 1;
|
|
281
268
|
this.DETAIL_ROWS = 9;
|
|
282
269
|
this.filePath = node_path.default.resolve(process.cwd(), filePath);
|
|
283
|
-
this.levelFilters = new Set([
|
|
270
|
+
this.levelFilters = /* @__PURE__ */ new Set([
|
|
284
271
|
"error",
|
|
285
272
|
"warn",
|
|
286
273
|
"info",
|
|
@@ -301,7 +288,7 @@ var TUIExplorer = class {
|
|
|
301
288
|
this.filePos = node_fs.default.statSync(this.filePath).size;
|
|
302
289
|
this.allEntries = safeParseLogs(raw);
|
|
303
290
|
this.applyFilters();
|
|
304
|
-
write(
|
|
291
|
+
write("\x1B[?1049h\x1B[?25l");
|
|
305
292
|
this.getTerminalSize();
|
|
306
293
|
process.stdout.on("resize", () => {
|
|
307
294
|
this.getTerminalSize();
|
|
@@ -367,7 +354,7 @@ var TUIExplorer = class {
|
|
|
367
354
|
const leftLen = stripAnsi(left).length;
|
|
368
355
|
const rightLen = stripAnsi(right).length;
|
|
369
356
|
const gap = Math.max(1, w - leftLen - rightLen);
|
|
370
|
-
write(moveTo(1, 1) + picocolors.default.bgBlack(left + " ".repeat(gap) + right) +
|
|
357
|
+
write(moveTo(1, 1) + picocolors.default.bgBlack(left + " ".repeat(gap) + right) + "\x1B[K\n");
|
|
371
358
|
}
|
|
372
359
|
drawFilterBar() {
|
|
373
360
|
const badges = [
|
|
@@ -385,14 +372,12 @@ var TUIExplorer = class {
|
|
|
385
372
|
const left = " " + badges;
|
|
386
373
|
const right = searchPart + " ";
|
|
387
374
|
const gap = Math.max(1, w - stripAnsi(left).length - stripAnsi(right).length);
|
|
388
|
-
write(moveTo(2, 1) + picocolors.default.bgBlack(left + " ".repeat(gap) + right) +
|
|
375
|
+
write(moveTo(2, 1) + picocolors.default.bgBlack(left + " ".repeat(gap) + right) + "\x1B[K\n");
|
|
389
376
|
}
|
|
390
377
|
drawColHeader() {
|
|
391
378
|
const w = this.width;
|
|
392
|
-
const timeCol = " TIME ";
|
|
393
|
-
const levelCol = " LVL ";
|
|
394
379
|
const msgWidth = Math.max(20, w - 14 - 5 - 2);
|
|
395
|
-
write(moveTo(3, 1) + compose(picocolors.default.bold, picocolors.default.bgBlack, picocolors.default.dim)(
|
|
380
|
+
write(moveTo(3, 1) + compose(picocolors.default.bold, picocolors.default.bgBlack, picocolors.default.dim)(" TIME LVL " + this.pad("MESSAGE", msgWidth)) + "\x1B[K\n");
|
|
396
381
|
}
|
|
397
382
|
drawList() {
|
|
398
383
|
const lr = this.LIST_ROWS;
|
|
@@ -436,7 +421,7 @@ var TUIExplorer = class {
|
|
|
436
421
|
const label = selected ? ` ▼ DETAIL (${this.selectedIndex + 1}/${this.filteredEntries.length}) ` : " ▼ DETAIL ";
|
|
437
422
|
const labelLen = stripAnsi(label).length;
|
|
438
423
|
const sepLine = compose(picocolors.default.bgBlack, picocolors.default.cyan, picocolors.default.bold)(label) + picocolors.default.dim("─".repeat(Math.max(0, w - labelLen)));
|
|
439
|
-
write(moveTo(sepRow, 1) + sepLine +
|
|
424
|
+
write(moveTo(sepRow, 1) + sepLine + "\x1B[K\n");
|
|
440
425
|
const lines = buildDetailLines(selected);
|
|
441
426
|
for (let row = 0; row < 8; row++) {
|
|
442
427
|
write(moveTo(sepRow + 1 + row, 1));
|
|
@@ -548,7 +533,6 @@ var TUIExplorer = class {
|
|
|
548
533
|
case "q":
|
|
549
534
|
this.cleanup();
|
|
550
535
|
return;
|
|
551
|
-
default: break;
|
|
552
536
|
}
|
|
553
537
|
this.redraw();
|
|
554
538
|
}
|
|
@@ -666,7 +650,7 @@ var TUIExplorer = class {
|
|
|
666
650
|
}
|
|
667
651
|
cleanup() {
|
|
668
652
|
if (this.fileWatcher) node_fs.default.unwatchFile(this.filePath);
|
|
669
|
-
write(
|
|
653
|
+
write("\x1B[?25h\x1B[?1049l");
|
|
670
654
|
if (process.stdin.isTTY) process.stdin.setRawMode(false);
|
|
671
655
|
process.stdin.pause();
|
|
672
656
|
process.exit(0);
|
|
@@ -679,9 +663,7 @@ const exploreCommand = new commander.Command("explore").description("Interactive
|
|
|
679
663
|
search: String(opts.search ?? "")
|
|
680
664
|
}).run();
|
|
681
665
|
});
|
|
682
|
-
|
|
683
|
-
//#endregion
|
|
684
|
-
//#region src/cli/commands/export.ts
|
|
666
|
+
// src/cli/commands/export.ts
|
|
685
667
|
async function exportLogs(raw, opts = {}) {
|
|
686
668
|
const entries = safeParseLogs(raw);
|
|
687
669
|
const fields = opts.fields ? opts.fields.split(",").map((f) => f.trim()) : null;
|
|
@@ -722,9 +704,36 @@ const exportCommand = new commander.Command("export").description("Export log fi
|
|
|
722
704
|
console.log(`Exported to: ${outPath}`);
|
|
723
705
|
} else console.log(output);
|
|
724
706
|
});
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
707
|
+
// src/cli/commands/query.ts
|
|
708
|
+
/**
|
|
709
|
+
* logixia CLI — SQL-like log query engine
|
|
710
|
+
*
|
|
711
|
+
* Supports a subset of SQL syntax over NDJSON / JSON log files:
|
|
712
|
+
*
|
|
713
|
+
* SELECT * FROM logs WHERE level='error' AND duration > 500
|
|
714
|
+
* SELECT level, message FROM logs WHERE level='warn'
|
|
715
|
+
* COUNT BY level
|
|
716
|
+
* AVG(duration) BY endpoint
|
|
717
|
+
* GROUP BY statusCode
|
|
718
|
+
*
|
|
719
|
+
* Time-range shortcuts (--since / --until):
|
|
720
|
+
* --since "last 2 hours"
|
|
721
|
+
* --since "last 30 minutes"
|
|
722
|
+
* --since "today"
|
|
723
|
+
* --since "2024-01-15T08:00:00"
|
|
724
|
+
*
|
|
725
|
+
* @example Basic filter
|
|
726
|
+
* logixia query app.log --sql "SELECT * FROM logs WHERE level='error'"
|
|
727
|
+
*
|
|
728
|
+
* @example Aggregation
|
|
729
|
+
* logixia query app.log --sql "COUNT BY level"
|
|
730
|
+
*
|
|
731
|
+
* @example Time range + table output
|
|
732
|
+
* logixia query app.log --since "last 1 hour" --format table
|
|
733
|
+
*
|
|
734
|
+
* @example Live tail with SQL filter
|
|
735
|
+
* logixia query app.log --follow --sql "WHERE level='error'"
|
|
736
|
+
*/
|
|
728
737
|
/**
|
|
729
738
|
* Parse a human-friendly time range string into a `Date`.
|
|
730
739
|
* Returns `undefined` when the string is not recognised.
|
|
@@ -762,6 +771,21 @@ function parseTimeRange(value) {
|
|
|
762
771
|
const parsed = new Date(value);
|
|
763
772
|
return Number.isNaN(parsed.getTime()) ? void 0 : parsed;
|
|
764
773
|
}
|
|
774
|
+
/** Replace the contents of quoted literals with `_` (same length) so clause keywords inside them are ignored. */
|
|
775
|
+
function maskQuoted(sql) {
|
|
776
|
+
let out = "";
|
|
777
|
+
let quote = null;
|
|
778
|
+
for (const ch of sql) if (quote !== null) {
|
|
779
|
+
if (ch === quote) {
|
|
780
|
+
quote = null;
|
|
781
|
+
out += ch;
|
|
782
|
+
} else out += "_";
|
|
783
|
+
} else {
|
|
784
|
+
if (ch === "'" || ch === "\"") quote = ch;
|
|
785
|
+
out += ch;
|
|
786
|
+
}
|
|
787
|
+
return out;
|
|
788
|
+
}
|
|
765
789
|
function parseSQL(sql) {
|
|
766
790
|
const result = {
|
|
767
791
|
select: "*",
|
|
@@ -771,6 +795,8 @@ function parseSQL(sql) {
|
|
|
771
795
|
limit: null
|
|
772
796
|
};
|
|
773
797
|
const upper = sql.trim().toUpperCase();
|
|
798
|
+
const masked = maskQuoted(sql.trim());
|
|
799
|
+
const maskedUpper = masked.toUpperCase();
|
|
774
800
|
{
|
|
775
801
|
const m = /^COUNT\s+BY\s+(\w+)/i.exec(sql.trim());
|
|
776
802
|
if (m) {
|
|
@@ -805,22 +831,22 @@ function parseSQL(sql) {
|
|
|
805
831
|
}
|
|
806
832
|
}
|
|
807
833
|
if (upper.startsWith("SELECT")) {
|
|
808
|
-
const fromIdx =
|
|
834
|
+
const fromIdx = maskedUpper.indexOf(" FROM ");
|
|
809
835
|
if (fromIdx !== -1) {
|
|
810
836
|
const selectPart = sql.slice(6, fromIdx + sql.length - upper.length).trim();
|
|
811
837
|
if (selectPart !== "*") result.select = selectPart.split(",").map((s) => s.trim()).filter(Boolean);
|
|
812
838
|
}
|
|
813
839
|
}
|
|
814
840
|
const remainder = sql.trim();
|
|
815
|
-
const whereTokenIdx =
|
|
841
|
+
const whereTokenIdx = maskedUpper.indexOf("WHERE ");
|
|
816
842
|
if (whereTokenIdx !== -1) {
|
|
817
843
|
const afterWhere = remainder.slice(whereTokenIdx + 6).trimStart();
|
|
818
|
-
const upperAfter =
|
|
844
|
+
const upperAfter = maskedUpper.slice(whereTokenIdx + 6).trimStart();
|
|
819
845
|
const candidates = [upperAfter.indexOf(" ORDER BY "), upperAfter.indexOf(" LIMIT ")].filter((i) => i !== -1);
|
|
820
846
|
const endIdx = candidates.length > 0 ? Math.min(...candidates) : afterWhere.length;
|
|
821
847
|
result.where = parseWhereClause(afterWhere.slice(0, endIdx).trim());
|
|
822
848
|
}
|
|
823
|
-
const orderMatch = /ORDER\s+BY\s+(\w+)(?:\s+(ASC|DESC))?/i.exec(
|
|
849
|
+
const orderMatch = /ORDER\s+BY\s+(\w+)(?:\s+(ASC|DESC))?/i.exec(masked);
|
|
824
850
|
if (orderMatch) {
|
|
825
851
|
var _orderMatch$;
|
|
826
852
|
result.orderBy = {
|
|
@@ -828,7 +854,7 @@ function parseSQL(sql) {
|
|
|
828
854
|
dir: ((_orderMatch$ = orderMatch[2]) === null || _orderMatch$ === void 0 ? void 0 : _orderMatch$.toUpperCase()) ?? "ASC"
|
|
829
855
|
};
|
|
830
856
|
}
|
|
831
|
-
const limitMatch = /LIMIT\s+(\d+)/i.exec(
|
|
857
|
+
const limitMatch = /LIMIT\s+(\d+)/i.exec(masked);
|
|
832
858
|
if (limitMatch) result.limit = Number.parseInt(limitMatch[1], 10);
|
|
833
859
|
return result;
|
|
834
860
|
}
|
|
@@ -1092,36 +1118,39 @@ function executeQuery(entries, opts) {
|
|
|
1092
1118
|
results: [],
|
|
1093
1119
|
aggregationOutput: runAggregation(rows, query.aggregation)
|
|
1094
1120
|
};
|
|
1095
|
-
rows = rows.map((row) => projectRow(row, query.select));
|
|
1096
1121
|
const orderField = ((_query$orderBy = query.orderBy) === null || _query$orderBy === void 0 ? void 0 : _query$orderBy.field) ?? opts.orderBy;
|
|
1097
1122
|
if (orderField) {
|
|
1098
1123
|
var _query$orderBy2;
|
|
1099
1124
|
const dir = ((_query$orderBy2 = query.orderBy) === null || _query$orderBy2 === void 0 ? void 0 : _query$orderBy2.dir) ?? "ASC";
|
|
1100
|
-
rows.sort((a, b) => {
|
|
1125
|
+
rows = [...rows].sort((a, b) => {
|
|
1101
1126
|
const av = a[orderField];
|
|
1102
1127
|
const bv = b[orderField];
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
if (
|
|
1128
|
+
const aMissing = av === void 0 || av === null;
|
|
1129
|
+
const bMissing = bv === void 0 || bv === null;
|
|
1130
|
+
if (aMissing && bMissing) return 0;
|
|
1131
|
+
if (aMissing) return 1;
|
|
1132
|
+
if (bMissing) return -1;
|
|
1106
1133
|
if (typeof av === "number" && typeof bv === "number") return dir === "ASC" ? av - bv : bv - av;
|
|
1107
1134
|
return dir === "ASC" ? String(av).localeCompare(String(bv)) : String(bv).localeCompare(String(av));
|
|
1108
1135
|
});
|
|
1109
1136
|
}
|
|
1110
1137
|
const limitN = query.limit ?? opts.limit;
|
|
1111
|
-
if (limitN && limitN
|
|
1138
|
+
if (typeof limitN === "number" && limitN >= 0) rows = rows.slice(0, limitN);
|
|
1139
|
+
rows = rows.map((row) => projectRow(row, query.select));
|
|
1112
1140
|
return {
|
|
1113
1141
|
results: rows,
|
|
1114
1142
|
aggregationOutput: null
|
|
1115
1143
|
};
|
|
1116
1144
|
}
|
|
1117
|
-
const queryCommand = new commander.Command("query").description("Query log files with SQL-like syntax\n\n Examples:\n logixia query app.log --sql \"SELECT * FROM logs WHERE level='error'\"\n logixia query app.log --sql \"COUNT BY level\"\n logixia query app.log --sql \"AVG(duration) BY endpoint\"\n logixia query app.log --since \"last 2 hours\" --format table\n logixia query app.log --follow --sql \"WHERE level='error'\"\n").argument("<file>", "Path to NDJSON or JSON log file").option("--sql <query>", "SQL-like query string").option("--since <time>", "Only include entries after this time (e.g. \"last 2 hours\", \"today\")").option("--until <time>", "Only include entries before this time").option("--limit <n>", "Maximum number of results to return"
|
|
1145
|
+
const queryCommand = new commander.Command("query").description("Query log files with SQL-like syntax\n\n Examples:\n logixia query app.log --sql \"SELECT * FROM logs WHERE level='error'\"\n logixia query app.log --sql \"COUNT BY level\"\n logixia query app.log --sql \"AVG(duration) BY endpoint\"\n logixia query app.log --since \"last 2 hours\" --format table\n logixia query app.log --follow --sql \"WHERE level='error'\"\n").argument("<file>", "Path to NDJSON or JSON log file").option("--sql <query>", "SQL-like query string").option("--since <time>", "Only include entries after this time (e.g. \"last 2 hours\", \"today\")").option("--until <time>", "Only include entries before this time").option("--limit <n>", "Maximum number of results to return").option("--order-by <field>", "Sort results by this field").option("--format <fmt>", "Output format: line, table, json, ndjson", "line").option("--follow", "Follow file for new entries matching the query (tail mode)", false).action(async (file, opts) => {
|
|
1118
1146
|
const full = node_path.default.resolve(process.cwd(), file);
|
|
1119
1147
|
if (!node_fs.default.existsSync(full)) {
|
|
1120
1148
|
console.error(picocolors.default.red(`File not found: ${full}`));
|
|
1121
1149
|
process.exit(2);
|
|
1122
1150
|
}
|
|
1123
1151
|
const entries = safeParseLogs(node_fs.default.readFileSync(full, "utf8"));
|
|
1124
|
-
const
|
|
1152
|
+
const parsedLimit = opts.limit === void 0 ? NaN : Number.parseInt(opts.limit, 10);
|
|
1153
|
+
const limitN = Number.isNaN(parsedLimit) ? void 0 : parsedLimit;
|
|
1125
1154
|
const { results, aggregationOutput } = executeQuery(entries, {
|
|
1126
1155
|
sql: opts.sql,
|
|
1127
1156
|
since: opts.since,
|
|
@@ -1168,9 +1197,7 @@ const queryCommand = new commander.Command("query").description("Query log files
|
|
|
1168
1197
|
});
|
|
1169
1198
|
}
|
|
1170
1199
|
});
|
|
1171
|
-
|
|
1172
|
-
//#endregion
|
|
1173
|
-
//#region src/cli/commands/search.ts
|
|
1200
|
+
// src/cli/commands/search.ts
|
|
1174
1201
|
function parseQuery(query) {
|
|
1175
1202
|
const match = query.match(/^(\w+):(.+)$/);
|
|
1176
1203
|
if (match) return {
|
|
@@ -1217,9 +1244,7 @@ const searchCommand = new commander.Command("search").description("Search log fi
|
|
|
1217
1244
|
console.log(picocolors.default.bold(`\nFound ${results.length} matches`));
|
|
1218
1245
|
console.log(formatSearchResults(results, opts.format, Number.parseInt(opts.context || "0")));
|
|
1219
1246
|
});
|
|
1220
|
-
|
|
1221
|
-
//#endregion
|
|
1222
|
-
//#region src/cli/commands/stats.ts
|
|
1247
|
+
// src/cli/commands/stats.ts
|
|
1223
1248
|
async function generateStats(raw, opts = {}) {
|
|
1224
1249
|
const entries = safeParseLogs(raw);
|
|
1225
1250
|
const group = opts.groupBy || "level";
|
|
@@ -1279,9 +1304,7 @@ const statsCommand = new commander.Command("stats").description("Show statistics
|
|
|
1279
1304
|
if (opts.format === "json") console.log(sanitizeForTerminal(JSON.stringify(stats, null, 2)));
|
|
1280
1305
|
else console.log(formatStatsOutput(stats, file));
|
|
1281
1306
|
});
|
|
1282
|
-
|
|
1283
|
-
//#endregion
|
|
1284
|
-
//#region src/cli/commands/tail.ts
|
|
1307
|
+
// src/cli/commands/tail.ts
|
|
1285
1308
|
function parseFilter(filter) {
|
|
1286
1309
|
if (!filter) return null;
|
|
1287
1310
|
const match = filter.match(/^(\w+):(.+)$/);
|
|
@@ -1349,9 +1372,7 @@ const tailCommand = new commander.Command("tail").description("Follow log files
|
|
|
1349
1372
|
});
|
|
1350
1373
|
}
|
|
1351
1374
|
});
|
|
1352
|
-
|
|
1353
|
-
//#endregion
|
|
1354
|
-
//#region src/cli/index.ts
|
|
1375
|
+
// src/cli/index.ts
|
|
1355
1376
|
const pkgPath = node_path.default.resolve(__dirname, "../..", "package.json");
|
|
1356
1377
|
let pkg;
|
|
1357
1378
|
try {
|
|
@@ -1381,7 +1402,5 @@ function isDirectRun(argv1, file) {
|
|
|
1381
1402
|
}
|
|
1382
1403
|
}
|
|
1383
1404
|
if (isDirectRun(process.argv[1], __filename)) program.parse(process.argv);
|
|
1384
|
-
|
|
1385
|
-
//#endregion
|
|
1386
1405
|
exports.isDirectRun = isDirectRun;
|
|
1387
|
-
exports.program = program;
|
|
1406
|
+
exports.program = program;
|
package/dist/cloudwatch.d.mts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import "./transport
|
|
2
|
-
import { n as CloudWatchTransportConfig, t as CloudWatchTransport } from "./cloudwatch.transport-Blc7Gtxt.mjs";
|
|
1
|
+
import { n as CloudWatchTransportConfig, t as CloudWatchTransport } from "./cloudwatch.transport-Rj4yTpRn.mjs";
|
|
3
2
|
export { CloudWatchTransport, CloudWatchTransportConfig };
|
package/dist/cloudwatch.d.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import "./transport
|
|
2
|
-
import { n as CloudWatchTransportConfig, t as CloudWatchTransport } from "./cloudwatch.transport-B00st6Xv.js";
|
|
1
|
+
import { n as CloudWatchTransportConfig, t as CloudWatchTransport } from "./cloudwatch.transport-Bf7L4I59.js";
|
|
3
2
|
export { CloudWatchTransport, CloudWatchTransportConfig };
|
package/dist/cloudwatch.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
require(
|
|
3
|
-
|
|
4
|
-
const require_cloudwatch_transport = require('./cloudwatch.transport-BO1ahxw-.js');
|
|
5
|
-
require('./entry-fields-BvOLFlJ4.js');
|
|
6
|
-
|
|
7
|
-
exports.CloudWatchTransport = require_cloudwatch_transport.CloudWatchTransport;
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_cloudwatch_transport = require("./cloudwatch.transport-B2wKQFF7.js");
|
|
3
|
+
exports.CloudWatchTransport = require_cloudwatch_transport.CloudWatchTransport;
|
package/dist/cloudwatch.mjs
CHANGED
|
@@ -1,7 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import "./safe-stringify-DJ66tW5I.mjs";
|
|
3
|
-
import "./batch-buffer-PGvSgbmd.mjs";
|
|
4
|
-
import { t as CloudWatchTransport } from "./cloudwatch.transport-DZ6ies7g.mjs";
|
|
5
|
-
import "./entry-fields-BJkuPnIg.mjs";
|
|
6
|
-
|
|
7
|
-
export { CloudWatchTransport };
|
|
1
|
+
export { t as CloudWatchTransport } from "./cloudwatch.transport-BTvYfLs9.mjs";
|
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
const
|
|
2
|
-
const require_internal_log = require(
|
|
3
|
-
const require_safe_stringify = require(
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
let
|
|
7
|
-
|
|
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_entry_fields = require("./entry-fields-RLd1jCoR.js");
|
|
5
|
+
const require_batch_buffer = require("./batch-buffer-DT4gdXmf.js");
|
|
6
|
+
let node_crypto = require("node:crypto");
|
|
7
|
+
node_crypto = require_secret_config.__toESM(node_crypto);
|
|
8
8
|
let node_os = require("node:os");
|
|
9
|
-
node_os =
|
|
9
|
+
node_os = require_secret_config.__toESM(node_os);
|
|
10
|
+
let node_fs = require("node:fs");
|
|
11
|
+
node_fs = require_secret_config.__toESM(node_fs);
|
|
10
12
|
let node_path = require("node:path");
|
|
11
|
-
node_path =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
node_path = require_secret_config.__toESM(node_path);
|
|
14
|
+
// src/transports/aws-credentials.ts
|
|
15
|
+
/**
|
|
16
|
+
* AWS credential resolution without the SDK.
|
|
17
|
+
*
|
|
18
|
+
* Order: explicit config, environment variables, shared credentials file,
|
|
19
|
+
* ECS/container credentials, EC2 instance metadata (IMDSv2).
|
|
20
|
+
* Not supported: SSO, assume-role profiles, credential_process, web identity.
|
|
21
|
+
*/
|
|
22
|
+
const REFRESH_MARGIN_MS = 3e5;
|
|
23
|
+
const FAILURE_BACKOFF_MS = 3e4;
|
|
18
24
|
const METADATA_TIMEOUT_MS = 2e3;
|
|
19
25
|
/** Parse the sections of an AWS ini file into `{ section: { key: value } }`. */
|
|
20
26
|
function parseIni(text) {
|
|
@@ -73,7 +79,7 @@ function fromDocument(raw) {
|
|
|
73
79
|
expiresAt: Number.isNaN(expiresAt) ? void 0 : expiresAt
|
|
74
80
|
};
|
|
75
81
|
}
|
|
76
|
-
const CONTAINER_HOSTS = new Set([
|
|
82
|
+
const CONTAINER_HOSTS = /* @__PURE__ */ new Set([
|
|
77
83
|
"169.254.170.2",
|
|
78
84
|
"169.254.170.23",
|
|
79
85
|
"[fd00:ec2::23]",
|
|
@@ -118,8 +124,7 @@ async function fromInstanceMetadata() {
|
|
|
118
124
|
timeoutMs: METADATA_TIMEOUT_MS,
|
|
119
125
|
label: "EC2 instance metadata"
|
|
120
126
|
});
|
|
121
|
-
const
|
|
122
|
-
const auth = { "X-aws-ec2-metadata-token": session.body.trim() };
|
|
127
|
+
const auth = { "X-aws-ec2-metadata-token": (await get("/latest/api/token", "PUT", { "X-aws-ec2-metadata-token-ttl-seconds": "21600" })).body.trim() };
|
|
123
128
|
const role = (_roles$body$split$ = (await get("/latest/meta-data/iam/security-credentials/", "GET", auth)).body.split("\n")[0]) === null || _roles$body$split$ === void 0 ? void 0 : _roles$body$split$.trim();
|
|
124
129
|
if (!role) return void 0;
|
|
125
130
|
return fromDocument((await get(`/latest/meta-data/iam/security-credentials/${encodeURIComponent(role)}`, "GET", auth)).body);
|
|
@@ -127,6 +132,7 @@ async function fromInstanceMetadata() {
|
|
|
127
132
|
var AwsCredentialProvider = class {
|
|
128
133
|
constructor(config) {
|
|
129
134
|
this.failedAt = 0;
|
|
135
|
+
require_secret_config.protectSecrets(this, ["cached", "explicit"]);
|
|
130
136
|
if (config.accessKeyId && config.secretAccessKey) this.explicit = {
|
|
131
137
|
accessKeyId: config.accessKeyId,
|
|
132
138
|
secretAccessKey: config.secretAccessKey,
|
|
@@ -154,6 +160,19 @@ var AwsCredentialProvider = class {
|
|
|
154
160
|
this.cached = found;
|
|
155
161
|
return found;
|
|
156
162
|
}
|
|
163
|
+
/** Secret values this provider may hold, for scrubbing error text. */
|
|
164
|
+
secretValues() {
|
|
165
|
+
var _this$explicit, _this$explicit2, _this$cached, _this$cached2;
|
|
166
|
+
const env = process.env;
|
|
167
|
+
return [
|
|
168
|
+
(_this$explicit = this.explicit) === null || _this$explicit === void 0 ? void 0 : _this$explicit.secretAccessKey,
|
|
169
|
+
(_this$explicit2 = this.explicit) === null || _this$explicit2 === void 0 ? void 0 : _this$explicit2.sessionToken,
|
|
170
|
+
(_this$cached = this.cached) === null || _this$cached === void 0 ? void 0 : _this$cached.secretAccessKey,
|
|
171
|
+
(_this$cached2 = this.cached) === null || _this$cached2 === void 0 ? void 0 : _this$cached2.sessionToken,
|
|
172
|
+
env["AWS_SECRET_ACCESS_KEY"],
|
|
173
|
+
env["AWS_SESSION_TOKEN"]
|
|
174
|
+
];
|
|
175
|
+
}
|
|
157
176
|
invalidate() {
|
|
158
177
|
this.cached = void 0;
|
|
159
178
|
this.failedAt = 0;
|
|
@@ -162,9 +181,10 @@ var AwsCredentialProvider = class {
|
|
|
162
181
|
return c.expiresAt !== void 0 && c.expiresAt - Date.now() < REFRESH_MARGIN_MS;
|
|
163
182
|
}
|
|
164
183
|
};
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
184
|
+
// src/transports/aws-sigv4.ts
|
|
185
|
+
/**
|
|
186
|
+
* AWS Signature Version 4 request signing, dependency-free.
|
|
187
|
+
*/
|
|
168
188
|
const sha256Hex = (data) => node_crypto.createHash("sha256").update(data).digest("hex");
|
|
169
189
|
const hmac = (key, msg) => node_crypto.createHmac("sha256", key).update(msg).digest();
|
|
170
190
|
/** Returns the request headers (lowercase names) with `x-amz-date` and `authorization` added. */
|
|
@@ -199,13 +219,11 @@ function signV4(opts) {
|
|
|
199
219
|
headers["authorization"] = `AWS4-HMAC-SHA256 Credential=${credentials.accessKeyId}/${scope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
|
|
200
220
|
return headers;
|
|
201
221
|
}
|
|
202
|
-
|
|
203
|
-
//#endregion
|
|
204
|
-
//#region src/transports/cloudwatch.transport.ts
|
|
222
|
+
// src/transports/cloudwatch.transport.ts
|
|
205
223
|
const MAX_EVENTS_PER_PUT = 1e4;
|
|
206
224
|
const EMF_MAX_METRICS = 100;
|
|
207
225
|
/** Error types worth retrying even though CloudWatch reports them as HTTP 400. */
|
|
208
|
-
const RETRYABLE_TYPES = new Set([
|
|
226
|
+
const RETRYABLE_TYPES = /* @__PURE__ */ new Set([
|
|
209
227
|
"ThrottlingException",
|
|
210
228
|
"ThrottledException",
|
|
211
229
|
"LimitExceededException",
|
|
@@ -241,18 +259,20 @@ var CloudWatchTransport = class {
|
|
|
241
259
|
this.emf = config.emf ?? false;
|
|
242
260
|
this.emfMetrics = config.emfMetrics ? new Set(config.emfMetrics) : void 0;
|
|
243
261
|
this.level = config.level;
|
|
244
|
-
this.requestTimeoutMs = config.requestTimeoutMs ??
|
|
262
|
+
this.requestTimeoutMs = config.requestTimeoutMs ?? 1e4;
|
|
245
263
|
this.buffer = new require_batch_buffer.BatchBuffer({
|
|
246
264
|
name: "CloudWatchTransport",
|
|
247
265
|
batchSize: this.batchSize,
|
|
248
|
-
maxBufferSize: config.maxBufferSize ??
|
|
266
|
+
maxBufferSize: config.maxBufferSize ?? 1e4,
|
|
249
267
|
send: (events) => this.putLogEvents(events),
|
|
268
|
+
secrets: () => [...this.credentials.secretValues(), ...require_secret_config.urlSecrets(this.endpoint)],
|
|
250
269
|
shouldRetry: (err) => !require_batch_buffer.isPermanentHttpError(err) || RETRYABLE_TYPES.has(awsErrorType(err) ?? "")
|
|
251
270
|
});
|
|
252
271
|
this.flushTimer = setInterval(() => {
|
|
253
272
|
this.flush().catch(() => {});
|
|
254
273
|
}, this.flushInterval);
|
|
255
274
|
if (this.flushTimer.unref) this.flushTimer.unref();
|
|
275
|
+
require_secret_config.protectSecrets(this, ["credentials", "endpoint"]);
|
|
256
276
|
}
|
|
257
277
|
write(entry) {
|
|
258
278
|
const timestamp = entry.timestamp ? new Date(entry.timestamp).getTime() : Date.now();
|
|
@@ -362,16 +382,21 @@ var CloudWatchTransport = class {
|
|
|
362
382
|
headers,
|
|
363
383
|
body,
|
|
364
384
|
timeoutMs: this.requestTimeoutMs,
|
|
365
|
-
label: `CloudWatch ${action}
|
|
385
|
+
label: `CloudWatch ${action}`,
|
|
386
|
+
secrets: () => [
|
|
387
|
+
...this.credentials.secretValues(),
|
|
388
|
+
headers["authorization"],
|
|
389
|
+
headers["x-amz-security-token"],
|
|
390
|
+
...require_secret_config.urlSecrets(this.endpoint)
|
|
391
|
+
]
|
|
366
392
|
});
|
|
367
393
|
}
|
|
368
394
|
};
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
return CloudWatchTransport;
|
|
375
|
-
}
|
|
395
|
+
Object.defineProperty(exports, "CloudWatchTransport", {
|
|
396
|
+
enumerable: true,
|
|
397
|
+
get: function() {
|
|
398
|
+
return CloudWatchTransport;
|
|
399
|
+
}
|
|
376
400
|
});
|
|
377
|
-
|
|
401
|
+
|
|
402
|
+
//# sourceMappingURL=cloudwatch.transport-B2wKQFF7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudwatch.transport-B2wKQFF7.js","names":["path","os","fs","httpRequest","crypto","HttpError","BatchBuffer","urlSecrets","isPermanentHttpError","stringifyForLog","mergeCoreFields","httpRequest"],"sources":["../src/transports/aws-credentials.ts","../src/transports/aws-sigv4.ts","../src/transports/cloudwatch.transport.ts"],"sourcesContent":["/**\n * AWS credential resolution without the SDK.\n *\n * Order: explicit config, environment variables, shared credentials file,\n * ECS/container credentials, EC2 instance metadata (IMDSv2).\n * Not supported: SSO, assume-role profiles, credential_process, web identity.\n */\n\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\n\nimport { internalWarn } from '../utils/internal-log';\nimport { type AwsCredentials } from './aws-sigv4';\nimport { httpRequest } from './batch-buffer';\nimport { protectSecrets } from './secret-config';\n\nconst REFRESH_MARGIN_MS = 5 * 60 * 1000;\nconst FAILURE_BACKOFF_MS = 30 * 1000;\nconst METADATA_TIMEOUT_MS = 2000;\n\nexport interface AwsCredentialConfig {\n accessKeyId?: string | undefined;\n secretAccessKey?: string | undefined;\n sessionToken?: string | undefined;\n}\n\n/** Parse the sections of an AWS ini file into `{ section: { key: value } }`. */\nexport function parseIni(text: string): Record<string, Record<string, string>> {\n const out: Record<string, Record<string, string>> = {};\n let section: Record<string, string> | undefined;\n for (const raw of text.split(/\\r?\\n/)) {\n const line = raw.trim();\n if (!line || line.startsWith('#') || line.startsWith(';')) continue;\n const header = /^\\[(.+)\\]$/.exec(line);\n if (header) {\n section = out[header[1]!.trim()] = out[header[1]!.trim()] ?? {};\n continue;\n }\n const eq = line.indexOf('=');\n if (eq > 0 && section) section[line.slice(0, eq).trim()] = line.slice(eq + 1).trim();\n }\n return out;\n}\n\nfunction fromEnv(): AwsCredentials | undefined {\n const accessKeyId = process.env['AWS_ACCESS_KEY_ID'];\n const secretAccessKey = process.env['AWS_SECRET_ACCESS_KEY'];\n if (!accessKeyId || !secretAccessKey) return undefined;\n return { accessKeyId, secretAccessKey, sessionToken: process.env['AWS_SESSION_TOKEN'] };\n}\n\nfunction fromSharedFile(): AwsCredentials | undefined {\n const file =\n process.env['AWS_SHARED_CREDENTIALS_FILE'] ?? path.join(os.homedir(), '.aws', 'credentials');\n const profile = process.env['AWS_PROFILE'] ?? 'default';\n let text: string;\n try {\n text = fs.readFileSync(file, 'utf8');\n } catch {\n return undefined;\n }\n const section = parseIni(text)[profile];\n const accessKeyId = section?.['aws_access_key_id'];\n const secretAccessKey = section?.['aws_secret_access_key'];\n if (!accessKeyId || !secretAccessKey) return undefined;\n return { accessKeyId, secretAccessKey, sessionToken: section?.['aws_session_token'] };\n}\n\ninterface CredentialDocument {\n AccessKeyId?: string;\n SecretAccessKey?: string;\n Token?: string;\n Expiration?: string;\n}\n\nfunction fromDocument(raw: string): AwsCredentials | undefined {\n const doc = JSON.parse(raw) as CredentialDocument;\n if (!doc.AccessKeyId || !doc.SecretAccessKey) return undefined;\n const expiresAt = doc.Expiration ? Date.parse(doc.Expiration) : Number.NaN;\n return {\n accessKeyId: doc.AccessKeyId,\n secretAccessKey: doc.SecretAccessKey,\n sessionToken: doc.Token,\n expiresAt: Number.isNaN(expiresAt) ? undefined : expiresAt,\n };\n}\n\nconst CONTAINER_HOSTS = new Set([\n // eslint-disable-next-line sonarjs/no-hardcoded-ip -- fixed ECS credentials endpoint\n '169.254.170.2',\n // eslint-disable-next-line sonarjs/no-hardcoded-ip -- fixed EKS pod identity endpoint\n '169.254.170.23',\n '[fd00:ec2::23]',\n 'localhost',\n '[::1]',\n]);\n\n/** Same rule as the AWS SDKs: never send the container token to an arbitrary http host. */\nfunction isAllowedContainerHost(url: URL): boolean {\n if (url.protocol === 'https:') return true;\n if (url.protocol !== 'http:') return false;\n return CONTAINER_HOSTS.has(url.hostname) || /^127(?:\\.\\d{1,3}){3}$/.test(url.hostname);\n}\n\nasync function fromContainer(): Promise<AwsCredentials | undefined> {\n const relative = process.env['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'];\n const full = process.env['AWS_CONTAINER_CREDENTIALS_FULL_URI'];\n if (!relative && !full) return undefined;\n const url = new URL(relative ? `http://169.254.170.2${relative}` : (full as string));\n if (!relative && !isAllowedContainerHost(url)) {\n internalWarn(\n `ignoring AWS_CONTAINER_CREDENTIALS_FULL_URI: ${url.host} is not https or a loopback / ECS / EKS address`\n );\n return undefined;\n }\n const headers: Record<string, string> = {};\n const tokenFile = process.env['AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE'];\n const token = tokenFile\n ? fs.readFileSync(tokenFile, 'utf8').trim()\n : process.env['AWS_CONTAINER_AUTHORIZATION_TOKEN'];\n if (token) headers['Authorization'] = token;\n const res = await httpRequest({\n url,\n method: 'GET',\n headers,\n timeoutMs: METADATA_TIMEOUT_MS,\n label: 'AWS container credentials',\n });\n return fromDocument(res.body);\n}\n\nasync function fromInstanceMetadata(): Promise<AwsCredentials | undefined> {\n if (process.env['AWS_EC2_METADATA_DISABLED'] === 'true') return undefined;\n const base = process.env['AWS_EC2_METADATA_SERVICE_ENDPOINT'] ?? 'http://169.254.169.254';\n const get = (p: string, method: string, headers: Record<string, string>) =>\n httpRequest({\n url: new URL(p, base),\n method,\n headers,\n timeoutMs: METADATA_TIMEOUT_MS,\n label: 'EC2 instance metadata',\n });\n const session = await get('/latest/api/token', 'PUT', {\n 'X-aws-ec2-metadata-token-ttl-seconds': '21600',\n });\n const auth = { 'X-aws-ec2-metadata-token': session.body.trim() };\n const roles = await get('/latest/meta-data/iam/security-credentials/', 'GET', auth);\n const role = roles.body.split('\\n')[0]?.trim();\n if (!role) return undefined;\n const creds = await get(\n `/latest/meta-data/iam/security-credentials/${encodeURIComponent(role)}`,\n 'GET',\n auth\n );\n return fromDocument(creds.body);\n}\n\nexport class AwsCredentialProvider {\n private cached: AwsCredentials | undefined;\n private failedAt = 0;\n private readonly explicit: AwsCredentials | undefined;\n\n constructor(config: AwsCredentialConfig) {\n protectSecrets(this, ['cached', 'explicit']);\n if (config.accessKeyId && config.secretAccessKey) {\n this.explicit = {\n accessKeyId: config.accessKeyId,\n secretAccessKey: config.secretAccessKey,\n sessionToken: config.sessionToken,\n };\n }\n }\n\n /** Throws when no source yields credentials, so the caller keeps its buffer. */\n async get(): Promise<AwsCredentials> {\n if (this.explicit) return this.explicit;\n const env = fromEnv();\n if (env) return env;\n if (this.cached && !this.isExpiring(this.cached)) return this.cached;\n if (Date.now() - this.failedAt < FAILURE_BACKOFF_MS) {\n throw new Error('no AWS credentials found (retrying shortly)');\n }\n\n let found = fromSharedFile();\n for (const source of [fromContainer, fromInstanceMetadata]) {\n if (found) break;\n try {\n found = await source();\n } catch {\n /* source not available here; try the next */\n }\n }\n if (!found) {\n this.failedAt = Date.now();\n throw new Error(\n 'no AWS credentials found: set AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY, a shared credentials file, container credentials, or run on EC2 with an instance role'\n );\n }\n this.cached = found;\n return found;\n }\n\n /** Secret values this provider may hold, for scrubbing error text. */\n secretValues(): (string | undefined)[] {\n const env = process.env;\n return [\n this.explicit?.secretAccessKey,\n this.explicit?.sessionToken,\n this.cached?.secretAccessKey,\n this.cached?.sessionToken,\n env['AWS_SECRET_ACCESS_KEY'],\n env['AWS_SESSION_TOKEN'],\n ];\n }\n\n invalidate(): void {\n this.cached = undefined;\n this.failedAt = 0;\n }\n\n private isExpiring(c: AwsCredentials): boolean {\n return c.expiresAt !== undefined && c.expiresAt - Date.now() < REFRESH_MARGIN_MS;\n }\n}\n","/**\n * AWS Signature Version 4 request signing, dependency-free.\n */\n\nimport * as crypto from 'node:crypto';\n\nexport interface AwsCredentials {\n accessKeyId: string;\n secretAccessKey: string;\n sessionToken?: string | undefined;\n /** Epoch ms after which the credentials are no longer valid. */\n expiresAt?: number | undefined;\n}\n\nexport interface SignV4Options {\n method: string;\n path: string;\n query?: string;\n /** Must include `host`. Names are lowercased before signing. */\n headers: Record<string, string>;\n body: string;\n region: string;\n service: string;\n credentials: AwsCredentials;\n date?: Date;\n}\n\nconst sha256Hex = (data: string): string => crypto.createHash('sha256').update(data).digest('hex');\n\nconst hmac = (key: Buffer | string, msg: string): Buffer =>\n crypto.createHmac('sha256', key).update(msg).digest();\n\n/** Returns the request headers (lowercase names) with `x-amz-date` and `authorization` added. */\nexport function signV4(opts: SignV4Options): Record<string, string> {\n const {\n method,\n path,\n query = '',\n body,\n region,\n service,\n credentials,\n headers: input,\n date,\n } = opts;\n const amzDate = (date ?? new Date()).toISOString().replace(/[:-]|\\.\\d{3}/g, '');\n const dateStamp = amzDate.slice(0, 8);\n\n const headers: Record<string, string> = {};\n for (const [k, v] of Object.entries(input)) headers[k.toLowerCase()] = v;\n headers['x-amz-date'] = amzDate;\n if (credentials.sessionToken) headers['x-amz-security-token'] = credentials.sessionToken;\n\n const names = Object.keys(headers).sort();\n const canonicalHeaders = names\n .map((n) => `${n}:${headers[n]!.trim().replace(/\\s+/g, ' ')}\\n`)\n .join('');\n const signedHeaders = names.join(';');\n\n const canonicalRequest = [\n method,\n path,\n query,\n canonicalHeaders,\n signedHeaders,\n sha256Hex(body),\n ].join('\\n');\n const scope = `${dateStamp}/${region}/${service}/aws4_request`;\n const stringToSign = ['AWS4-HMAC-SHA256', amzDate, scope, sha256Hex(canonicalRequest)].join('\\n');\n\n const signingKey = hmac(\n hmac(hmac(hmac(`AWS4${credentials.secretAccessKey}`, dateStamp), region), service),\n 'aws4_request'\n );\n const signature = crypto.createHmac('sha256', signingKey).update(stringToSign).digest('hex');\n\n headers['authorization'] =\n `AWS4-HMAC-SHA256 Credential=${credentials.accessKeyId}/${scope}, ` +\n `SignedHeaders=${signedHeaders}, Signature=${signature}`;\n return headers;\n}\n","/**\n * logixia — AWS CloudWatch Logs transport\n *\n * Sends log entries to AWS CloudWatch Logs via the PutLogEvents API.\n * Supports EMF (Embedded Metric Format) for automatic metric extraction.\n *\n * Auth, in order: explicit config, environment variables, the shared\n * credentials file (AWS_PROFILE, AWS_SHARED_CREDENTIALS_FILE), ECS container\n * credentials, then EC2 instance metadata (IMDSv2). SSO, assume-role profiles\n * and credential_process are not supported. No SDK dependency — raw HTTPS with\n * AWS Signature Version 4.\n *\n * The log group and stream are created on first use if they do not exist.\n *\n * @example\n * ```ts\n * import { CloudWatchTransport } from 'logixia';\n *\n * const logger = createLogger({\n * transports: {\n * cloudwatch: new CloudWatchTransport({\n * region: 'us-east-1',\n * logGroupName: '/myapp/production',\n * logStreamName: `api-${process.env.HOSTNAME}`,\n * batchSize: 100,\n * flushIntervalMs: 5000,\n * }),\n * },\n * });\n * ```\n */\n\nimport type { IAsyncTransport, TransportLogEntry } from '../types/transport.types';\nimport { internalWarn } from '../utils/internal-log';\nimport { stringifyForLog } from '../utils/safe-stringify';\nimport { AwsCredentialProvider } from './aws-credentials';\nimport { signV4 } from './aws-sigv4';\nimport {\n BatchBuffer,\n DEFAULT_MAX_BUFFER_SIZE,\n DEFAULT_REQUEST_TIMEOUT_MS,\n HttpError,\n httpRequest,\n isPermanentHttpError,\n} from './batch-buffer';\nimport { mergeCoreFields } from './entry-fields';\nimport { protectSecrets, urlSecrets } from './secret-config';\n\nexport interface CloudWatchTransportConfig {\n /** AWS region, e.g. `'us-east-1'`. Falls back to `AWS_REGION` env var. */\n region?: string;\n /** CloudWatch Logs group name. Created automatically if it does not exist. */\n logGroupName: string;\n /** CloudWatch Logs stream name. Defaults to hostname + process PID. */\n logStreamName?: string;\n /** Override the Logs endpoint, e.g. for LocalStack. Default: `https://logs.<region>.amazonaws.com`. */\n endpoint?: string;\n /** AWS access key ID. Falls back to the credential chain described above. */\n accessKeyId?: string;\n /** AWS secret access key. Used together with `accessKeyId`. */\n secretAccessKey?: string;\n /** AWS session token for temporary credentials. Used together with `accessKeyId`. */\n sessionToken?: string;\n /**\n * Number of log events to batch before flushing.\n * CloudWatch allows max 10,000 events per PutLogEvents call; larger values are capped.\n * @default 100\n */\n batchSize?: number;\n /**\n * Max ms between flushes even if batchSize is not reached.\n * @default 5000\n */\n flushIntervalMs?: number;\n /**\n * Enable EMF (Embedded Metric Format) — wraps log entries as CloudWatch\n * metric namespaces so numeric fields become CloudWatch Metrics automatically.\n * @default false\n */\n emf?: boolean;\n /** CloudWatch Metrics namespace used by EMF. @default 'Logixia' */\n emfNamespace?: string;\n /**\n * Payload fields published as EMF metrics. When set, only these numeric\n * fields become metrics; when unset every numeric payload field does (up to\n * the EMF limit of 100 per entry).\n */\n emfMetrics?: string[];\n /** Abort a request that has not finished after this many ms. @default 10000 */\n requestTimeoutMs?: number;\n /** Max buffered events; the oldest are dropped past this. @default 10000 */\n maxBufferSize?: number;\n /** Minimum log level to forward. */\n level?: string;\n}\n\nconst MAX_EVENTS_PER_PUT = 10_000;\nconst EMF_MAX_METRICS = 100;\n\n/** Error types worth retrying even though CloudWatch reports them as HTTP 400. */\nconst RETRYABLE_TYPES = new Set([\n 'ThrottlingException',\n 'ThrottledException',\n 'LimitExceededException',\n 'ServiceUnavailableException',\n 'ExpiredTokenException',\n 'ResourceNotFoundException',\n]);\n\nfunction awsErrorType(err: unknown): string | undefined {\n if (!(err instanceof HttpError)) return undefined;\n try {\n const type = (JSON.parse(err.body) as { __type?: string }).__type;\n return type?.split('#').pop();\n } catch {\n return undefined;\n }\n}\n\ninterface CwLogEvent {\n timestamp: number;\n message: string;\n}\n\n/**\n * AWS CloudWatch Logs transport with EMF support and batched PutLogEvents calls.\n */\nexport class CloudWatchTransport implements IAsyncTransport {\n public readonly name = 'cloudwatch';\n public readonly batchSize: number;\n public readonly flushInterval: number;\n public readonly level: string | undefined;\n\n private readonly buffer: BatchBuffer<CwLogEvent>;\n private readonly requestTimeoutMs: number;\n private flushTimer: NodeJS.Timeout | null = null;\n private readonly credentials: AwsCredentialProvider;\n private readonly endpoint: URL;\n private streamReady = false;\n\n private readonly region: string;\n private readonly logGroupName: string;\n private readonly logStreamName: string;\n private readonly emf: boolean;\n private readonly emfNamespace: string;\n private readonly emfMetrics: ReadonlySet<string> | undefined;\n\n constructor(config: CloudWatchTransportConfig) {\n this.region =\n config.region ??\n process.env['AWS_REGION'] ??\n process.env['AWS_DEFAULT_REGION'] ??\n 'us-east-1';\n this.logGroupName = config.logGroupName;\n this.logStreamName =\n config.logStreamName ?? `${process.env['HOSTNAME'] ?? 'node'}-${process.pid}`;\n this.credentials = new AwsCredentialProvider(config);\n this.endpoint = new URL(config.endpoint ?? `https://logs.${this.region}.amazonaws.com`);\n this.batchSize = Math.min(config.batchSize ?? 100, MAX_EVENTS_PER_PUT);\n this.emfNamespace = config.emfNamespace ?? 'Logixia';\n this.flushInterval = config.flushIntervalMs ?? 5000;\n this.emf = config.emf ?? false;\n this.emfMetrics = config.emfMetrics ? new Set(config.emfMetrics) : undefined;\n this.level = config.level;\n this.requestTimeoutMs = config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n this.buffer = new BatchBuffer<CwLogEvent>({\n name: 'CloudWatchTransport',\n batchSize: this.batchSize,\n maxBufferSize: config.maxBufferSize ?? DEFAULT_MAX_BUFFER_SIZE,\n send: (events) => this.putLogEvents(events),\n secrets: () => [...this.credentials.secretValues(), ...urlSecrets(this.endpoint)],\n shouldRetry: (err) =>\n !isPermanentHttpError(err) || RETRYABLE_TYPES.has(awsErrorType(err) ?? ''),\n });\n\n this.flushTimer = setInterval(() => {\n this.flush().catch(() => {});\n }, this.flushInterval);\n if (this.flushTimer.unref) this.flushTimer.unref();\n protectSecrets(this, ['credentials', 'endpoint']);\n }\n\n write(entry: TransportLogEntry): void {\n const timestamp = entry.timestamp ? new Date(entry.timestamp).getTime() : Date.now();\n const message = this.emf ? this.toEmf(entry) : stringifyForLog(entry);\n this.buffer.push({ timestamp, message });\n this.buffer.flushIfFull();\n }\n\n flush(): Promise<void> {\n return this.buffer.flush();\n }\n\n /**\n * Flush remaining events and stop the interval timer on shutdown. Without this\n * the manager's close() skips the transport (close was undefined) and any\n * buffered events 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 toEmf(entry: TransportLogEntry): string {\n const { level, message, data: payload, timestamp } = entry;\n const fields = mergeCoreFields({ _aws: undefined, level, message }, payload);\n const metricNames: string[] = [];\n for (const [k, v] of Object.entries(fields)) {\n if (k === '_aws' || k === 'level' || k === 'message' || typeof v !== 'number') continue;\n if (this.emfMetrics && !this.emfMetrics.has(k)) continue;\n if (metricNames.length < EMF_MAX_METRICS) metricNames.push(k);\n }\n fields['_aws'] = {\n Timestamp: timestamp ? new Date(timestamp).getTime() : Date.now(),\n CloudWatchMetrics:\n metricNames.length > 0\n ? [\n {\n Namespace: this.emfNamespace,\n Dimensions: [['level']],\n Metrics: metricNames.map((n) => ({ Name: n, Unit: 'None' })),\n },\n ]\n : [],\n };\n return stringifyForLog(fields);\n }\n\n private async putLogEvents(events: CwLogEvent[]): Promise<void> {\n await this.ensureStream();\n const logEvents = [...events].sort((a, b) => a.timestamp - b.timestamp);\n try {\n await this.call('PutLogEvents', {\n logGroupName: this.logGroupName,\n logStreamName: this.logStreamName,\n logEvents,\n });\n } catch (err) {\n const type = awsErrorType(err);\n if (type === 'DataAlreadyAcceptedException') return;\n if (type === 'ResourceNotFoundException') this.streamReady = false;\n if (type === 'ExpiredTokenException') this.credentials.invalidate();\n throw err;\n }\n }\n\n private async ensureStream(): Promise<void> {\n if (this.streamReady) return;\n try {\n await this.call('CreateLogGroup', { logGroupName: this.logGroupName });\n } catch (err) {\n if (awsErrorType(err) === 'ExpiredTokenException') this.credentials.invalidate();\n if (!(err instanceof HttpError)) throw err;\n if (awsErrorType(err) !== 'ResourceAlreadyExistsException') {\n internalWarn(`CloudWatchTransport: CreateLogGroup failed, continuing (${err.message})`);\n }\n }\n try {\n await this.call('CreateLogStream', {\n logGroupName: this.logGroupName,\n logStreamName: this.logStreamName,\n });\n } catch (err) {\n if (awsErrorType(err) !== 'ResourceAlreadyExistsException') throw err;\n }\n this.streamReady = true;\n }\n\n private async call(action: string, payload: Record<string, unknown>): Promise<void> {\n const credentials = await this.credentials.get();\n const body = stringifyForLog(payload);\n const { host } = this.endpoint;\n const headers = signV4({\n method: 'POST',\n path: '/',\n headers: {\n host,\n 'content-type': 'application/x-amz-json-1.1',\n 'x-amz-target': `Logs_20140328.${action}`,\n },\n body,\n region: this.region,\n service: 'logs',\n credentials,\n });\n await httpRequest({\n url: this.endpoint,\n headers,\n body,\n timeoutMs: this.requestTimeoutMs,\n label: `CloudWatch ${action}`,\n secrets: () => [\n ...this.credentials.secretValues(),\n headers['authorization'],\n headers['x-amz-security-token'],\n ...urlSecrets(this.endpoint),\n ],\n });\n }\n}\n"],"mappings":"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"}
|