logixia 1.13.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -16
- package/dist/{async-context-CwBNMm2E.mjs → async-context-BzJrbfQs.mjs} +8 -4
- package/dist/async-context-BzJrbfQs.mjs.map +1 -0
- package/dist/{async-context-CSHWoHMB.js → async-context-DyQQYq3I.js} +8 -4
- package/dist/async-context-DyQQYq3I.js.map +1 -0
- package/dist/{azure-monitor.transport-CG7ClkYj.d.ts → azure-monitor.transport-Cn_3Usvu.d.ts} +2 -2
- package/dist/{azure-monitor.transport-CG7ClkYj.d.ts.map → azure-monitor.transport-Cn_3Usvu.d.ts.map} +1 -1
- package/dist/{azure-monitor.transport-Cm74kXZS.d.mts → azure-monitor.transport-D7Da4RAb.d.mts} +2 -2
- package/dist/{azure-monitor.transport-Cm74kXZS.d.mts.map → azure-monitor.transport-D7Da4RAb.d.mts.map} +1 -1
- package/dist/azure.d.mts +2 -2
- package/dist/azure.d.ts +2 -2
- package/dist/browser.d.mts +9 -0
- package/dist/browser.d.mts.map +1 -1
- package/dist/browser.d.ts +9 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +43 -12
- package/dist/browser.js.map +1 -1
- package/dist/browser.mjs +43 -12
- package/dist/browser.mjs.map +1 -1
- package/dist/{logitron-logger.module-Bs3XYZgF.mjs → builder-0gEzRopq.mjs} +383 -1021
- package/dist/builder-0gEzRopq.mjs.map +1 -0
- package/dist/{logitron-logger.module-BsDZR5BH.js → builder-D44QktIo.js} +411 -1155
- package/dist/builder-D44QktIo.js.map +1 -0
- package/dist/cli/index.js +130 -65
- package/dist/cloudwatch.d.mts +2 -2
- package/dist/cloudwatch.d.ts +2 -2
- package/dist/cloudwatch.js +2 -1
- package/dist/cloudwatch.mjs +2 -1
- package/dist/{cloudwatch.transport-pNBNWJLt.js → cloudwatch.transport-BO1ahxw-.js} +26 -19
- package/dist/cloudwatch.transport-BO1ahxw-.js.map +1 -0
- package/dist/{cloudwatch.transport-yBwm4OeO.mjs → cloudwatch.transport-DZ6ies7g.mjs} +26 -19
- package/dist/cloudwatch.transport-DZ6ies7g.mjs.map +1 -0
- package/dist/{cloudwatch.transport-CGHY4buE.d.mts → cloudwatch.transport-DsEq633o.d.ts} +9 -2
- package/dist/cloudwatch.transport-DsEq633o.d.ts.map +1 -0
- package/dist/{cloudwatch.transport-DK_8cKd3.d.ts → cloudwatch.transport-UlyZFWMn.d.mts} +9 -2
- package/dist/cloudwatch.transport-UlyZFWMn.d.mts.map +1 -0
- package/dist/{coerce.utils-BN980Y9V.js → coerce.utils-B-LilukN.js} +1 -1
- package/dist/{coerce.utils-BN980Y9V.js.map → coerce.utils-B-LilukN.js.map} +1 -1
- package/dist/{coerce.utils-Dxv4_ikC.mjs → coerce.utils-Cu6IUTgX.mjs} +1 -1
- package/dist/{coerce.utils-Dxv4_ikC.mjs.map → coerce.utils-Cu6IUTgX.mjs.map} +1 -1
- package/dist/correlation.d.mts +24 -6
- package/dist/correlation.d.mts.map +1 -1
- package/dist/correlation.d.ts +24 -6
- package/dist/correlation.d.ts.map +1 -1
- package/dist/correlation.js +41 -16
- package/dist/correlation.js.map +1 -1
- package/dist/correlation.mjs +41 -16
- package/dist/correlation.mjs.map +1 -1
- package/dist/entry-fields-BJkuPnIg.mjs +30 -0
- package/dist/entry-fields-BJkuPnIg.mjs.map +1 -0
- package/dist/entry-fields-BvOLFlJ4.js +36 -0
- package/dist/entry-fields-BvOLFlJ4.js.map +1 -0
- package/dist/gcp.d.mts +2 -2
- package/dist/gcp.d.ts +2 -2
- package/dist/gcp.js +2 -1
- package/dist/gcp.mjs +2 -1
- package/dist/{gcp.transport-BOhkVKlI.d.ts → gcp.transport-B7oc97sG.d.ts} +2 -2
- package/dist/gcp.transport-B7oc97sG.d.ts.map +1 -0
- package/dist/{gcp.transport-SHdtc1n0.js → gcp.transport-CHV8MGgz.js} +5 -5
- package/dist/gcp.transport-CHV8MGgz.js.map +1 -0
- package/dist/{gcp.transport-BJuNRFe_.mjs → gcp.transport-DBX5TPIy.mjs} +5 -5
- package/dist/gcp.transport-DBX5TPIy.mjs.map +1 -0
- package/dist/{gcp.transport-Bi6CUqZR.d.mts → gcp.transport-GrJurKo8.d.mts} +2 -2
- package/dist/gcp.transport-GrJurKo8.d.mts.map +1 -0
- package/dist/{index-BPKwwERo.d.mts → index-3mw5gaCw.d.mts} +2 -2
- package/dist/{index-BPKwwERo.d.mts.map → index-3mw5gaCw.d.mts.map} +1 -1
- package/dist/{index-C1X-TE5I.d.ts → index-DhIoploR.d.ts} +2 -2
- package/dist/{index-C1X-TE5I.d.ts.map → index-DhIoploR.d.ts.map} +1 -1
- package/dist/index.d.mts +99 -137
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +99 -137
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +146 -510
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +99 -431
- package/dist/index.mjs.map +1 -1
- package/dist/logitron-logger-BFDSO8Io.d.mts +257 -0
- package/dist/logitron-logger-BFDSO8Io.d.mts.map +1 -0
- package/dist/logitron-logger-UVeN-mQm.d.ts +257 -0
- package/dist/logitron-logger-UVeN-mQm.d.ts.map +1 -0
- package/dist/middleware.d.mts +11 -4
- package/dist/middleware.d.mts.map +1 -1
- package/dist/middleware.d.ts +11 -4
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +148 -24
- package/dist/middleware.js.map +1 -1
- package/dist/middleware.mjs +148 -24
- package/dist/middleware.mjs.map +1 -1
- package/dist/nest.d.mts +481 -6
- package/dist/nest.d.mts.map +1 -1
- package/dist/nest.d.ts +481 -6
- package/dist/nest.d.ts.map +1 -1
- package/dist/nest.js +884 -13
- package/dist/nest.js.map +1 -0
- package/dist/nest.mjs +863 -6
- package/dist/nest.mjs.map +1 -0
- package/dist/{search-CFQRISUv.mjs → search-BFbu_oVn.mjs} +35 -12
- package/dist/search-BFbu_oVn.mjs.map +1 -0
- package/dist/{search-njTI2hdo.js → search-C4V0OMEn.js} +35 -12
- package/dist/search-C4V0OMEn.js.map +1 -0
- package/dist/{search-DujhR94O.d.ts → search-CNh9uVwR.d.ts} +2 -3
- package/dist/search-CNh9uVwR.d.ts.map +1 -0
- package/dist/{search-CQOo-Iq6.d.mts → search-DXANsQ2n.d.mts} +2 -3
- package/dist/search-DXANsQ2n.d.mts.map +1 -0
- package/dist/search.d.mts +3 -3
- package/dist/search.d.ts +3 -3
- package/dist/search.js +2 -2
- package/dist/search.mjs +2 -2
- package/dist/slack.transport-BZzoXDPn.d.mts +112 -0
- package/dist/slack.transport-BZzoXDPn.d.mts.map +1 -0
- package/dist/slack.transport-BfJRouB2.js +654 -0
- package/dist/slack.transport-BfJRouB2.js.map +1 -0
- package/dist/slack.transport-Bzw7sucI.mjs +643 -0
- package/dist/slack.transport-Bzw7sucI.mjs.map +1 -0
- package/dist/slack.transport-CXjQYOes.d.ts +112 -0
- package/dist/slack.transport-CXjQYOes.d.ts.map +1 -0
- package/dist/testing.d.mts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/trace.utils-CvXgaiQT.mjs +278 -0
- package/dist/trace.utils-CvXgaiQT.mjs.map +1 -0
- package/dist/trace.utils-DpBOLDtq.js +358 -0
- package/dist/trace.utils-DpBOLDtq.js.map +1 -0
- package/dist/{transport.manager-D6KL3t9V.mjs → transport.manager-BiuCAJd2.mjs} +526 -160
- package/dist/transport.manager-BiuCAJd2.mjs.map +1 -0
- package/dist/{transport.manager-BivyUTtU.js → transport.manager-CXbKKdVE.js} +537 -159
- package/dist/transport.manager-CXbKKdVE.js.map +1 -0
- package/dist/{transport.types-B5vcyv2k.d.mts → transport.types-BMnurPcc.d.mts} +23 -3
- package/dist/transport.types-BMnurPcc.d.mts.map +1 -0
- package/dist/{transport.types-BuY84TwO.d.ts → transport.types-CGoHpWQR.d.ts} +23 -3
- package/dist/transport.types-CGoHpWQR.d.ts.map +1 -0
- package/dist/transports.d.mts +50 -20
- package/dist/transports.d.mts.map +1 -1
- package/dist/transports.d.ts +50 -20
- package/dist/transports.d.ts.map +1 -1
- package/dist/transports.js +9 -5
- package/dist/transports.mjs +8 -6
- package/dist/worker-entry.js +307 -55
- package/dist/worker.d.mts +2 -2
- package/dist/worker.d.ts +2 -2
- package/dist/worker.js +1 -1
- package/dist/worker.mjs +1 -1
- package/dist/{worker.transport-CfH6z37Z.js → worker.transport-BdPxu3PN.js} +1 -1
- package/dist/{worker.transport-CfH6z37Z.js.map → worker.transport-BdPxu3PN.js.map} +1 -1
- package/dist/{worker.transport-mKXgNK0L.d.ts → worker.transport-CdzSZJmw.d.ts} +2 -2
- package/dist/{worker.transport-mKXgNK0L.d.ts.map → worker.transport-CdzSZJmw.d.ts.map} +1 -1
- package/dist/{worker.transport-BP8Q28Z2.d.mts → worker.transport-JvGPog3C.d.mts} +2 -2
- package/dist/{worker.transport-BP8Q28Z2.d.mts.map → worker.transport-JvGPog3C.d.mts.map} +1 -1
- package/dist/{worker.transport-BhMyvqQ2.mjs → worker.transport-lPxO2MVL.mjs} +1 -1
- package/dist/{worker.transport-BhMyvqQ2.mjs.map → worker.transport-lPxO2MVL.mjs.map} +1 -1
- package/package.json +27 -14
- package/dist/.tsbuildinfo +0 -1
- package/dist/async-context-CSHWoHMB.js.map +0 -1
- package/dist/async-context-CwBNMm2E.mjs.map +0 -1
- package/dist/cloudwatch.transport-CGHY4buE.d.mts.map +0 -1
- package/dist/cloudwatch.transport-DK_8cKd3.d.ts.map +0 -1
- package/dist/cloudwatch.transport-pNBNWJLt.js.map +0 -1
- package/dist/cloudwatch.transport-yBwm4OeO.mjs.map +0 -1
- package/dist/gcp.transport-BJuNRFe_.mjs.map +0 -1
- package/dist/gcp.transport-BOhkVKlI.d.ts.map +0 -1
- package/dist/gcp.transport-Bi6CUqZR.d.mts.map +0 -1
- package/dist/gcp.transport-SHdtc1n0.js.map +0 -1
- package/dist/logitron-logger.module-BdG1Jnpk.d.mts +0 -618
- package/dist/logitron-logger.module-BdG1Jnpk.d.mts.map +0 -1
- package/dist/logitron-logger.module-Bs3XYZgF.mjs.map +0 -1
- package/dist/logitron-logger.module-BsDZR5BH.js.map +0 -1
- package/dist/logitron-logger.module-CbXy2gfW.d.ts +0 -618
- package/dist/logitron-logger.module-CbXy2gfW.d.ts.map +0 -1
- package/dist/search-CFQRISUv.mjs.map +0 -1
- package/dist/search-CQOo-Iq6.d.mts.map +0 -1
- package/dist/search-DujhR94O.d.ts.map +0 -1
- package/dist/search-njTI2hdo.js.map +0 -1
- package/dist/transport.manager-BivyUTtU.js.map +0 -1
- package/dist/transport.manager-D6KL3t9V.mjs.map +0 -1
- package/dist/transport.types-B5vcyv2k.d.mts.map +0 -1
- package/dist/transport.types-BuY84TwO.d.ts.map +0 -1
- package/scripts/postinstall.js +0 -61
|
@@ -1,14 +1,33 @@
|
|
|
1
1
|
import { t as __require } from "./chunk-DLSkYcPk.mjs";
|
|
2
2
|
import { n as internalLog, r as internalWarn, t as internalError } from "./internal-log-Cm8SOWSV.mjs";
|
|
3
3
|
import { i as stringifyForLog } from "./safe-stringify-DJ66tW5I.mjs";
|
|
4
|
-
import { t as
|
|
4
|
+
import { t as mergeCoreFields } from "./entry-fields-BJkuPnIg.mjs";
|
|
5
|
+
import { t as safeToString } from "./coerce.utils-Cu6IUTgX.mjs";
|
|
5
6
|
import * as fs from "node:fs";
|
|
6
7
|
import * as path$1 from "node:path";
|
|
7
8
|
import { EventEmitter } from "node:events";
|
|
8
|
-
import { pipeline } from "node:stream/promises";
|
|
9
9
|
import { promisify } from "node:util";
|
|
10
|
-
import { createGzip } from "node:zlib";
|
|
10
|
+
import { createGzip, gzip } from "node:zlib";
|
|
11
|
+
import { pipeline } from "node:stream/promises";
|
|
11
12
|
|
|
13
|
+
//#region src/utils/sanitize.utils.ts
|
|
14
|
+
/**
|
|
15
|
+
* Control-character stripping for text-mode log output.
|
|
16
|
+
*
|
|
17
|
+
* Line breaks become the visible escapes `\\n` / `\\r`; other C0 characters
|
|
18
|
+
* (except tab), DEL and C1 characters are removed, so user-supplied text cannot
|
|
19
|
+
* inject ANSI escapes, overwrite lines, or forge extra log entries.
|
|
20
|
+
*/
|
|
21
|
+
const CONTROL_CHARS_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]/g;
|
|
22
|
+
const VISIBLE_ESCAPES = {
|
|
23
|
+
"\n": "\\n",
|
|
24
|
+
"\r": "\\r"
|
|
25
|
+
};
|
|
26
|
+
function stripControlChars(value) {
|
|
27
|
+
return value.replace(CONTROL_CHARS_RE, (ch) => VISIBLE_ESCAPES[ch] ?? "");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
12
31
|
//#region src/transports/console.transport.ts
|
|
13
32
|
/**
|
|
14
33
|
* Writes log entries to stdout (info/debug/verbose) and stderr (error/warn).
|
|
@@ -39,9 +58,8 @@ var ConsoleTransport = class ConsoleTransport {
|
|
|
39
58
|
["brightwhite", "\x1B[97m"],
|
|
40
59
|
["reset", "\x1B[0m"]
|
|
41
60
|
]);
|
|
42
|
-
static #_2 = this.CONTROL_CHARS_RE = /[\x00-\x08\x0B-\x1F\x7F-\x9F]/g;
|
|
43
61
|
static sanitize(value) {
|
|
44
|
-
return safeToString(value)
|
|
62
|
+
return stripControlChars(safeToString(value));
|
|
45
63
|
}
|
|
46
64
|
constructor(config = {}) {
|
|
47
65
|
this.config = config;
|
|
@@ -54,16 +72,15 @@ var ConsoleTransport = class ConsoleTransport {
|
|
|
54
72
|
(lvl === "error" || lvl === "warn" ? process.stderr : process.stdout).write(formatted);
|
|
55
73
|
}
|
|
56
74
|
formatEntry(entry) {
|
|
57
|
-
if (this.config.format === "json") return stringifyForLog({
|
|
75
|
+
if (this.config.format === "json") return stringifyForLog(mergeCoreFields({
|
|
58
76
|
timestamp: this.config.timestamp !== false ? entry.timestamp.toISOString() : void 0,
|
|
59
77
|
level: entry.level,
|
|
60
78
|
message: entry.message,
|
|
61
|
-
...entry.data || {},
|
|
62
79
|
context: entry.context,
|
|
63
80
|
traceId: entry.traceId,
|
|
64
81
|
appName: entry.appName,
|
|
65
82
|
environment: entry.environment
|
|
66
|
-
});
|
|
83
|
+
}, entry.data));
|
|
67
84
|
const parts = [];
|
|
68
85
|
if (this.config.timestamp !== false) {
|
|
69
86
|
const timestamp = entry.timestamp.toISOString();
|
|
@@ -111,6 +128,47 @@ var ConsoleTransport = class ConsoleTransport {
|
|
|
111
128
|
}
|
|
112
129
|
};
|
|
113
130
|
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region src/transports/buffer-cap.ts
|
|
133
|
+
const DEFAULT_BUFFER_CAP = 1e4;
|
|
134
|
+
const DROP_WARN_INTERVAL_MS$1 = 5e3;
|
|
135
|
+
/**
|
|
136
|
+
* Keeps an in-memory retry buffer bounded. Past `max` the oldest items are
|
|
137
|
+
* dropped, counted, and reported through internalWarn at most every few seconds.
|
|
138
|
+
*
|
|
139
|
+
* `requested` must be an integer of at least 1, otherwise the default is used.
|
|
140
|
+
* A cap below `batchSize` is raised to `batchSize` so one batch always fits.
|
|
141
|
+
*/
|
|
142
|
+
var BufferCap = class {
|
|
143
|
+
constructor(name, requested, batchSize, fallback = DEFAULT_BUFFER_CAP) {
|
|
144
|
+
this.name = name;
|
|
145
|
+
this.dropped = 0;
|
|
146
|
+
this.lastWarning = 0;
|
|
147
|
+
let max = fallback;
|
|
148
|
+
if (requested !== void 0) if (Number.isInteger(requested) && requested >= 1) max = requested;
|
|
149
|
+
else internalWarn(`${name}: maxBufferSize ${String(requested)} is not a positive integer; using ${fallback}`);
|
|
150
|
+
this.max = Math.max(max, batchSize);
|
|
151
|
+
}
|
|
152
|
+
/** Drops the oldest items beyond the cap, in place. */
|
|
153
|
+
enforce(items) {
|
|
154
|
+
const excess = items.length - this.max;
|
|
155
|
+
if (excess <= 0) return;
|
|
156
|
+
items.splice(0, excess);
|
|
157
|
+
this.note(excess);
|
|
158
|
+
}
|
|
159
|
+
note(count) {
|
|
160
|
+
this.dropped += count;
|
|
161
|
+
this.report(DROP_WARN_INTERVAL_MS$1);
|
|
162
|
+
}
|
|
163
|
+
report(minGapMs) {
|
|
164
|
+
const now = Date.now();
|
|
165
|
+
if (this.dropped === 0 || now - this.lastWarning < minGapMs) return;
|
|
166
|
+
internalWarn(`${this.name}: buffer full (${this.max}), dropped ${this.dropped} oldest entr${this.dropped === 1 ? "y" : "ies"}`);
|
|
167
|
+
this.dropped = 0;
|
|
168
|
+
this.lastWarning = now;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
114
172
|
//#endregion
|
|
115
173
|
//#region src/transports/database.transport.ts
|
|
116
174
|
/**
|
|
@@ -121,6 +179,80 @@ const POSTGRES_MAX_PARAMS = 65535;
|
|
|
121
179
|
const POSTGRES_COLUMNS = 8;
|
|
122
180
|
const POSTGRES_ROWS_PER_INSERT = Math.floor(POSTGRES_MAX_PARAMS / POSTGRES_COLUMNS);
|
|
123
181
|
const MYSQL_ROWS_PER_INSERT = 5e3;
|
|
182
|
+
/** Postgres rejects NUL in TEXT and JSONB. */
|
|
183
|
+
function stripNul(value) {
|
|
184
|
+
return typeof value === "string" ? value.split("\0").join("") : value;
|
|
185
|
+
}
|
|
186
|
+
/** JSONB also rejects the \u0000 escape, which JSON.stringify writes for a NUL. */
|
|
187
|
+
function stripJsonNulEscape(value) {
|
|
188
|
+
if (typeof value !== "string") return value;
|
|
189
|
+
return value.replace(/(?<!\\)((?:\\\\)*)\\u0000/g, "$1");
|
|
190
|
+
}
|
|
191
|
+
const PG_DATA_CLASSES = [
|
|
192
|
+
"22",
|
|
193
|
+
"23",
|
|
194
|
+
"54"
|
|
195
|
+
];
|
|
196
|
+
const MYSQL_DATA_CODES = new Set([
|
|
197
|
+
"ER_DATA_TOO_LONG",
|
|
198
|
+
"ER_TRUNCATED_WRONG_VALUE",
|
|
199
|
+
"ER_TRUNCATED_WRONG_VALUE_FOR_FIELD",
|
|
200
|
+
"ER_BAD_NULL_ERROR",
|
|
201
|
+
"ER_WARN_DATA_OUT_OF_RANGE",
|
|
202
|
+
"ER_DUP_ENTRY",
|
|
203
|
+
"ER_INVALID_JSON_TEXT",
|
|
204
|
+
"ER_INVALID_CHARACTER_STRING"
|
|
205
|
+
]);
|
|
206
|
+
const MYSQL_DATA_ERRNOS = new Set([
|
|
207
|
+
1048,
|
|
208
|
+
1062,
|
|
209
|
+
1264,
|
|
210
|
+
1292,
|
|
211
|
+
1366,
|
|
212
|
+
1406,
|
|
213
|
+
3140
|
|
214
|
+
]);
|
|
215
|
+
const SQLITE_DATA_CODES = new Set([
|
|
216
|
+
"SQLITE_CONSTRAINT",
|
|
217
|
+
"SQLITE_TOOBIG",
|
|
218
|
+
"SQLITE_MISMATCH"
|
|
219
|
+
]);
|
|
220
|
+
const MONGO_DATA_CODES = new Set([
|
|
221
|
+
2,
|
|
222
|
+
121,
|
|
223
|
+
10334,
|
|
224
|
+
11e3
|
|
225
|
+
]);
|
|
226
|
+
function isDataErrorLayer(type, e) {
|
|
227
|
+
const code = e.code;
|
|
228
|
+
switch (type) {
|
|
229
|
+
case "postgresql": return typeof code === "string" && PG_DATA_CLASSES.includes(code.slice(0, 2));
|
|
230
|
+
case "mysql": return typeof code === "string" && MYSQL_DATA_CODES.has(code) || typeof e.errno === "number" && MYSQL_DATA_ERRNOS.has(e.errno);
|
|
231
|
+
case "sqlite": return typeof code === "string" && (SQLITE_DATA_CODES.has(code) || code.startsWith("SQLITE_CONSTRAINT_"));
|
|
232
|
+
case "mongodb": return e.name === "BSONObjectTooLarge" || typeof code === "number" && MONGO_DATA_CODES.has(code);
|
|
233
|
+
default: return false;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* True when the database refused the data itself (bad value, constraint, size),
|
|
238
|
+
* which retrying cannot fix. Connection, timeout, auth and unknown errors are
|
|
239
|
+
* not data errors and must be retried, never dropped.
|
|
240
|
+
*/
|
|
241
|
+
function isDataError(type, error) {
|
|
242
|
+
let current = error;
|
|
243
|
+
for (let depth = 0; depth < 3 && current && typeof current === "object"; depth += 1) {
|
|
244
|
+
if (isDataErrorLayer(type, current)) return true;
|
|
245
|
+
current = current.cause;
|
|
246
|
+
}
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
/** A write that stored part of a batch: only `remaining` still needs to be written. */
|
|
250
|
+
var PartialWriteError = class extends Error {
|
|
251
|
+
constructor(message, remaining, cause) {
|
|
252
|
+
super(message, { cause });
|
|
253
|
+
this.remaining = remaining;
|
|
254
|
+
}
|
|
255
|
+
};
|
|
124
256
|
function chunk(items, size) {
|
|
125
257
|
const chunks = [];
|
|
126
258
|
for (let i = 0; i < items.length; i += size) chunks.push(items.slice(i, i + size));
|
|
@@ -149,6 +281,7 @@ var DatabaseTransport = class {
|
|
|
149
281
|
this.isConnected = false;
|
|
150
282
|
this.batchSize = config.batchSize || 100;
|
|
151
283
|
this.flushInterval = config.flushInterval || 5e3;
|
|
284
|
+
this.cap = new BufferCap("DatabaseTransport", config.maxBufferSize, this.batchSize);
|
|
152
285
|
if (config.filter) this.filter = config.filter;
|
|
153
286
|
if (config.table) validateSqlIdentifier(config.table, "table");
|
|
154
287
|
this.setupFlushTimer();
|
|
@@ -160,6 +293,7 @@ var DatabaseTransport = class {
|
|
|
160
293
|
}
|
|
161
294
|
addToBatch(entry) {
|
|
162
295
|
this.batch.push(entry);
|
|
296
|
+
this.cap.enforce(this.batch);
|
|
163
297
|
}
|
|
164
298
|
async flush() {
|
|
165
299
|
if (!this.flushPromise) this.flushPromise = this.drain().finally(() => {
|
|
@@ -168,37 +302,97 @@ var DatabaseTransport = class {
|
|
|
168
302
|
await this.flushPromise;
|
|
169
303
|
}
|
|
170
304
|
/**
|
|
171
|
-
* Drains the
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
305
|
+
* Drains the buffer to the database one batch at a time. A batch is detached
|
|
306
|
+
* SYNCHRONOUSLY before awaiting the write, so entries appended by concurrent
|
|
307
|
+
* write() calls land in a fresh array and are never written twice.
|
|
308
|
+
*
|
|
309
|
+
* A failure that is not a data error (connection, timeout, auth, unknown) puts
|
|
310
|
+
* the batch back at the front of the buffer, bounded by `maxBufferSize`, and
|
|
311
|
+
* stops the loop so a down database is not hammered. A data error means the
|
|
312
|
+
* database refused some entry itself, so that batch alone is split to find and
|
|
313
|
+
* drop the refused entries; see isolate().
|
|
177
314
|
*/
|
|
178
315
|
async drain() {
|
|
179
316
|
while (this.batch.length > 0) {
|
|
180
|
-
const
|
|
181
|
-
this.batch = [];
|
|
317
|
+
const entries = this.batch.splice(0, this.batchSize);
|
|
182
318
|
try {
|
|
183
|
-
|
|
184
|
-
case "mongodb":
|
|
185
|
-
await this.flushToMongoDB(entriesToFlush);
|
|
186
|
-
break;
|
|
187
|
-
case "postgresql":
|
|
188
|
-
await this.flushToPostgreSQL(entriesToFlush);
|
|
189
|
-
break;
|
|
190
|
-
case "mysql":
|
|
191
|
-
await this.flushToMySQL(entriesToFlush);
|
|
192
|
-
break;
|
|
193
|
-
case "sqlite":
|
|
194
|
-
await this.flushToSQLite(entriesToFlush);
|
|
195
|
-
break;
|
|
196
|
-
default: throw new Error(`Unsupported database type: ${this.config.type}`);
|
|
197
|
-
}
|
|
319
|
+
await this.writeEntries(entries);
|
|
198
320
|
} catch (error) {
|
|
199
321
|
internalError("Database flush error", error);
|
|
200
|
-
|
|
201
|
-
|
|
322
|
+
if (error instanceof PartialWriteError) {
|
|
323
|
+
this.requeue(error.remaining);
|
|
324
|
+
throw error.cause;
|
|
325
|
+
}
|
|
326
|
+
if (!isDataError(this.config.type, error)) {
|
|
327
|
+
this.requeue(entries);
|
|
328
|
+
throw error;
|
|
329
|
+
}
|
|
330
|
+
const state = {
|
|
331
|
+
budget: 2 * this.batchSize,
|
|
332
|
+
rejected: 0,
|
|
333
|
+
requeue: [],
|
|
334
|
+
stopped: false
|
|
335
|
+
};
|
|
336
|
+
await this.isolate(entries, state);
|
|
337
|
+
if (state.rejected > 0) internalWarn(`DatabaseTransport: dropped ${state.rejected} log entr${state.rejected === 1 ? "y" : "ies"} the database rejected`);
|
|
338
|
+
this.requeue(state.requeue);
|
|
339
|
+
if (state.stopped) throw state.error;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
requeue(entries) {
|
|
344
|
+
if (entries.length === 0) return;
|
|
345
|
+
this.batch = entries.concat(this.batch);
|
|
346
|
+
this.cap.enforce(this.batch);
|
|
347
|
+
}
|
|
348
|
+
async writeEntries(entries) {
|
|
349
|
+
switch (this.config.type) {
|
|
350
|
+
case "mongodb":
|
|
351
|
+
await this.flushToMongoDB(entries);
|
|
352
|
+
break;
|
|
353
|
+
case "postgresql":
|
|
354
|
+
await this.flushToPostgreSQL(entries);
|
|
355
|
+
break;
|
|
356
|
+
case "mysql":
|
|
357
|
+
await this.flushToMySQL(entries);
|
|
358
|
+
break;
|
|
359
|
+
case "sqlite":
|
|
360
|
+
await this.flushToSQLite(entries);
|
|
361
|
+
break;
|
|
362
|
+
default: throw new Error(`Unsupported database type: ${this.config.type}`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* `entries` failed with a data error. Splits them in half until the refused
|
|
367
|
+
* entries are alone and drops those. A write that fails with anything but a
|
|
368
|
+
* data error, or running out of the per-flush write budget, stops the search:
|
|
369
|
+
* the entries not yet written go back to the buffer.
|
|
370
|
+
*/
|
|
371
|
+
async isolate(entries, state) {
|
|
372
|
+
if (entries.length === 1) {
|
|
373
|
+
state.rejected += 1;
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const mid = Math.ceil(entries.length / 2);
|
|
377
|
+
for (const half of [entries.slice(0, mid), entries.slice(mid)]) {
|
|
378
|
+
if (state.stopped || state.budget <= 0) {
|
|
379
|
+
state.requeue.push(...half);
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
state.budget -= 1;
|
|
383
|
+
try {
|
|
384
|
+
await this.writeEntries(half);
|
|
385
|
+
} catch (error) {
|
|
386
|
+
if (error instanceof PartialWriteError) {
|
|
387
|
+
state.requeue.push(...error.remaining);
|
|
388
|
+
state.stopped = true;
|
|
389
|
+
state.error = error.cause;
|
|
390
|
+
} else if (isDataError(this.config.type, error)) await this.isolate(half, state);
|
|
391
|
+
else {
|
|
392
|
+
state.requeue.push(...half);
|
|
393
|
+
state.stopped = true;
|
|
394
|
+
state.error = error;
|
|
395
|
+
}
|
|
202
396
|
}
|
|
203
397
|
}
|
|
204
398
|
}
|
|
@@ -323,7 +517,26 @@ var DatabaseTransport = class {
|
|
|
323
517
|
appName: entry.appName,
|
|
324
518
|
environment: entry.environment
|
|
325
519
|
}));
|
|
326
|
-
|
|
520
|
+
try {
|
|
521
|
+
await collection.insertMany(documents, { ordered: false });
|
|
522
|
+
} catch (error) {
|
|
523
|
+
const raw = error.writeErrors;
|
|
524
|
+
let list = [];
|
|
525
|
+
if (Array.isArray(raw)) list = raw;
|
|
526
|
+
else if (raw) list = [raw];
|
|
527
|
+
const writeErrors = list;
|
|
528
|
+
if (writeErrors.length === 0) throw error;
|
|
529
|
+
const remaining = [];
|
|
530
|
+
let rejected = 0;
|
|
531
|
+
for (const writeError of writeErrors) {
|
|
532
|
+
const entry = typeof writeError.index === "number" ? entries[writeError.index] : void 0;
|
|
533
|
+
if (!entry) throw error;
|
|
534
|
+
if (isDataError("mongodb", writeError)) rejected += 1;
|
|
535
|
+
else remaining.push(entry);
|
|
536
|
+
}
|
|
537
|
+
if (rejected > 0) internalWarn(`DatabaseTransport: dropped ${rejected} log entr${rejected === 1 ? "y" : "ies"} the database rejected`);
|
|
538
|
+
if (remaining.length > 0) throw new PartialWriteError("MongoDB insert partially failed", remaining, error);
|
|
539
|
+
}
|
|
327
540
|
}
|
|
328
541
|
async flushToPostgreSQL(entries) {
|
|
329
542
|
const tableName = this.config.table || "logs";
|
|
@@ -336,7 +549,7 @@ var DatabaseTransport = class {
|
|
|
336
549
|
entry.traceId,
|
|
337
550
|
entry.appName,
|
|
338
551
|
entry.environment
|
|
339
|
-
]), POSTGRES_ROWS_PER_INSERT);
|
|
552
|
+
].map((value, column) => stripNul(column === 3 ? stripJsonNulEscape(value) : value))), POSTGRES_ROWS_PER_INSERT);
|
|
340
553
|
const insertChunk = async (rows) => {
|
|
341
554
|
const query = `
|
|
342
555
|
INSERT INTO ${tableName}
|
|
@@ -496,6 +709,7 @@ var DatabaseTransport = class {
|
|
|
496
709
|
internalError("Database flush during close failed; entries remain buffered", error);
|
|
497
710
|
}
|
|
498
711
|
if (this.batch.length > 0) internalError(`Database transport closing with ${this.batch.length} unflushed log entr${this.batch.length === 1 ? "y" : "ies"} after ${MAX_CLOSE_FLUSH_ATTEMPTS} attempts`);
|
|
712
|
+
this.cap.report(0);
|
|
499
713
|
if (this.connection) switch (this.config.type) {
|
|
500
714
|
case "mongodb":
|
|
501
715
|
await this.connection.close();
|
|
@@ -552,6 +766,17 @@ var DatabaseTransport = class {
|
|
|
552
766
|
|
|
553
767
|
//#endregion
|
|
554
768
|
//#region src/transports/analytics.transport.ts
|
|
769
|
+
/**
|
|
770
|
+
* Thrown by sendBatch() when part of a batch was already delivered. drain()
|
|
771
|
+
* requeues only `unsent`, so delivered entries are not sent twice.
|
|
772
|
+
*/
|
|
773
|
+
var PartialBatchError = class extends Error {
|
|
774
|
+
constructor(message, unsent, options) {
|
|
775
|
+
super(message, options);
|
|
776
|
+
this.unsent = unsent;
|
|
777
|
+
this.name = "PartialBatchError";
|
|
778
|
+
}
|
|
779
|
+
};
|
|
555
780
|
var AnalyticsTransport = class {
|
|
556
781
|
constructor(name, config) {
|
|
557
782
|
this.batch = [];
|
|
@@ -567,6 +792,7 @@ var AnalyticsTransport = class {
|
|
|
567
792
|
this.level = config.level;
|
|
568
793
|
this.batchSize = this.config.batchSize || 50;
|
|
569
794
|
this.flushInterval = this.config.flushInterval || 1e4;
|
|
795
|
+
this.cap = new BufferCap(name, config.maxBufferSize, this.batchSize);
|
|
570
796
|
}
|
|
571
797
|
async write(entry) {
|
|
572
798
|
if (!this.isReady) await this.ensureReady();
|
|
@@ -576,6 +802,7 @@ var AnalyticsTransport = class {
|
|
|
576
802
|
}
|
|
577
803
|
addToBatch(entry) {
|
|
578
804
|
this.batch.push(entry);
|
|
805
|
+
this.cap.enforce(this.batch);
|
|
579
806
|
if (this.batch.length >= (this.config.batchSize || 50)) this.flush().catch((err) => internalError(`${this.name} batch flush failed`, err));
|
|
580
807
|
else if (!this.batchTimer && this.config.flushInterval) {
|
|
581
808
|
var _this$batchTimer$unre, _this$batchTimer;
|
|
@@ -610,7 +837,8 @@ var AnalyticsTransport = class {
|
|
|
610
837
|
await this.sendBatch(entriesToSend);
|
|
611
838
|
} catch (error) {
|
|
612
839
|
internalError(`Analytics transport ${this.name} flush failed`, error);
|
|
613
|
-
this.batch.unshift(...entriesToSend);
|
|
840
|
+
this.batch.unshift(...error instanceof PartialBatchError ? error.unsent : entriesToSend);
|
|
841
|
+
this.cap.enforce(this.batch);
|
|
614
842
|
return;
|
|
615
843
|
}
|
|
616
844
|
}
|
|
@@ -623,25 +851,36 @@ var AnalyticsTransport = class {
|
|
|
623
851
|
const MAX_CLOSE_FLUSH_ATTEMPTS = 3;
|
|
624
852
|
for (let attempt = 0; attempt < MAX_CLOSE_FLUSH_ATTEMPTS && this.batch.length > 0; attempt += 1) await this.flush();
|
|
625
853
|
if (this.batch.length > 0) internalError(`Analytics transport ${this.name} closing with ${this.batch.length} unflushed entr${this.batch.length === 1 ? "y" : "ies"} after ${MAX_CLOSE_FLUSH_ATTEMPTS} attempts`);
|
|
854
|
+
this.cap.report(0);
|
|
626
855
|
await this.cleanup();
|
|
627
856
|
}
|
|
628
857
|
shouldSkipEntry(entry) {
|
|
629
858
|
return ["debug", "trace"].includes(entry.level.toLowerCase());
|
|
630
859
|
}
|
|
631
860
|
transformEntry(entry) {
|
|
632
|
-
const
|
|
861
|
+
const core = {
|
|
633
862
|
timestamp: entry.timestamp.toISOString(),
|
|
634
863
|
level: entry.level,
|
|
635
864
|
message: entry.message,
|
|
636
|
-
|
|
865
|
+
context: entry.context,
|
|
866
|
+
traceId: entry.traceId,
|
|
867
|
+
appName: entry.appName,
|
|
868
|
+
environment: entry.environment
|
|
637
869
|
};
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
870
|
+
const transformed = mergeCoreFields(core, entry.data, this.reservedKeys());
|
|
871
|
+
for (const key of [
|
|
872
|
+
"context",
|
|
873
|
+
"traceId",
|
|
874
|
+
"appName",
|
|
875
|
+
"environment"
|
|
876
|
+
]) if (!core[key]) delete transformed[key];
|
|
642
877
|
if (this.config.customProperties) Object.assign(transformed, this.config.customProperties);
|
|
643
878
|
return transformed;
|
|
644
879
|
}
|
|
880
|
+
/** Provider-specific field names a payload key must not replace. */
|
|
881
|
+
reservedKeys() {
|
|
882
|
+
return [];
|
|
883
|
+
}
|
|
645
884
|
/**
|
|
646
885
|
* Runs initialize() once. A bad config (say, a missing API key) fails every
|
|
647
886
|
* write with the same error instead of an unhandled rejection at startup.
|
|
@@ -661,8 +900,71 @@ var AnalyticsTransport = class {
|
|
|
661
900
|
|
|
662
901
|
//#endregion
|
|
663
902
|
//#region src/transports/datadog.transport.ts
|
|
903
|
+
const gzipAsync = promisify(gzip);
|
|
904
|
+
const MAX_LOGS_PER_REQUEST = 1e3;
|
|
905
|
+
const MAX_LOGS_PAYLOAD_BYTES = 5e6;
|
|
906
|
+
const MAX_LOG_BYTES = 1e6;
|
|
907
|
+
const MAX_TRUNCATED_MESSAGE_CHARS = 15e4;
|
|
908
|
+
const TRUNCATED_LOG_KEYS = [
|
|
909
|
+
"ddsource",
|
|
910
|
+
"ddtags",
|
|
911
|
+
"hostname",
|
|
912
|
+
"service",
|
|
913
|
+
"status",
|
|
914
|
+
"timestamp",
|
|
915
|
+
"level",
|
|
916
|
+
"context",
|
|
917
|
+
"traceId",
|
|
918
|
+
"appName",
|
|
919
|
+
"environment",
|
|
920
|
+
"env",
|
|
921
|
+
"version",
|
|
922
|
+
"logger",
|
|
923
|
+
"dd.trace_id",
|
|
924
|
+
"dd.span_id"
|
|
925
|
+
];
|
|
926
|
+
const STATUS_MAP = {
|
|
927
|
+
fatal: "critical",
|
|
928
|
+
critical: "critical",
|
|
929
|
+
error: "error",
|
|
930
|
+
warn: "warn",
|
|
931
|
+
warning: "warn",
|
|
932
|
+
info: "info",
|
|
933
|
+
debug: "debug",
|
|
934
|
+
trace: "debug",
|
|
935
|
+
verbose: "debug"
|
|
936
|
+
};
|
|
937
|
+
const MAX_UINT64 = (1n << 64n) - 1n;
|
|
938
|
+
const DASHED_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
939
|
+
const HEX = /^[0-9a-f]+$/i;
|
|
940
|
+
const DIGITS = /^\d+$/;
|
|
664
941
|
/**
|
|
665
|
-
*
|
|
942
|
+
* Datadog correlates on a decimal 64-bit id. Accepts:
|
|
943
|
+
* - a dashed UUID (logixia's default trace id): dashes stripped, then 32-hex;
|
|
944
|
+
* - 32 hex chars (W3C trace id) or 16 hex chars containing a-f: low 64 bits as decimal;
|
|
945
|
+
* - an all-digit string: already decimal (dd-trace's native format), passed through.
|
|
946
|
+
* An all-digit string is ambiguous when it is 16 or 32 long: 32 is read as hex (a
|
|
947
|
+
* decimal id has at most 20 digits), 16 is read as decimal.
|
|
948
|
+
* Anything else yields the raw string for trace ids (`passthrough`) and nothing for span ids.
|
|
949
|
+
*/
|
|
950
|
+
function toDatadogId(id, passthrough) {
|
|
951
|
+
if (typeof id !== "string" || id === "") return void 0;
|
|
952
|
+
const fallback = passthrough ? id : void 0;
|
|
953
|
+
const compact = DASHED_UUID.test(id) ? id.replaceAll("-", "") : id;
|
|
954
|
+
const isHexId = HEX.test(compact) && (compact.length === 32 || compact.length === 16);
|
|
955
|
+
if (DIGITS.test(compact) && compact.length !== 32) {
|
|
956
|
+
const value = BigInt(compact);
|
|
957
|
+
return value <= MAX_UINT64 ? value.toString() : fallback;
|
|
958
|
+
}
|
|
959
|
+
if (isHexId) return BigInt(`0x${compact.slice(-16)}`).toString();
|
|
960
|
+
return fallback;
|
|
961
|
+
}
|
|
962
|
+
/** Datadog tags: no commas or whitespace, lowercase, at most 200 chars. */
|
|
963
|
+
function tag(key, value) {
|
|
964
|
+
return `${key}:${value}`.replaceAll(/[\s,]+/g, "_").toLowerCase().slice(0, 200);
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* Sends log entries and metrics to Datadog via the Logs (v2) and Metrics HTTP APIs.
|
|
666
968
|
*
|
|
667
969
|
* The API key is transmitted via the `DD-API-KEY` request header — never in the URL.
|
|
668
970
|
*
|
|
@@ -688,29 +990,68 @@ var DataDogTransport = class extends AnalyticsTransport {
|
|
|
688
990
|
}
|
|
689
991
|
}
|
|
690
992
|
async sendEntry(entry) {
|
|
691
|
-
|
|
692
|
-
if (this.datadogConfig.enableLogs !== false) promises.push(this.sendLog(entry));
|
|
693
|
-
if (this.datadogConfig.enableMetrics) promises.push(this.sendMetric(entry));
|
|
694
|
-
if (this.datadogConfig.enableTraces && entry.traceId) promises.push(this.sendTrace(entry));
|
|
695
|
-
await Promise.all(promises);
|
|
993
|
+
await this.sendBatch([entry]);
|
|
696
994
|
}
|
|
995
|
+
/**
|
|
996
|
+
* Logs go first, chunk by chunk; metrics follow once every log chunk is out.
|
|
997
|
+
* A failure part-way throws PartialBatchError naming only the entries that were
|
|
998
|
+
* not delivered, so a retry never re-posts a chunk Datadog already accepted.
|
|
999
|
+
*/
|
|
697
1000
|
async sendBatch(entries) {
|
|
698
|
-
|
|
699
|
-
if (this.datadogConfig.
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
1001
|
+
if (this.datadogConfig.enableLogs !== false) await this.sendLogBatch(entries);
|
|
1002
|
+
if (this.datadogConfig.enableMetrics) try {
|
|
1003
|
+
await this.sendMetricBatch(entries);
|
|
1004
|
+
} catch (error) {
|
|
1005
|
+
if (this.datadogConfig.enableLogs === false) throw error;
|
|
1006
|
+
throw new PartialBatchError(error.message, [], { cause: error });
|
|
704
1007
|
}
|
|
705
|
-
await Promise.all(promises);
|
|
706
1008
|
}
|
|
707
1009
|
async cleanup() {}
|
|
708
|
-
async sendLog(entry) {
|
|
709
|
-
await this.sendLogBatch([entry]);
|
|
710
|
-
}
|
|
711
1010
|
async sendLogBatch(entries) {
|
|
712
|
-
const
|
|
713
|
-
|
|
1011
|
+
const items = entries.map((entry) => ({
|
|
1012
|
+
entry,
|
|
1013
|
+
json: this.serializeLog(entry)
|
|
1014
|
+
}));
|
|
1015
|
+
const chunks = this.chunkLogs(items);
|
|
1016
|
+
for (let i = 0; i < chunks.length; i += 1) {
|
|
1017
|
+
const chunk$1 = chunks[i];
|
|
1018
|
+
try {
|
|
1019
|
+
await this.makeLogsRequest("/api/v2/logs", `[${chunk$1.map((item) => item.json).join(",")}]`);
|
|
1020
|
+
} catch (error) {
|
|
1021
|
+
if (i === 0) throw error;
|
|
1022
|
+
const unsent = chunks.slice(i).flatMap((c) => c.map((item) => item.entry));
|
|
1023
|
+
throw new PartialBatchError(error.message, unsent, { cause: error });
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
/** Splits into requests of at most 1000 entries and about 5MB of JSON. */
|
|
1028
|
+
chunkLogs(items) {
|
|
1029
|
+
const chunks = [];
|
|
1030
|
+
let current = [];
|
|
1031
|
+
let currentBytes = 2;
|
|
1032
|
+
for (const item of items) {
|
|
1033
|
+
const bytes = Buffer.byteLength(item.json) + 1;
|
|
1034
|
+
if (current.length > 0 && (current.length >= MAX_LOGS_PER_REQUEST || currentBytes + bytes > MAX_LOGS_PAYLOAD_BYTES)) {
|
|
1035
|
+
chunks.push(current);
|
|
1036
|
+
current = [];
|
|
1037
|
+
currentBytes = 2;
|
|
1038
|
+
}
|
|
1039
|
+
current.push(item);
|
|
1040
|
+
currentBytes += bytes;
|
|
1041
|
+
}
|
|
1042
|
+
if (current.length > 0) chunks.push(current);
|
|
1043
|
+
return chunks;
|
|
1044
|
+
}
|
|
1045
|
+
/** Serializes once. A log over 1MB keeps its identity and correlation fields but loses its attributes and most of its message. */
|
|
1046
|
+
serializeLog(entry) {
|
|
1047
|
+
const log = this.transformToDataDogLog(entry);
|
|
1048
|
+
const json = stringifyForLog(log);
|
|
1049
|
+
if (Buffer.byteLength(json) <= MAX_LOG_BYTES) return json;
|
|
1050
|
+
const kept = {};
|
|
1051
|
+
for (const key of TRUNCATED_LOG_KEYS) if (log[key] !== void 0) kept[key] = log[key];
|
|
1052
|
+
kept["message"] = String(log["message"]).slice(0, MAX_TRUNCATED_MESSAGE_CHARS);
|
|
1053
|
+
kept["truncated"] = true;
|
|
1054
|
+
return stringifyForLog(kept);
|
|
714
1055
|
}
|
|
715
1056
|
async sendMetric(entry) {
|
|
716
1057
|
await this.sendMetricBatch([entry]);
|
|
@@ -719,32 +1060,53 @@ var DataDogTransport = class extends AnalyticsTransport {
|
|
|
719
1060
|
const payload = { series: entries.map((entry) => this.transformToDataDogMetric(entry)) };
|
|
720
1061
|
await this.makeMetricsRequest("/api/v1/series", payload);
|
|
721
1062
|
}
|
|
722
|
-
async sendTrace(entry) {
|
|
723
|
-
await this.sendLog(entry);
|
|
724
|
-
}
|
|
725
|
-
async sendTraceBatch(entries) {
|
|
726
|
-
await this.sendLogBatch(entries);
|
|
727
|
-
}
|
|
728
1063
|
transformToDataDogLog(entry) {
|
|
1064
|
+
var _entry$data, _entry$data2;
|
|
729
1065
|
const transformed = this.transformEntry(entry);
|
|
1066
|
+
const service = this.datadogConfig.service || "logixia";
|
|
1067
|
+
const env = this.datadogConfig.env || "production";
|
|
1068
|
+
const version = this.datadogConfig.version;
|
|
1069
|
+
const tags = [
|
|
1070
|
+
tag("env", env),
|
|
1071
|
+
tag("service", service),
|
|
1072
|
+
...version ? [tag("version", version)] : []
|
|
1073
|
+
];
|
|
1074
|
+
const spanId = toDatadogId(((_entry$data = entry.data) === null || _entry$data === void 0 ? void 0 : _entry$data["spanId"]) ?? ((_entry$data2 = entry.data) === null || _entry$data2 === void 0 ? void 0 : _entry$data2["span_id"]), false);
|
|
1075
|
+
const traceId = toDatadogId(entry.traceId, true);
|
|
730
1076
|
return {
|
|
731
|
-
|
|
732
|
-
|
|
1077
|
+
...transformed,
|
|
1078
|
+
ddsource: "nodejs",
|
|
1079
|
+
ddtags: tags.join(","),
|
|
1080
|
+
hostname: this.getHostname(),
|
|
1081
|
+
service,
|
|
1082
|
+
status: this.mapLogLevel(entry.level),
|
|
733
1083
|
message: entry.message,
|
|
734
|
-
|
|
735
|
-
version
|
|
736
|
-
env: this.datadogConfig.env || "production",
|
|
1084
|
+
env,
|
|
1085
|
+
version,
|
|
737
1086
|
logger: {
|
|
738
1087
|
name: "logixia",
|
|
739
1088
|
thread_name: "main"
|
|
740
1089
|
},
|
|
741
|
-
...
|
|
742
|
-
"dd.
|
|
743
|
-
"dd.span_id": this.generateSpanId(),
|
|
744
|
-
host: this.getHostname(),
|
|
745
|
-
source: "nodejs"
|
|
1090
|
+
...traceId && { "dd.trace_id": traceId },
|
|
1091
|
+
...traceId && spanId && { "dd.span_id": spanId }
|
|
746
1092
|
};
|
|
747
1093
|
}
|
|
1094
|
+
reservedKeys() {
|
|
1095
|
+
return [
|
|
1096
|
+
"status",
|
|
1097
|
+
"ddtags",
|
|
1098
|
+
"ddsource",
|
|
1099
|
+
"hostname",
|
|
1100
|
+
"service",
|
|
1101
|
+
"version",
|
|
1102
|
+
"env",
|
|
1103
|
+
"logger",
|
|
1104
|
+
"host",
|
|
1105
|
+
"source",
|
|
1106
|
+
"dd.trace_id",
|
|
1107
|
+
"dd.span_id"
|
|
1108
|
+
];
|
|
1109
|
+
}
|
|
748
1110
|
transformToDataDogMetric(entry) {
|
|
749
1111
|
return {
|
|
750
1112
|
metric: `logitron.logs.${entry.level}`,
|
|
@@ -752,58 +1114,29 @@ var DataDogTransport = class extends AnalyticsTransport {
|
|
|
752
1114
|
type: "count",
|
|
753
1115
|
host: this.getHostname(),
|
|
754
1116
|
tags: [
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
...entry.context ? [
|
|
759
|
-
...entry.appName ? [
|
|
1117
|
+
tag("level", entry.level),
|
|
1118
|
+
tag("service", this.datadogConfig.service || "logixia"),
|
|
1119
|
+
tag("env", this.datadogConfig.env || "production"),
|
|
1120
|
+
...entry.context ? [tag("context", entry.context)] : [],
|
|
1121
|
+
...entry.appName ? [tag("app", entry.appName)] : []
|
|
760
1122
|
]
|
|
761
1123
|
};
|
|
762
1124
|
}
|
|
763
|
-
transformToDataDogTrace(entry) {
|
|
764
|
-
return {
|
|
765
|
-
trace_id: entry.traceId,
|
|
766
|
-
span_id: this.generateSpanId(),
|
|
767
|
-
parent_id: null,
|
|
768
|
-
name: "log.entry",
|
|
769
|
-
service: this.datadogConfig.service || "logixia",
|
|
770
|
-
resource: entry.message,
|
|
771
|
-
type: "log",
|
|
772
|
-
start: entry.timestamp.getTime() * 1e6,
|
|
773
|
-
duration: 1e6,
|
|
774
|
-
meta: {
|
|
775
|
-
"log.level": entry.level,
|
|
776
|
-
"log.message": entry.message,
|
|
777
|
-
...entry.context && { "log.context": entry.context },
|
|
778
|
-
...entry.data && Object.keys(entry.data).reduce((acc, key) => {
|
|
779
|
-
acc[`log.${key}`] = String(entry.data[key]);
|
|
780
|
-
return acc;
|
|
781
|
-
}, {})
|
|
782
|
-
},
|
|
783
|
-
metrics: { _sampling_priority_v1: 1 }
|
|
784
|
-
};
|
|
785
|
-
}
|
|
786
1125
|
mapLogLevel(level) {
|
|
787
|
-
return
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
warning: "warn",
|
|
791
|
-
info: "info",
|
|
792
|
-
debug: "debug",
|
|
793
|
-
trace: "trace",
|
|
794
|
-
verbose: "debug"
|
|
795
|
-
}[level.toLowerCase()] || "info";
|
|
796
|
-
}
|
|
797
|
-
async makeLogsRequest(endpoint, data) {
|
|
1126
|
+
return STATUS_MAP[level.toLowerCase()] || "info";
|
|
1127
|
+
}
|
|
1128
|
+
async makeLogsRequest(endpoint, json) {
|
|
798
1129
|
const url = `${this.logsUrl}${endpoint}`;
|
|
799
1130
|
try {
|
|
1131
|
+
const compress = this.datadogConfig.compress === true;
|
|
800
1132
|
const response = await fetch(url, {
|
|
801
1133
|
method: "POST",
|
|
802
1134
|
headers: {
|
|
803
1135
|
"Content-Type": "application/json",
|
|
804
|
-
"DD-API-KEY": this.datadogConfig.apiKey
|
|
1136
|
+
"DD-API-KEY": this.datadogConfig.apiKey,
|
|
1137
|
+
...compress && { "Content-Encoding": "gzip" }
|
|
805
1138
|
},
|
|
806
|
-
body:
|
|
1139
|
+
body: compress ? await gzipAsync(json) : json
|
|
807
1140
|
});
|
|
808
1141
|
if (!response.ok) throw new Error(`DataDog Logs API error: ${response.status} ${response.statusText}`);
|
|
809
1142
|
} catch (error) {
|
|
@@ -826,9 +1159,6 @@ var DataDogTransport = class extends AnalyticsTransport {
|
|
|
826
1159
|
throw new Error(`Failed to send metrics to DataDog: ${error.message}`, { cause: error });
|
|
827
1160
|
}
|
|
828
1161
|
}
|
|
829
|
-
generateSpanId() {
|
|
830
|
-
return Math.floor(Math.random() * 0xffffffffffff).toString(16);
|
|
831
|
-
}
|
|
832
1162
|
getHostname() {
|
|
833
1163
|
try {
|
|
834
1164
|
return __require("node:os").hostname();
|
|
@@ -884,6 +1214,12 @@ const unlink = promisify(fs.unlink);
|
|
|
884
1214
|
const readdir = promisify(fs.readdir);
|
|
885
1215
|
const stat = promisify(fs.stat);
|
|
886
1216
|
const DROP_WARN_INTERVAL_MS = 5e3;
|
|
1217
|
+
const DEFAULT_MAX_QUEUE = 1e4;
|
|
1218
|
+
const DEFAULT_FILE_MODE = 384;
|
|
1219
|
+
const DEFAULT_DIR_MODE = 448;
|
|
1220
|
+
function csvField(value) {
|
|
1221
|
+
return `"${stripControlChars(safeToString(value)).replace(/"/g, "\"\"")}"`;
|
|
1222
|
+
}
|
|
887
1223
|
const SIZE_UNITS = {
|
|
888
1224
|
"": 1,
|
|
889
1225
|
k: 1024,
|
|
@@ -919,6 +1255,10 @@ function formatDatePattern(date, pattern) {
|
|
|
919
1255
|
* rotated files are renamed beside it (`app-2026-10-22T09-30-00-000.log`).
|
|
920
1256
|
* With a `rotation` block every file, the live one included, is timestamped.
|
|
921
1257
|
*
|
|
1258
|
+
* Files are created with mode 0o600 and directories with 0o700; override with
|
|
1259
|
+
* `fileMode` and `dirMode`. At most `maxQueue` (default 10000) entries wait in
|
|
1260
|
+
* memory; the rest are dropped per `queuePolicy` and counted in a warning.
|
|
1261
|
+
*
|
|
922
1262
|
* @example
|
|
923
1263
|
* transports: { file: { filename: 'app.log', dirname: './logs', maxSize: '50MB' } }
|
|
924
1264
|
*/
|
|
@@ -953,8 +1293,10 @@ var FileTransport = class {
|
|
|
953
1293
|
this.maxBytes = parseSize(rawMaxSize);
|
|
954
1294
|
if (rawMaxSize !== void 0 && this.maxBytes === void 0) internalWarn(`FileTransport: maxSize ${JSON.stringify(rawMaxSize)} is not a valid size (try '50MB'); size rotation is off`);
|
|
955
1295
|
const maxQueue = config.maxQueue;
|
|
956
|
-
if (maxQueue !== void 0 && !(Number.isInteger(maxQueue) && maxQueue > 0)) internalWarn(`FileTransport: maxQueue ${String(maxQueue)} is not a positive integer;
|
|
957
|
-
|
|
1296
|
+
if (maxQueue !== void 0 && !(Number.isInteger(maxQueue) && maxQueue > 0)) internalWarn(`FileTransport: maxQueue ${String(maxQueue)} is not a positive integer; using ${DEFAULT_MAX_QUEUE}`);
|
|
1297
|
+
this.maxQueue = maxQueue !== void 0 && Number.isInteger(maxQueue) && maxQueue > 0 ? maxQueue : DEFAULT_MAX_QUEUE;
|
|
1298
|
+
this.fileMode = config.fileMode ?? DEFAULT_FILE_MODE;
|
|
1299
|
+
this.dirMode = config.dirMode ?? DEFAULT_DIR_MODE;
|
|
958
1300
|
this.queuePolicy = config.queuePolicy ?? "drop-oldest";
|
|
959
1301
|
this.maxFiles = (rotation === null || rotation === void 0 ? void 0 : rotation.maxFiles) ?? config.maxFiles;
|
|
960
1302
|
this.compress = (rotation === null || rotation === void 0 ? void 0 : rotation.compress) ?? config.zippedArchive ?? false;
|
|
@@ -964,7 +1306,10 @@ var FileTransport = class {
|
|
|
964
1306
|
this.ext = path$1.extname(config.filename);
|
|
965
1307
|
this.base = path$1.basename(config.filename, this.ext);
|
|
966
1308
|
try {
|
|
967
|
-
fs.mkdirSync(this.dir, {
|
|
1309
|
+
fs.mkdirSync(this.dir, {
|
|
1310
|
+
recursive: true,
|
|
1311
|
+
mode: this.dirMode
|
|
1312
|
+
});
|
|
968
1313
|
} catch (error) {
|
|
969
1314
|
internalError(`FileTransport could not create ${this.dir}`, error);
|
|
970
1315
|
}
|
|
@@ -1032,7 +1377,7 @@ var FileTransport = class {
|
|
|
1032
1377
|
this.enqueued += 1;
|
|
1033
1378
|
}
|
|
1034
1379
|
queueFull() {
|
|
1035
|
-
return this.
|
|
1380
|
+
return this.batch.length + this.inFlight >= this.maxQueue;
|
|
1036
1381
|
}
|
|
1037
1382
|
roomAvailable() {
|
|
1038
1383
|
const room = new Promise((resolve) => this.spaceWaiters.push(resolve));
|
|
@@ -1112,30 +1457,26 @@ var FileTransport = class {
|
|
|
1112
1457
|
}
|
|
1113
1458
|
formatEntry(entry) {
|
|
1114
1459
|
switch (this.config.format) {
|
|
1115
|
-
case "json": return stringifyForLog({
|
|
1460
|
+
case "json": return stringifyForLog(mergeCoreFields({
|
|
1116
1461
|
timestamp: entry.timestamp.toISOString(),
|
|
1117
1462
|
level: entry.level,
|
|
1118
|
-
message: entry.message
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
safeToString(entry.traceId),
|
|
1129
|
-
stringifyForLog(entry.data || {})
|
|
1130
|
-
].join(",");
|
|
1131
|
-
}
|
|
1463
|
+
message: entry.message
|
|
1464
|
+
}, entry.data));
|
|
1465
|
+
case "csv": return [
|
|
1466
|
+
entry.timestamp.toISOString(),
|
|
1467
|
+
csvField(entry.level),
|
|
1468
|
+
csvField(entry.message),
|
|
1469
|
+
csvField(entry.context),
|
|
1470
|
+
csvField(entry.traceId),
|
|
1471
|
+
csvField(stringifyForLog(entry.data || {}))
|
|
1472
|
+
].join(",");
|
|
1132
1473
|
case "text":
|
|
1133
|
-
default: return `${entry.timestamp.toISOString()} [${entry.level.toUpperCase()}] ${safeToString(entry.message)}${entry.data ? " " + stringifyForLog(entry.data) : ""}`;
|
|
1474
|
+
default: return `${entry.timestamp.toISOString()} [${stripControlChars(safeToString(entry.level)).toUpperCase()}] ${stripControlChars(safeToString(entry.message))}${entry.data ? " " + stringifyForLog(entry.data) : ""}`;
|
|
1134
1475
|
}
|
|
1135
1476
|
}
|
|
1136
1477
|
addToBatch(entry) {
|
|
1137
1478
|
this.enqueue(entry);
|
|
1138
|
-
const threshold = Math.min(this.config.batchSize || 100, this.maxQueue
|
|
1479
|
+
const threshold = Math.min(this.config.batchSize || 100, this.maxQueue);
|
|
1139
1480
|
if (this.batch.length >= threshold && !this.draining) {
|
|
1140
1481
|
if (this.batchTimer) {
|
|
1141
1482
|
clearTimeout(this.batchTimer);
|
|
@@ -1173,7 +1514,7 @@ var FileTransport = class {
|
|
|
1173
1514
|
if (chunk$1) await this.append(chunk$1, chunkBytes);
|
|
1174
1515
|
}
|
|
1175
1516
|
async append(content, bytes = Buffer.byteLength(content)) {
|
|
1176
|
-
await appendFile(this.currentFilePath, content);
|
|
1517
|
+
await appendFile(this.currentFilePath, content, { mode: this.fileMode });
|
|
1177
1518
|
this.bytesWritten += bytes;
|
|
1178
1519
|
}
|
|
1179
1520
|
timeToRotate() {
|
|
@@ -1267,7 +1608,7 @@ var FileTransport = class {
|
|
|
1267
1608
|
async compressFile(filePath) {
|
|
1268
1609
|
const gzPath = `${filePath}.gz`;
|
|
1269
1610
|
try {
|
|
1270
|
-
await pipeline(fs.createReadStream(filePath), createGzip(), fs.createWriteStream(gzPath));
|
|
1611
|
+
await pipeline(fs.createReadStream(filePath), createGzip(), fs.createWriteStream(gzPath, { mode: this.fileMode }));
|
|
1271
1612
|
await unlink(filePath);
|
|
1272
1613
|
} catch (error) {
|
|
1273
1614
|
internalError("Failed to compress rotated log file", error);
|
|
@@ -1351,12 +1692,27 @@ var GoogleAnalyticsTransport = class extends AnalyticsTransport {
|
|
|
1351
1692
|
await this.sendEvents(events);
|
|
1352
1693
|
}
|
|
1353
1694
|
async cleanup() {}
|
|
1695
|
+
reservedKeys() {
|
|
1696
|
+
return [
|
|
1697
|
+
"event_category",
|
|
1698
|
+
"event_label",
|
|
1699
|
+
"log_level",
|
|
1700
|
+
"log_message",
|
|
1701
|
+
"trace_id",
|
|
1702
|
+
"app_name",
|
|
1703
|
+
"custom_dimension_1",
|
|
1704
|
+
"custom_dimension_2",
|
|
1705
|
+
"custom_dimension_3"
|
|
1706
|
+
];
|
|
1707
|
+
}
|
|
1354
1708
|
transformToGAEvent(entry) {
|
|
1355
1709
|
const transformed = this.transformEntry(entry);
|
|
1710
|
+
const eventCategory = this.mapLogLevelToCategory(entry.level);
|
|
1356
1711
|
return {
|
|
1357
1712
|
name: "log_event",
|
|
1358
1713
|
params: {
|
|
1359
|
-
|
|
1714
|
+
...this.flattenData(transformed),
|
|
1715
|
+
event_category: eventCategory,
|
|
1360
1716
|
event_label: entry.message,
|
|
1361
1717
|
log_level: entry.level,
|
|
1362
1718
|
log_message: entry.message,
|
|
@@ -1365,7 +1721,6 @@ var GoogleAnalyticsTransport = class extends AnalyticsTransport {
|
|
|
1365
1721
|
...entry.traceId && { trace_id: entry.traceId },
|
|
1366
1722
|
...entry.appName && { app_name: entry.appName },
|
|
1367
1723
|
...entry.environment && { environment: entry.environment },
|
|
1368
|
-
...this.flattenData(transformed),
|
|
1369
1724
|
custom_dimension_1: entry.level,
|
|
1370
1725
|
custom_dimension_2: entry.context || "default",
|
|
1371
1726
|
custom_dimension_3: entry.environment || "production"
|
|
@@ -1561,12 +1916,21 @@ var MixpanelTransport = class extends AnalyticsTransport {
|
|
|
1561
1916
|
await this.trackEvents(events);
|
|
1562
1917
|
}
|
|
1563
1918
|
async cleanup() {}
|
|
1919
|
+
reservedKeys() {
|
|
1920
|
+
return [
|
|
1921
|
+
"token",
|
|
1922
|
+
"distinct_id",
|
|
1923
|
+
"time",
|
|
1924
|
+
"$insert_id"
|
|
1925
|
+
];
|
|
1926
|
+
}
|
|
1564
1927
|
transformToMixpanelEvent(entry) {
|
|
1565
1928
|
const transformed = this.transformEntry(entry);
|
|
1566
1929
|
return {
|
|
1567
1930
|
name: `log_${entry.level}`,
|
|
1568
1931
|
properties: {
|
|
1569
1932
|
...transformed,
|
|
1933
|
+
token: this.mixpanelConfig.token,
|
|
1570
1934
|
distinct_id: this.mixpanelConfig.distinct_id || "anonymous",
|
|
1571
1935
|
time: entry.timestamp.getTime(),
|
|
1572
1936
|
$insert_id: this.generateInsertId(entry),
|
|
@@ -1579,8 +1943,8 @@ var MixpanelTransport = class extends AnalyticsTransport {
|
|
|
1579
1943
|
const payload = {
|
|
1580
1944
|
event: event.name,
|
|
1581
1945
|
properties: {
|
|
1582
|
-
|
|
1583
|
-
|
|
1946
|
+
...event.properties,
|
|
1947
|
+
token: this.mixpanelConfig.token
|
|
1584
1948
|
}
|
|
1585
1949
|
};
|
|
1586
1950
|
await this.makeRequest("/track", [payload]);
|
|
@@ -1589,8 +1953,8 @@ var MixpanelTransport = class extends AnalyticsTransport {
|
|
|
1589
1953
|
const payload = events.map((event) => ({
|
|
1590
1954
|
event: event.name,
|
|
1591
1955
|
properties: {
|
|
1592
|
-
|
|
1593
|
-
|
|
1956
|
+
...event.properties,
|
|
1957
|
+
token: this.mixpanelConfig.token
|
|
1594
1958
|
}
|
|
1595
1959
|
}));
|
|
1596
1960
|
await this.makeRequest("/track", payload);
|
|
@@ -1648,11 +2012,11 @@ var MixpanelTransport = class extends AnalyticsTransport {
|
|
|
1648
2012
|
const payload = {
|
|
1649
2013
|
event: eventName,
|
|
1650
2014
|
properties: {
|
|
2015
|
+
...properties,
|
|
2016
|
+
...this.mixpanelConfig.enableSuperProperties ? this.mixpanelConfig.superProperties : {},
|
|
1651
2017
|
token: this.mixpanelConfig.token,
|
|
1652
2018
|
distinct_id: this.mixpanelConfig.distinct_id || "anonymous",
|
|
1653
|
-
time: Date.now()
|
|
1654
|
-
...properties,
|
|
1655
|
-
...this.mixpanelConfig.enableSuperProperties ? this.mixpanelConfig.superProperties : {}
|
|
2019
|
+
time: Date.now()
|
|
1656
2020
|
}
|
|
1657
2021
|
};
|
|
1658
2022
|
await this.makeRequest("/track", [payload]);
|
|
@@ -1712,6 +2076,9 @@ var SegmentTransport = class extends AnalyticsTransport {
|
|
|
1712
2076
|
await this.batchTrack(segmentEvents);
|
|
1713
2077
|
}
|
|
1714
2078
|
async cleanup() {}
|
|
2079
|
+
reservedKeys() {
|
|
2080
|
+
return ["logger"];
|
|
2081
|
+
}
|
|
1715
2082
|
transformToSegmentEvent(entry) {
|
|
1716
2083
|
const transformed = this.transformEntry(entry);
|
|
1717
2084
|
return {
|
|
@@ -1721,10 +2088,10 @@ var SegmentTransport = class extends AnalyticsTransport {
|
|
|
1721
2088
|
anonymousId: this.generateAnonymousId(),
|
|
1722
2089
|
timestamp: entry.timestamp.toISOString(),
|
|
1723
2090
|
properties: {
|
|
2091
|
+
...transformed,
|
|
1724
2092
|
level: entry.level,
|
|
1725
2093
|
message: entry.message,
|
|
1726
2094
|
logger: "logixia",
|
|
1727
|
-
...transformed,
|
|
1728
2095
|
...entry.context && { context: entry.context },
|
|
1729
2096
|
...entry.traceId && { traceId: entry.traceId },
|
|
1730
2097
|
...entry.appName && { appName: entry.appName },
|
|
@@ -1780,11 +2147,10 @@ var SegmentTransport = class extends AnalyticsTransport {
|
|
|
1780
2147
|
}
|
|
1781
2148
|
}
|
|
1782
2149
|
extractUserId(entry) {
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
}
|
|
2150
|
+
var _entry$data;
|
|
2151
|
+
const field = this.segmentConfig.userIdField ?? "userId";
|
|
2152
|
+
const id = (_entry$data = entry.data) === null || _entry$data === void 0 ? void 0 : _entry$data[field];
|
|
2153
|
+
return typeof id === "string" ? id : void 0;
|
|
1788
2154
|
}
|
|
1789
2155
|
generateAnonymousId() {
|
|
1790
2156
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
|
@@ -2285,5 +2651,5 @@ var TransportManager = class extends EventEmitter {
|
|
|
2285
2651
|
};
|
|
2286
2652
|
|
|
2287
2653
|
//#endregion
|
|
2288
|
-
export { FileTransport as a, DatabaseTransport as c, GoogleAnalyticsTransport as i,
|
|
2289
|
-
//# sourceMappingURL=transport.manager-
|
|
2654
|
+
export { FileTransport as a, DatabaseTransport as c, stripControlChars as d, GoogleAnalyticsTransport as i, BufferCap as l, SegmentTransport as n, DataDogTransport as o, MixpanelTransport as r, AnalyticsTransport as s, TransportManager as t, ConsoleTransport as u };
|
|
2655
|
+
//# sourceMappingURL=transport.manager-BiuCAJd2.mjs.map
|