@loggerjs/processors 0.0.1
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/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/breadcrumb-buffer.d.ts +34 -0
- package/dist/breadcrumb-buffer.d.ts.map +1 -0
- package/dist/dedupe.d.ts +8 -0
- package/dist/dedupe.d.ts.map +1 -0
- package/dist/dynamic-sampler.d.ts +34 -0
- package/dist/dynamic-sampler.d.ts.map +1 -0
- package/dist/enrich.d.ts +24 -0
- package/dist/enrich.d.ts.map +1 -0
- package/dist/filter-route.d.ts +35 -0
- package/dist/filter-route.d.ts.map +1 -0
- package/dist/fingerprint.d.ts +12 -0
- package/dist/fingerprint.d.ts.map +1 -0
- package/dist/fingers-crossed.d.ts +29 -0
- package/dist/fingers-crossed.d.ts.map +1 -0
- package/dist/index.cjs +1379 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1328 -0
- package/dist/index.js.map +1 -0
- package/dist/level-override.d.ts +20 -0
- package/dist/level-override.d.ts.map +1 -0
- package/dist/normalize-error.d.ts +14 -0
- package/dist/normalize-error.d.ts.map +1 -0
- package/dist/privacy-guard.d.ts +22 -0
- package/dist/privacy-guard.d.ts.map +1 -0
- package/dist/rate-limit.d.ts +19 -0
- package/dist/rate-limit.d.ts.map +1 -0
- package/dist/redact.d.ts +10 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/sample.d.ts +8 -0
- package/dist/sample.d.ts.map +1 -0
- package/dist/schema-dev-check.d.ts +16 -0
- package/dist/schema-dev-check.d.ts.map +1 -0
- package/dist/stack-parser.d.ts +19 -0
- package/dist/stack-parser.d.ts.map +1 -0
- package/dist/tags.d.ts +8 -0
- package/dist/tags.d.ts.map +1 -0
- package/dist/trace.d.ts +5 -0
- package/dist/trace.d.ts.map +1 -0
- package/package.json +47 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1379 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let _loggerjs_core = require("@loggerjs/core");
|
|
3
|
+
//#region src/redact.ts
|
|
4
|
+
function matchesKey(key, path, value, matchers) {
|
|
5
|
+
return matchers.some((matcher) => {
|
|
6
|
+
if (typeof matcher === "string") return matcher.toLowerCase() === key.toLowerCase();
|
|
7
|
+
if (matcher instanceof RegExp) return matcher.test(key) || matcher.test(path);
|
|
8
|
+
return matcher(key, path, value);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
function pathMatches(path, paths) {
|
|
12
|
+
return paths.includes(path);
|
|
13
|
+
}
|
|
14
|
+
function redactValue(value, options, path = "", depth = 0, seen = /* @__PURE__ */ new WeakMap()) {
|
|
15
|
+
if (value === null || value === void 0) return value;
|
|
16
|
+
if (typeof value !== "object") return value;
|
|
17
|
+
if (depth >= options.maxDepth) return value;
|
|
18
|
+
if (seen.has(value)) return seen.get(value);
|
|
19
|
+
if (Array.isArray(value)) {
|
|
20
|
+
const out = [];
|
|
21
|
+
seen.set(value, out);
|
|
22
|
+
for (let index = 0; index < value.length; index += 1) out[index] = redactValue(value[index], options, `${path}[${index}]`, depth + 1, seen);
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
if (value instanceof Error) return value;
|
|
26
|
+
if (value instanceof Date) return value;
|
|
27
|
+
const input = value;
|
|
28
|
+
const out = {};
|
|
29
|
+
seen.set(value, out);
|
|
30
|
+
for (const [key, child] of Object.entries(input)) {
|
|
31
|
+
const childPath = path ? `${path}.${key}` : key;
|
|
32
|
+
if (matchesKey(key, childPath, child, options.keys ?? []) || pathMatches(childPath, options.paths ?? [])) out[key] = options.replacement;
|
|
33
|
+
else out[key] = redactValue(child, options, childPath, depth + 1, seen);
|
|
34
|
+
}
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
function redactProcessor(options = {}) {
|
|
38
|
+
const normalized = {
|
|
39
|
+
keys: options.keys ?? [
|
|
40
|
+
"password",
|
|
41
|
+
"passwd",
|
|
42
|
+
"secret",
|
|
43
|
+
"token",
|
|
44
|
+
"authorization",
|
|
45
|
+
"cookie",
|
|
46
|
+
"set-cookie",
|
|
47
|
+
"apiKey",
|
|
48
|
+
"api_key"
|
|
49
|
+
],
|
|
50
|
+
paths: options.paths ?? [],
|
|
51
|
+
replacement: options.replacement ?? "[REDACTED]",
|
|
52
|
+
maxDepth: options.maxDepth ?? 8
|
|
53
|
+
};
|
|
54
|
+
return (event) => ({
|
|
55
|
+
...event,
|
|
56
|
+
data: redactValue(event.data, normalized),
|
|
57
|
+
context: redactValue(event.context, normalized),
|
|
58
|
+
tags: redactValue(event.tags, normalized),
|
|
59
|
+
error: redactValue(event.error, normalized)
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/sample.ts
|
|
64
|
+
function clampRate$1(rate) {
|
|
65
|
+
if (Number.isNaN(rate)) return 1;
|
|
66
|
+
return Math.max(0, Math.min(1, rate));
|
|
67
|
+
}
|
|
68
|
+
function sampleProcessor(options = {}) {
|
|
69
|
+
const defaultRate = clampRate$1(options.defaultRate ?? 1);
|
|
70
|
+
const random = options.random ?? Math.random;
|
|
71
|
+
const rates = options.rates ?? {};
|
|
72
|
+
return (event) => {
|
|
73
|
+
const rate = clampRate$1(rates[event.levelName] ?? defaultRate);
|
|
74
|
+
if (rate >= 1) return event;
|
|
75
|
+
if (rate <= 0) return false;
|
|
76
|
+
return random() < rate ? event : false;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/tags.ts
|
|
81
|
+
function tagsMiddleware(tags) {
|
|
82
|
+
return (0, _loggerjs_core.createMiddleware)("tags", (record) => {
|
|
83
|
+
record.tags = {
|
|
84
|
+
...record.tags,
|
|
85
|
+
...tags
|
|
86
|
+
};
|
|
87
|
+
return record;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function typeMiddleware(type) {
|
|
91
|
+
return (0, _loggerjs_core.createMiddleware)("type", (record) => {
|
|
92
|
+
record.type = type;
|
|
93
|
+
return record;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function contextMiddleware(context) {
|
|
97
|
+
return (0, _loggerjs_core.createMiddleware)("context", (record) => {
|
|
98
|
+
record.ctx = (0, _loggerjs_core.createBoundContext)({
|
|
99
|
+
...record.ctx,
|
|
100
|
+
...context
|
|
101
|
+
});
|
|
102
|
+
return record;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function tagsProcessor(tags) {
|
|
106
|
+
return (event) => ({
|
|
107
|
+
...event,
|
|
108
|
+
tags: {
|
|
109
|
+
...event.tags,
|
|
110
|
+
...tags
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function typeProcessor(type) {
|
|
115
|
+
return (event) => ({
|
|
116
|
+
...event,
|
|
117
|
+
type
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
function contextProcessor(context) {
|
|
121
|
+
return (event) => ({
|
|
122
|
+
...event,
|
|
123
|
+
context: {
|
|
124
|
+
...event.context,
|
|
125
|
+
...context
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region src/dedupe.ts
|
|
131
|
+
function dedupeProcessor(options = {}) {
|
|
132
|
+
const windowMs = options.windowMs ?? 1e3;
|
|
133
|
+
const maxEntries = options.maxEntries ?? 1e3;
|
|
134
|
+
const keyFor = options.key ?? ((event) => `${event.levelName}:${event.message}:${event.error?.message ?? ""}`);
|
|
135
|
+
const seen = /* @__PURE__ */ new Map();
|
|
136
|
+
return (event, context) => {
|
|
137
|
+
const now = context.now();
|
|
138
|
+
const key = keyFor(event);
|
|
139
|
+
const previous = seen.get(key);
|
|
140
|
+
if (previous !== void 0 && now - previous < windowMs) return false;
|
|
141
|
+
seen.set(key, now);
|
|
142
|
+
if (seen.size > maxEntries) {
|
|
143
|
+
const cutoff = now - windowMs;
|
|
144
|
+
for (const [entryKey, timestamp] of seen) if (timestamp < cutoff || seen.size > maxEntries) seen.delete(entryKey);
|
|
145
|
+
}
|
|
146
|
+
return event;
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
//#endregion
|
|
150
|
+
//#region src/trace.ts
|
|
151
|
+
function traceContextMiddleware(provider) {
|
|
152
|
+
return (0, _loggerjs_core.createMiddleware)("traceContext", (record) => {
|
|
153
|
+
const trace = provider();
|
|
154
|
+
if (!trace) return record;
|
|
155
|
+
record.trace = {
|
|
156
|
+
...record.trace,
|
|
157
|
+
...trace
|
|
158
|
+
};
|
|
159
|
+
return record;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
function traceContextProcessor(provider) {
|
|
163
|
+
return (event) => {
|
|
164
|
+
const trace = provider();
|
|
165
|
+
if (!trace) return event;
|
|
166
|
+
return {
|
|
167
|
+
...event,
|
|
168
|
+
trace: {
|
|
169
|
+
...event.trace,
|
|
170
|
+
...trace
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
//#endregion
|
|
176
|
+
//#region src/rate-limit.ts
|
|
177
|
+
const DEFAULT_EXEMPT_LEVELS$1 = new Set(["error", "fatal"]);
|
|
178
|
+
function defaultKey$2(event) {
|
|
179
|
+
return `${event.logger}:${event.levelName}:${event.source?.integration ?? event.type ?? "manual"}`;
|
|
180
|
+
}
|
|
181
|
+
function normalizePositive(value, fallback) {
|
|
182
|
+
if (value === void 0 || !Number.isFinite(value) || value <= 0) return fallback;
|
|
183
|
+
return value;
|
|
184
|
+
}
|
|
185
|
+
function normalizeNonNegative(value, fallback) {
|
|
186
|
+
if (value === void 0 || !Number.isFinite(value) || value < 0) return fallback;
|
|
187
|
+
return value;
|
|
188
|
+
}
|
|
189
|
+
function snapshot$3(bucket) {
|
|
190
|
+
return {
|
|
191
|
+
key: bucket.key,
|
|
192
|
+
tokens: bucket.tokens,
|
|
193
|
+
lastRefillMs: bucket.lastRefillMs
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function rateLimitProcessor(options = {}) {
|
|
197
|
+
const capacity = normalizePositive(options.capacity, 100);
|
|
198
|
+
const refillPerSecond = normalizeNonNegative(options.refillPerSecond, capacity);
|
|
199
|
+
const maxBuckets = Math.max(1, Math.floor(options.maxBuckets ?? 1e4));
|
|
200
|
+
const key = options.key ?? defaultKey$2;
|
|
201
|
+
const exemptLevels = new Set(options.exemptLevels ?? DEFAULT_EXEMPT_LEVELS$1);
|
|
202
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
203
|
+
const prune = () => {
|
|
204
|
+
while (buckets.size > maxBuckets) {
|
|
205
|
+
let oldest;
|
|
206
|
+
for (const bucket of buckets.values()) if (!oldest || bucket.lastSeenMs < oldest.lastSeenMs) oldest = bucket;
|
|
207
|
+
if (!oldest) return;
|
|
208
|
+
buckets.delete(oldest.key);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
const processor = ((event, context) => {
|
|
212
|
+
if (exemptLevels.has(event.levelName)) return event;
|
|
213
|
+
const now = context.now();
|
|
214
|
+
const bucketKey = key(event);
|
|
215
|
+
let bucket = buckets.get(bucketKey);
|
|
216
|
+
if (!bucket) {
|
|
217
|
+
bucket = {
|
|
218
|
+
key: bucketKey,
|
|
219
|
+
tokens: capacity,
|
|
220
|
+
lastRefillMs: now,
|
|
221
|
+
lastSeenMs: now
|
|
222
|
+
};
|
|
223
|
+
buckets.set(bucketKey, bucket);
|
|
224
|
+
prune();
|
|
225
|
+
}
|
|
226
|
+
const elapsedSeconds = Math.max(0, (now - bucket.lastRefillMs) / 1e3);
|
|
227
|
+
bucket.tokens = Math.min(capacity, bucket.tokens + elapsedSeconds * refillPerSecond);
|
|
228
|
+
bucket.lastRefillMs = now;
|
|
229
|
+
bucket.lastSeenMs = now;
|
|
230
|
+
if (bucket.tokens >= 1) {
|
|
231
|
+
bucket.tokens -= 1;
|
|
232
|
+
return event;
|
|
233
|
+
}
|
|
234
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)("processor.rateLimit.dropped");
|
|
235
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)(`processor.rateLimit.dropped.${event.levelName}`);
|
|
236
|
+
options.onDrop?.(event, bucketKey);
|
|
237
|
+
return false;
|
|
238
|
+
});
|
|
239
|
+
processor.buckets = () => [...buckets.values()].map(snapshot$3);
|
|
240
|
+
return processor;
|
|
241
|
+
}
|
|
242
|
+
//#endregion
|
|
243
|
+
//#region src/fingers-crossed.ts
|
|
244
|
+
const DEFAULT_KEY = "default";
|
|
245
|
+
function normalizeCount$1(value, fallback) {
|
|
246
|
+
if (value === void 0 || !Number.isFinite(value)) return fallback;
|
|
247
|
+
return Math.max(0, Math.floor(value));
|
|
248
|
+
}
|
|
249
|
+
function normalizeBucketCount$1(value) {
|
|
250
|
+
if (value === void 0 || !Number.isFinite(value)) return 1024;
|
|
251
|
+
return Math.max(1, Math.floor(value));
|
|
252
|
+
}
|
|
253
|
+
function incrementBy(name, count) {
|
|
254
|
+
for (let index = 0; index < count; index += 1) (0, _loggerjs_core.incrementLoggerMetaCounter)(name);
|
|
255
|
+
}
|
|
256
|
+
function snapshot$2(state) {
|
|
257
|
+
return {
|
|
258
|
+
key: state.key,
|
|
259
|
+
buffered: state.buffer.length,
|
|
260
|
+
activeUntilMs: state.activeUntilMs,
|
|
261
|
+
lastSeenMs: state.lastSeenMs
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
function isFlushFunction(target) {
|
|
265
|
+
return typeof target === "function";
|
|
266
|
+
}
|
|
267
|
+
function isPromiseLike(value) {
|
|
268
|
+
return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
|
|
269
|
+
}
|
|
270
|
+
async function flushToTarget(target, events, context) {
|
|
271
|
+
if (events.length === 0) return;
|
|
272
|
+
if (isFlushFunction(target)) {
|
|
273
|
+
await target(events, context);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const minLevel = target.minLevel === void 0 ? void 0 : (0, _loggerjs_core.toLevelValue)(target.minLevel);
|
|
277
|
+
const selected = minLevel === void 0 ? [...events] : events.filter((event) => event.level >= minLevel);
|
|
278
|
+
if (selected.length === 0) return;
|
|
279
|
+
const transportContext = {
|
|
280
|
+
loggerName: context.loggerName,
|
|
281
|
+
now: context.now,
|
|
282
|
+
toEvent: _loggerjs_core.recordToEvent,
|
|
283
|
+
reportInternalError: context.reportInternalError
|
|
284
|
+
};
|
|
285
|
+
if (target.logBatch) {
|
|
286
|
+
const result = target.logBatch(selected, transportContext);
|
|
287
|
+
if (isPromiseLike(result)) await result;
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
if (target.log) {
|
|
291
|
+
for (const event of selected) {
|
|
292
|
+
const result = target.log(event, transportContext);
|
|
293
|
+
if (isPromiseLike(result)) await result;
|
|
294
|
+
}
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
const records = selected.map(_loggerjs_core.eventToRecord);
|
|
298
|
+
if (target.writeBatch) {
|
|
299
|
+
const result = target.writeBatch(records, transportContext);
|
|
300
|
+
if (isPromiseLike(result)) await result;
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
if (!target.write) return;
|
|
304
|
+
for (const record of records) {
|
|
305
|
+
const result = target.write(record, transportContext);
|
|
306
|
+
if (isPromiseLike(result)) await result;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function scheduleFlush(target, events, context) {
|
|
310
|
+
if (!target || events.length === 0) return;
|
|
311
|
+
const batch = [...events];
|
|
312
|
+
incrementBy("processor.fingersCrossed.flushed", batch.length);
|
|
313
|
+
flushToTarget(target, batch, context).catch((error) => {
|
|
314
|
+
context.reportInternalError(error, {
|
|
315
|
+
phase: "processor",
|
|
316
|
+
processor: "fingersCrossed"
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
function fingersCrossedProcessor(options = {}) {
|
|
321
|
+
const triggerLevel = (0, _loggerjs_core.toLevelValue)(options.triggerLevel ?? "error");
|
|
322
|
+
const shouldTrigger = options.shouldTrigger ?? ((event) => event.level >= triggerLevel);
|
|
323
|
+
const bufferSize = normalizeCount$1(options.bufferSize, 100);
|
|
324
|
+
const maxBuckets = normalizeBucketCount$1(options.maxBuckets);
|
|
325
|
+
const keyFor = options.key ?? (() => DEFAULT_KEY);
|
|
326
|
+
const includeTrigger = options.includeTrigger ?? true;
|
|
327
|
+
const passthroughTrigger = options.passthroughTrigger ?? !options.flushTo;
|
|
328
|
+
const passthroughAfterTrigger = options.passthroughAfterTrigger ?? true;
|
|
329
|
+
const activationMs = options.activationMs;
|
|
330
|
+
const states = /* @__PURE__ */ new Map();
|
|
331
|
+
const drop = (event, reason, key) => {
|
|
332
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)("processor.fingersCrossed.dropped");
|
|
333
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)(`processor.fingersCrossed.dropped.${reason}`);
|
|
334
|
+
options.onDrop?.(event, reason, key);
|
|
335
|
+
};
|
|
336
|
+
const getState = (key, now) => {
|
|
337
|
+
let state = states.get(key);
|
|
338
|
+
if (!state) {
|
|
339
|
+
state = {
|
|
340
|
+
key,
|
|
341
|
+
buffer: [],
|
|
342
|
+
activeUntilMs: 0,
|
|
343
|
+
lastSeenMs: now
|
|
344
|
+
};
|
|
345
|
+
states.set(key, state);
|
|
346
|
+
}
|
|
347
|
+
state.lastSeenMs = now;
|
|
348
|
+
while (states.size > maxBuckets) {
|
|
349
|
+
let oldest;
|
|
350
|
+
for (const candidate of states.values()) if (!oldest || candidate.lastSeenMs < oldest.lastSeenMs) oldest = candidate;
|
|
351
|
+
if (!oldest) break;
|
|
352
|
+
for (const buffered of oldest.buffer) drop(buffered, "bucket-pruned", oldest.key);
|
|
353
|
+
states.delete(oldest.key);
|
|
354
|
+
}
|
|
355
|
+
return state;
|
|
356
|
+
};
|
|
357
|
+
const processor = ((event, context) => {
|
|
358
|
+
const now = context.now();
|
|
359
|
+
const key = keyFor(event);
|
|
360
|
+
const state = getState(key, now);
|
|
361
|
+
if (state.activeUntilMs > 0 && state.activeUntilMs <= now) state.activeUntilMs = 0;
|
|
362
|
+
if (state.activeUntilMs > now) return passthroughAfterTrigger ? event : false;
|
|
363
|
+
if (shouldTrigger(event)) {
|
|
364
|
+
const buffered = state.buffer.splice(0);
|
|
365
|
+
state.activeUntilMs = activationMs === void 0 ? Number.POSITIVE_INFINITY : now + Math.max(0, activationMs);
|
|
366
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)("processor.fingersCrossed.triggered");
|
|
367
|
+
options.onTrigger?.(event, buffered, key);
|
|
368
|
+
scheduleFlush(options.flushTo, includeTrigger ? [...buffered, event] : buffered, context);
|
|
369
|
+
return passthroughTrigger ? event : false;
|
|
370
|
+
}
|
|
371
|
+
if (bufferSize === 0) return false;
|
|
372
|
+
if (state.buffer.length >= bufferSize) {
|
|
373
|
+
const dropped = state.buffer.shift();
|
|
374
|
+
if (dropped) drop(dropped, "buffer-full", key);
|
|
375
|
+
}
|
|
376
|
+
state.buffer.push(event);
|
|
377
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)("processor.fingersCrossed.buffered");
|
|
378
|
+
return false;
|
|
379
|
+
});
|
|
380
|
+
processor.states = () => [...states.values()].map(snapshot$2);
|
|
381
|
+
processor.reset = (key) => {
|
|
382
|
+
if (key === void 0) {
|
|
383
|
+
states.clear();
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
states.delete(key);
|
|
387
|
+
};
|
|
388
|
+
return processor;
|
|
389
|
+
}
|
|
390
|
+
//#endregion
|
|
391
|
+
//#region src/enrich.ts
|
|
392
|
+
function isRecord$1(value) {
|
|
393
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
394
|
+
}
|
|
395
|
+
function mergeData(current, patch) {
|
|
396
|
+
if (patch === void 0) return current;
|
|
397
|
+
if (isRecord$1(current) && isRecord$1(patch)) return {
|
|
398
|
+
...current,
|
|
399
|
+
...patch
|
|
400
|
+
};
|
|
401
|
+
return patch;
|
|
402
|
+
}
|
|
403
|
+
function mergeRecordData(current, patch) {
|
|
404
|
+
if (patch === void 0) return current;
|
|
405
|
+
if (isRecord$1(current) && isRecord$1(patch)) return {
|
|
406
|
+
...current,
|
|
407
|
+
...patch
|
|
408
|
+
};
|
|
409
|
+
if (isRecord$1(patch)) return patch;
|
|
410
|
+
return { value: patch };
|
|
411
|
+
}
|
|
412
|
+
function sourceForRecord(source) {
|
|
413
|
+
if (!source) return void 0;
|
|
414
|
+
if (typeof source === "string") return source;
|
|
415
|
+
return source.integration ?? source.runtime;
|
|
416
|
+
}
|
|
417
|
+
function applyPatch(event, patch) {
|
|
418
|
+
return {
|
|
419
|
+
...event,
|
|
420
|
+
message: patch.message ?? event.message,
|
|
421
|
+
type: patch.type ?? event.type,
|
|
422
|
+
tags: patch.tags ? {
|
|
423
|
+
...event.tags,
|
|
424
|
+
...patch.tags
|
|
425
|
+
} : event.tags,
|
|
426
|
+
data: mergeData(event.data, patch.data),
|
|
427
|
+
context: patch.context ? {
|
|
428
|
+
...event.context,
|
|
429
|
+
...patch.context
|
|
430
|
+
} : event.context,
|
|
431
|
+
trace: patch.trace ? {
|
|
432
|
+
...event.trace,
|
|
433
|
+
...patch.trace
|
|
434
|
+
} : event.trace,
|
|
435
|
+
source: patch.source ? {
|
|
436
|
+
...event.source,
|
|
437
|
+
...patch.source
|
|
438
|
+
} : event.source
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
function enrichProcessor(input) {
|
|
442
|
+
return (event, context) => {
|
|
443
|
+
const patch = typeof input === "function" ? input(event, context) : input;
|
|
444
|
+
if (patch === false) return false;
|
|
445
|
+
if (!patch) return event;
|
|
446
|
+
return applyPatch(event, patch);
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
function applyRecordPatch(record, patch) {
|
|
450
|
+
if (patch.message !== void 0) {
|
|
451
|
+
record.msg = patch.message;
|
|
452
|
+
record.lazy = null;
|
|
453
|
+
}
|
|
454
|
+
if (patch.type !== void 0) record.type = patch.type;
|
|
455
|
+
if (patch.tags) record.tags = {
|
|
456
|
+
...record.tags,
|
|
457
|
+
...patch.tags
|
|
458
|
+
};
|
|
459
|
+
if (patch.data !== void 0) record.props = mergeRecordData(record.props, patch.data);
|
|
460
|
+
if (patch.context) record.ctx = (0, _loggerjs_core.createBoundContext)({
|
|
461
|
+
...record.ctx,
|
|
462
|
+
...patch.context
|
|
463
|
+
});
|
|
464
|
+
if (patch.trace) record.trace = {
|
|
465
|
+
...record.trace,
|
|
466
|
+
...patch.trace
|
|
467
|
+
};
|
|
468
|
+
const source = sourceForRecord(patch.source);
|
|
469
|
+
if (source) record.source = source;
|
|
470
|
+
return record;
|
|
471
|
+
}
|
|
472
|
+
function enrichMiddleware(input) {
|
|
473
|
+
return (0, _loggerjs_core.createMiddleware)("enrich", (record, context) => {
|
|
474
|
+
const patch = typeof input === "function" ? input(record, context) : input;
|
|
475
|
+
if (patch === false) return null;
|
|
476
|
+
if (!patch) return record;
|
|
477
|
+
return applyRecordPatch(record, patch);
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
//#endregion
|
|
481
|
+
//#region src/level-override.ts
|
|
482
|
+
function asMatchers(matcher) {
|
|
483
|
+
if (!matcher) return [];
|
|
484
|
+
return Array.isArray(matcher) ? matcher : [matcher];
|
|
485
|
+
}
|
|
486
|
+
function matchOne(matcher, value, event) {
|
|
487
|
+
if (typeof matcher === "function") return matcher(value, event);
|
|
488
|
+
if (matcher instanceof RegExp) return matcher.test(value ?? "");
|
|
489
|
+
return value === matcher;
|
|
490
|
+
}
|
|
491
|
+
function matchString(matcher, value, event) {
|
|
492
|
+
const matchers = asMatchers(matcher);
|
|
493
|
+
if (matchers.length === 0) return true;
|
|
494
|
+
return matchers.some((item) => matchOne(item, value, event));
|
|
495
|
+
}
|
|
496
|
+
function matchTags(expected, actual) {
|
|
497
|
+
if (!expected) return true;
|
|
498
|
+
for (const [key, value] of Object.entries(expected)) if (actual?.[key] !== value) return false;
|
|
499
|
+
return true;
|
|
500
|
+
}
|
|
501
|
+
function matchLevelRange(event, rule) {
|
|
502
|
+
if (rule.minLevel !== void 0 && event.level < (0, _loggerjs_core.toLevelValue)(rule.minLevel)) return false;
|
|
503
|
+
if (rule.maxLevel !== void 0 && event.level > (0, _loggerjs_core.toLevelValue)(rule.maxLevel)) return false;
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
506
|
+
function matchesRule(event, context, rule) {
|
|
507
|
+
return (!rule.when || rule.when(event, context)) && matchString(rule.logger, event.logger, event) && matchString(rule.type, event.type, event) && matchString(rule.integration, event.source?.integration, event) && matchString(rule.runtime, event.source?.runtime, event) && matchTags(rule.tags, event.tags) && matchLevelRange(event, rule);
|
|
508
|
+
}
|
|
509
|
+
function resolveLevel(value, event, context) {
|
|
510
|
+
if (typeof value === "function") {
|
|
511
|
+
const level = value(event, context);
|
|
512
|
+
return level === void 0 ? void 0 : level;
|
|
513
|
+
}
|
|
514
|
+
return value;
|
|
515
|
+
}
|
|
516
|
+
function applyLevel(event, level) {
|
|
517
|
+
if (level === void 0) return event;
|
|
518
|
+
if (level === false || level === "silent") return false;
|
|
519
|
+
const nextLevel = (0, _loggerjs_core.toLevelValue)(level, event.level);
|
|
520
|
+
if (!Number.isFinite(nextLevel)) return false;
|
|
521
|
+
const nextLevelName = (0, _loggerjs_core.toLevelName)(nextLevel);
|
|
522
|
+
if (nextLevel === event.level && nextLevelName === event.levelName) return event;
|
|
523
|
+
return {
|
|
524
|
+
...event,
|
|
525
|
+
level: nextLevel,
|
|
526
|
+
levelName: nextLevelName
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
function isOptions(input) {
|
|
530
|
+
return typeof input === "object" && input !== null && !Array.isArray(input);
|
|
531
|
+
}
|
|
532
|
+
function isRuleArray(input) {
|
|
533
|
+
return Array.isArray(input);
|
|
534
|
+
}
|
|
535
|
+
function levelOverrideProcessor(input) {
|
|
536
|
+
if (!isRuleArray(input) && !isOptions(input)) return (event, context) => applyLevel(event, resolveLevel(input, event, context));
|
|
537
|
+
const rules = isRuleArray(input) ? input : input.rules;
|
|
538
|
+
return (event, context) => {
|
|
539
|
+
for (const rule of rules) if (matchesRule(event, context, rule)) return applyLevel(event, resolveLevel(rule.level, event, context));
|
|
540
|
+
return event;
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
//#endregion
|
|
544
|
+
//#region src/filter-route.ts
|
|
545
|
+
function stringMatchers(matcher) {
|
|
546
|
+
if (!matcher) return [];
|
|
547
|
+
return Array.isArray(matcher) ? matcher : [matcher];
|
|
548
|
+
}
|
|
549
|
+
function matchesString(matcher, value, event) {
|
|
550
|
+
const matchers = stringMatchers(matcher);
|
|
551
|
+
if (matchers.length === 0) return true;
|
|
552
|
+
for (const item of matchers) {
|
|
553
|
+
if (typeof item === "function" && item(value, event)) return true;
|
|
554
|
+
if (item instanceof RegExp && item.test(value ?? "")) return true;
|
|
555
|
+
if (typeof item === "string" && value === item) return true;
|
|
556
|
+
}
|
|
557
|
+
return false;
|
|
558
|
+
}
|
|
559
|
+
function matchesLevelName(expected, actual) {
|
|
560
|
+
if (!expected) return true;
|
|
561
|
+
return Array.isArray(expected) ? expected.includes(actual) : expected === actual;
|
|
562
|
+
}
|
|
563
|
+
function matchesTags(expected, actual) {
|
|
564
|
+
if (!expected) return true;
|
|
565
|
+
for (const [key, value] of Object.entries(expected)) if (actual?.[key] !== value) return false;
|
|
566
|
+
return true;
|
|
567
|
+
}
|
|
568
|
+
function matchesLevelRange(event, match) {
|
|
569
|
+
if (match.minLevel !== void 0 && event.level < (0, _loggerjs_core.toLevelValue)(match.minLevel)) return false;
|
|
570
|
+
if (match.maxLevel !== void 0 && event.level > (0, _loggerjs_core.toLevelValue)(match.maxLevel)) return false;
|
|
571
|
+
return true;
|
|
572
|
+
}
|
|
573
|
+
function matchesEvent(event, context, match) {
|
|
574
|
+
return (!match.when || match.when(event, context)) && matchesString(match.logger, event.logger, event) && matchesString(match.type, event.type, event) && matchesString(match.integration, event.source?.integration, event) && matchesString(match.runtime, event.source?.runtime, event) && matchesLevelName(match.levelName, event.levelName) && matchesTags(match.tags, event.tags) && matchesLevelRange(event, match);
|
|
575
|
+
}
|
|
576
|
+
function isFilterRuleArray(input) {
|
|
577
|
+
return Array.isArray(input);
|
|
578
|
+
}
|
|
579
|
+
function normalizeFilterOptions(input) {
|
|
580
|
+
return isFilterRuleArray(input) ? { rules: input } : input;
|
|
581
|
+
}
|
|
582
|
+
function reportDrop(options, event, reason) {
|
|
583
|
+
options.onDrop?.(event, reason);
|
|
584
|
+
return false;
|
|
585
|
+
}
|
|
586
|
+
function filterProcessor(input) {
|
|
587
|
+
if (typeof input === "function") return (event, context) => input(event, context) ? event : false;
|
|
588
|
+
const options = normalizeFilterOptions(input);
|
|
589
|
+
const defaultAction = options.defaultAction ?? "keep";
|
|
590
|
+
return (event, context) => {
|
|
591
|
+
for (const rule of options.rules) {
|
|
592
|
+
if (!matchesEvent(event, context, rule)) continue;
|
|
593
|
+
return (rule.action ?? "drop") === "keep" ? event : reportDrop(options, event, rule.reason ?? "rule");
|
|
594
|
+
}
|
|
595
|
+
return defaultAction === "keep" ? event : reportDrop(options, event, "default");
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
function hasRoute(route) {
|
|
599
|
+
return Boolean(route?.transports || route?.excludeTransports);
|
|
600
|
+
}
|
|
601
|
+
function routeFromRule(rule) {
|
|
602
|
+
return {
|
|
603
|
+
transports: rule.transports,
|
|
604
|
+
excludeTransports: rule.excludeTransports
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
function isRouteOptions(input) {
|
|
608
|
+
return typeof input === "object" && input !== null && "rules" in input;
|
|
609
|
+
}
|
|
610
|
+
function isRouteRuleArray(input) {
|
|
611
|
+
return Array.isArray(input);
|
|
612
|
+
}
|
|
613
|
+
function routeProcessor(input) {
|
|
614
|
+
if (!isRouteRuleArray(input) && !isRouteOptions(input)) return (event) => hasRoute(input) ? (0, _loggerjs_core.withLogEventRoute)(event, input) : event;
|
|
615
|
+
const rules = isRouteRuleArray(input) ? input : input.rules;
|
|
616
|
+
const defaultRoute = isRouteRuleArray(input) ? void 0 : input.defaultRoute;
|
|
617
|
+
return (event, context) => {
|
|
618
|
+
for (const rule of rules) if (matchesEvent(event, context, rule)) {
|
|
619
|
+
const route = routeFromRule(rule);
|
|
620
|
+
return hasRoute(route) ? (0, _loggerjs_core.withLogEventRoute)(event, route) : event;
|
|
621
|
+
}
|
|
622
|
+
return hasRoute(defaultRoute) ? (0, _loggerjs_core.withLogEventRoute)(event, defaultRoute) : event;
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
//#endregion
|
|
626
|
+
//#region src/fingerprint.ts
|
|
627
|
+
const DEFAULT_PARTS = [
|
|
628
|
+
"logger",
|
|
629
|
+
"type",
|
|
630
|
+
"message",
|
|
631
|
+
"error.name",
|
|
632
|
+
"error.message",
|
|
633
|
+
"source.integration"
|
|
634
|
+
];
|
|
635
|
+
function fnv1a32(input) {
|
|
636
|
+
let hash = 2166136261;
|
|
637
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
638
|
+
hash ^= input.charCodeAt(index);
|
|
639
|
+
hash = Math.imul(hash, 16777619);
|
|
640
|
+
}
|
|
641
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
642
|
+
}
|
|
643
|
+
function stackTop(stack) {
|
|
644
|
+
if (!stack) return void 0;
|
|
645
|
+
const lines = stack.split("\n");
|
|
646
|
+
return (lines[1] ?? lines[0])?.trim();
|
|
647
|
+
}
|
|
648
|
+
function partValue(part, event, context) {
|
|
649
|
+
if (typeof part === "function") return part(event, context);
|
|
650
|
+
if (part === "logger") return event.logger;
|
|
651
|
+
if (part === "level") return event.levelName;
|
|
652
|
+
if (part === "type") return event.type;
|
|
653
|
+
if (part === "message") return event.message;
|
|
654
|
+
if (part === "error.name") return event.error?.name;
|
|
655
|
+
if (part === "error.message") return event.error?.message;
|
|
656
|
+
if (part === "source.integration") return event.source?.integration;
|
|
657
|
+
if (part === "source.runtime") return event.source?.runtime;
|
|
658
|
+
return stackTop(event.error?.stack);
|
|
659
|
+
}
|
|
660
|
+
function stringifyPart(value) {
|
|
661
|
+
if (value === void 0 || value === null) return "";
|
|
662
|
+
if (typeof value === "string") return value;
|
|
663
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
|
|
664
|
+
if (value instanceof Error) return `${value.name}:${value.message}`;
|
|
665
|
+
return String(value);
|
|
666
|
+
}
|
|
667
|
+
function writeFingerprint(event, target, key, fingerprint) {
|
|
668
|
+
if (target === "context") return {
|
|
669
|
+
...event,
|
|
670
|
+
context: {
|
|
671
|
+
...event.context,
|
|
672
|
+
[key]: fingerprint
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
return {
|
|
676
|
+
...event,
|
|
677
|
+
tags: {
|
|
678
|
+
...event.tags,
|
|
679
|
+
[key]: fingerprint
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
function fingerprintProcessor(options = {}) {
|
|
684
|
+
const parts = options.parts ?? DEFAULT_PARTS;
|
|
685
|
+
const hash = options.hash ?? fnv1a32;
|
|
686
|
+
const target = options.target ?? "tags";
|
|
687
|
+
const key = options.key ?? "fingerprint";
|
|
688
|
+
const separator = options.separator ?? "";
|
|
689
|
+
const prefix = options.prefix ?? "";
|
|
690
|
+
return (event, context) => {
|
|
691
|
+
return writeFingerprint(event, target, key, `${prefix}${hash(parts.map((part) => stringifyPart(partValue(part, event, context))).join(separator))}`);
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
//#endregion
|
|
695
|
+
//#region src/normalize-error.ts
|
|
696
|
+
function stackWithLimit(stack, maxStackLines) {
|
|
697
|
+
if (typeof stack !== "string" || maxStackLines <= 0) return void 0;
|
|
698
|
+
return stack.split("\n").slice(0, maxStackLines).join("\n");
|
|
699
|
+
}
|
|
700
|
+
function errorMessage(value) {
|
|
701
|
+
if (typeof value === "string") return value;
|
|
702
|
+
if (value && typeof value === "object" && "message" in value) {
|
|
703
|
+
const message = value.message;
|
|
704
|
+
if (typeof message === "string") return message;
|
|
705
|
+
}
|
|
706
|
+
return String(value);
|
|
707
|
+
}
|
|
708
|
+
function errorName(value) {
|
|
709
|
+
if (value && typeof value === "object" && "name" in value) {
|
|
710
|
+
const name = value.name;
|
|
711
|
+
if (typeof name === "string") return name;
|
|
712
|
+
}
|
|
713
|
+
return value instanceof Error ? value.name : void 0;
|
|
714
|
+
}
|
|
715
|
+
function objectRecord(value) {
|
|
716
|
+
return value && typeof value === "object" ? value : void 0;
|
|
717
|
+
}
|
|
718
|
+
function normalizeUnknownError(value, options, depth, seen) {
|
|
719
|
+
if (depth > options.maxDepth) return { message: "[Max error depth]" };
|
|
720
|
+
if (value === null || value === void 0) return { message: String(value) };
|
|
721
|
+
if (typeof value !== "object") return { message: errorMessage(value) };
|
|
722
|
+
if (seen.has(value)) return { message: "[Circular error]" };
|
|
723
|
+
seen.add(value);
|
|
724
|
+
const record = objectRecord(value);
|
|
725
|
+
const out = {
|
|
726
|
+
name: errorName(value),
|
|
727
|
+
message: errorMessage(value),
|
|
728
|
+
stack: stackWithLimit(record?.stack, options.maxStackLines)
|
|
729
|
+
};
|
|
730
|
+
const code = record?.code;
|
|
731
|
+
if (typeof code === "string" || typeof code === "number") out.code = code;
|
|
732
|
+
if (record?.cause !== void 0) out.cause = normalizeUnknownError(record.cause, options, depth + 1, seen);
|
|
733
|
+
if (options.includeAggregateErrors && Array.isArray(record?.errors)) out.errors = record.errors.map((item) => normalizeUnknownError(item, options, depth + 1, seen));
|
|
734
|
+
if (options.includeEnumerableProperties && record) for (const key of Object.keys(record)) {
|
|
735
|
+
if (key in out || key === "errors" || key === "cause") continue;
|
|
736
|
+
out[key] = record[key];
|
|
737
|
+
}
|
|
738
|
+
return out;
|
|
739
|
+
}
|
|
740
|
+
function isRecord(value) {
|
|
741
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
742
|
+
}
|
|
743
|
+
function normalizeDataErrors(data, options, seen) {
|
|
744
|
+
if (!isRecord(data) || options.dataErrorKeys.length === 0) return data;
|
|
745
|
+
let next;
|
|
746
|
+
for (const key of options.dataErrorKeys) {
|
|
747
|
+
if (!(key in data) || data[key] === void 0 || data[key] === null) continue;
|
|
748
|
+
next ??= { ...data };
|
|
749
|
+
next[key] = normalizeUnknownError(data[key], options, 0, seen);
|
|
750
|
+
}
|
|
751
|
+
return next ?? data;
|
|
752
|
+
}
|
|
753
|
+
function normalizeErrorProcessor(options = {}) {
|
|
754
|
+
const normalized = {
|
|
755
|
+
maxDepth: Math.max(0, Math.floor(options.maxDepth ?? 5)),
|
|
756
|
+
maxStackLines: Math.max(0, Math.floor(options.maxStackLines ?? 40)),
|
|
757
|
+
includeEnumerableProperties: options.includeEnumerableProperties ?? true,
|
|
758
|
+
includeAggregateErrors: options.includeAggregateErrors ?? true,
|
|
759
|
+
dataErrorKeys: options.dataErrorKeys ?? []
|
|
760
|
+
};
|
|
761
|
+
return (event) => {
|
|
762
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
763
|
+
const error = event.error === void 0 ? void 0 : normalizeUnknownError(event.error, normalized, 0, seen);
|
|
764
|
+
const data = normalizeDataErrors(event.data, normalized, seen);
|
|
765
|
+
if (error === void 0 && data === event.data) return event;
|
|
766
|
+
return {
|
|
767
|
+
...event,
|
|
768
|
+
error,
|
|
769
|
+
data
|
|
770
|
+
};
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
//#endregion
|
|
774
|
+
//#region src/stack-parser.ts
|
|
775
|
+
const V8_FRAME = /^\s*at\s+(?:(.*?)\s+\()?(.+?):(\d+):(\d+)\)?\s*$/;
|
|
776
|
+
const FIREFOX_FRAME = /^\s*(?:(.*?)@)?(.+?):(\d+):(\d+)\s*$/;
|
|
777
|
+
function toNumber(input) {
|
|
778
|
+
const value = Number(input);
|
|
779
|
+
return Number.isFinite(value) ? value : void 0;
|
|
780
|
+
}
|
|
781
|
+
function cleanFunctionName(input) {
|
|
782
|
+
if (!input || input === "async") return void 0;
|
|
783
|
+
return input.trim() || void 0;
|
|
784
|
+
}
|
|
785
|
+
function frameFromMatch(raw, match) {
|
|
786
|
+
return {
|
|
787
|
+
raw,
|
|
788
|
+
function: cleanFunctionName(match[1]),
|
|
789
|
+
file: match[2],
|
|
790
|
+
line: match[3] ? toNumber(match[3]) : void 0,
|
|
791
|
+
column: match[4] ? toNumber(match[4]) : void 0
|
|
792
|
+
};
|
|
793
|
+
}
|
|
794
|
+
function parseLine(raw) {
|
|
795
|
+
const v8 = raw.match(V8_FRAME);
|
|
796
|
+
if (v8) return frameFromMatch(raw, v8);
|
|
797
|
+
const firefox = raw.match(FIREFOX_FRAME);
|
|
798
|
+
if (firefox) return frameFromMatch(raw, firefox);
|
|
799
|
+
return { raw };
|
|
800
|
+
}
|
|
801
|
+
function isInternalFrame(frame) {
|
|
802
|
+
const file = frame.file ?? frame.raw ?? "";
|
|
803
|
+
return file.startsWith("node:internal") || file.includes("/node:internal/");
|
|
804
|
+
}
|
|
805
|
+
function defaultParseStack(stack) {
|
|
806
|
+
const frames = [];
|
|
807
|
+
for (const raw of stack.split("\n")) {
|
|
808
|
+
const line = raw.trim();
|
|
809
|
+
if (!line || !line.includes(":")) continue;
|
|
810
|
+
const frame = parseLine(line);
|
|
811
|
+
if (frame.file || line.startsWith("at ") || line.includes("@")) frames.push(frame);
|
|
812
|
+
}
|
|
813
|
+
return frames;
|
|
814
|
+
}
|
|
815
|
+
function stripRaw(frame) {
|
|
816
|
+
const { raw: _raw, ...rest } = frame;
|
|
817
|
+
return rest;
|
|
818
|
+
}
|
|
819
|
+
function normalizeFrames(frames, options) {
|
|
820
|
+
const out = [];
|
|
821
|
+
for (const frame of frames) {
|
|
822
|
+
if (options.dropInternal && isInternalFrame(frame)) continue;
|
|
823
|
+
out.push(options.includeRaw ? frame : stripRaw(frame));
|
|
824
|
+
if (out.length >= options.maxFrames) break;
|
|
825
|
+
}
|
|
826
|
+
return out;
|
|
827
|
+
}
|
|
828
|
+
function writeFrames(event, options, frames) {
|
|
829
|
+
if (options.target === "context") return {
|
|
830
|
+
...event,
|
|
831
|
+
context: {
|
|
832
|
+
...event.context,
|
|
833
|
+
[options.key]: frames
|
|
834
|
+
}
|
|
835
|
+
};
|
|
836
|
+
return {
|
|
837
|
+
...event,
|
|
838
|
+
error: {
|
|
839
|
+
message: event.error?.message ?? event.message,
|
|
840
|
+
...event.error,
|
|
841
|
+
[options.key]: frames
|
|
842
|
+
}
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
function parseStack(stack) {
|
|
846
|
+
return defaultParseStack(stack);
|
|
847
|
+
}
|
|
848
|
+
function stackParserProcessor(options = {}) {
|
|
849
|
+
const normalized = {
|
|
850
|
+
maxFrames: Math.max(0, Math.floor(options.maxFrames ?? 20)),
|
|
851
|
+
dropInternal: options.dropInternal ?? false,
|
|
852
|
+
includeRaw: options.includeRaw ?? true,
|
|
853
|
+
target: options.target ?? "error",
|
|
854
|
+
key: options.key ?? "frames",
|
|
855
|
+
parser: options.parser ?? defaultParseStack
|
|
856
|
+
};
|
|
857
|
+
return (event) => {
|
|
858
|
+
const stack = event.error?.stack;
|
|
859
|
+
if (!stack || normalized.maxFrames === 0) return event;
|
|
860
|
+
const frames = normalizeFrames(normalized.parser(stack), normalized);
|
|
861
|
+
return frames.length > 0 ? writeFrames(event, normalized, frames) : event;
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
//#endregion
|
|
865
|
+
//#region src/privacy-guard.ts
|
|
866
|
+
const DEFAULT_DENY_KEYS = [
|
|
867
|
+
"password",
|
|
868
|
+
"passwd",
|
|
869
|
+
"secret",
|
|
870
|
+
"token",
|
|
871
|
+
"authorization",
|
|
872
|
+
"cookie",
|
|
873
|
+
"set-cookie",
|
|
874
|
+
"apiKey",
|
|
875
|
+
"api_key",
|
|
876
|
+
/session/i
|
|
877
|
+
];
|
|
878
|
+
function digitsOnly(input) {
|
|
879
|
+
return input.replace(/\D/g, "");
|
|
880
|
+
}
|
|
881
|
+
function passesLuhn(input) {
|
|
882
|
+
const digits = digitsOnly(input);
|
|
883
|
+
if (digits.length < 13 || digits.length > 19) return false;
|
|
884
|
+
let sum = 0;
|
|
885
|
+
let doubleDigit = false;
|
|
886
|
+
for (let index = digits.length - 1; index >= 0; index -= 1) {
|
|
887
|
+
let value = digits.charCodeAt(index) - 48;
|
|
888
|
+
if (doubleDigit) {
|
|
889
|
+
value *= 2;
|
|
890
|
+
if (value > 9) value -= 9;
|
|
891
|
+
}
|
|
892
|
+
sum += value;
|
|
893
|
+
doubleDigit = !doubleDigit;
|
|
894
|
+
}
|
|
895
|
+
return sum % 10 === 0;
|
|
896
|
+
}
|
|
897
|
+
const DEFAULT_PATTERNS = [
|
|
898
|
+
{
|
|
899
|
+
name: "email",
|
|
900
|
+
pattern: /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi
|
|
901
|
+
},
|
|
902
|
+
{
|
|
903
|
+
name: "bearer-token",
|
|
904
|
+
pattern: /\bBearer\s+[A-Za-z0-9._~+/=-]+\b/g
|
|
905
|
+
},
|
|
906
|
+
{
|
|
907
|
+
name: "credit-card",
|
|
908
|
+
pattern: /\b(?:\d[ -]*?){13,19}\b/g,
|
|
909
|
+
validate: passesLuhn
|
|
910
|
+
}
|
|
911
|
+
];
|
|
912
|
+
function matcherMatches(matcher, key, path, value) {
|
|
913
|
+
if (typeof matcher === "string") return matcher.toLowerCase() === key.toLowerCase();
|
|
914
|
+
if (matcher instanceof RegExp) {
|
|
915
|
+
matcher.lastIndex = 0;
|
|
916
|
+
return matcher.test(key) || matcher.test(path);
|
|
917
|
+
}
|
|
918
|
+
return matcher(key, path, value);
|
|
919
|
+
}
|
|
920
|
+
function matchesAny(matchers, key, path, value) {
|
|
921
|
+
return matchers.some((matcher) => matcherMatches(matcher, key, path, value));
|
|
922
|
+
}
|
|
923
|
+
function redact(path, reason, options) {
|
|
924
|
+
options.onRedact?.(path, reason);
|
|
925
|
+
return options.replacement;
|
|
926
|
+
}
|
|
927
|
+
function guardString(input, path, options) {
|
|
928
|
+
let value = input;
|
|
929
|
+
for (const item of options.patterns) {
|
|
930
|
+
item.pattern.lastIndex = 0;
|
|
931
|
+
value = value.replace(item.pattern, (match) => {
|
|
932
|
+
if (item.validate && !item.validate(match)) return match;
|
|
933
|
+
options.onRedact?.(path, item.name);
|
|
934
|
+
return item.replacement ?? options.replacement;
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
if (value.length > options.maxStringLength) {
|
|
938
|
+
options.onRedact?.(path, "max-string-length");
|
|
939
|
+
value = `${value.slice(0, options.maxStringLength)}${options.truncateSuffix}`;
|
|
940
|
+
}
|
|
941
|
+
return {
|
|
942
|
+
value,
|
|
943
|
+
changed: value !== input
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
function guardValue(value, path, key, depth, options, seen) {
|
|
947
|
+
if (matchesAny(options.denyKeys, key, path, value) && !matchesAny(options.allowKeys, key, path, value)) return {
|
|
948
|
+
value: redact(path, "deny-key", options),
|
|
949
|
+
changed: true
|
|
950
|
+
};
|
|
951
|
+
if (typeof value === "string") return guardString(value, path, options);
|
|
952
|
+
if (value === null || value === void 0 || typeof value !== "object") return {
|
|
953
|
+
value,
|
|
954
|
+
changed: false
|
|
955
|
+
};
|
|
956
|
+
if (depth >= options.maxDepth) return {
|
|
957
|
+
value: redact(path, "max-depth", options),
|
|
958
|
+
changed: true
|
|
959
|
+
};
|
|
960
|
+
if (seen.has(value)) return {
|
|
961
|
+
value: seen.get(value),
|
|
962
|
+
changed: true
|
|
963
|
+
};
|
|
964
|
+
if (value instanceof Date || value instanceof Error) return {
|
|
965
|
+
value,
|
|
966
|
+
changed: false
|
|
967
|
+
};
|
|
968
|
+
if (Array.isArray(value)) {
|
|
969
|
+
const out = [];
|
|
970
|
+
seen.set(value, out);
|
|
971
|
+
let changed = false;
|
|
972
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
973
|
+
const child = guardValue(value[index], `${path}[${index}]`, String(index), depth + 1, options, seen);
|
|
974
|
+
out[index] = child.value;
|
|
975
|
+
changed ||= child.changed;
|
|
976
|
+
}
|
|
977
|
+
return {
|
|
978
|
+
value: changed ? out : value,
|
|
979
|
+
changed
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
const input = value;
|
|
983
|
+
const out = {};
|
|
984
|
+
seen.set(value, out);
|
|
985
|
+
let changed = false;
|
|
986
|
+
for (const [childKey, childValue] of Object.entries(input)) {
|
|
987
|
+
const child = guardValue(childValue, path ? `${path}.${childKey}` : childKey, childKey, depth + 1, options, seen);
|
|
988
|
+
out[childKey] = child.value;
|
|
989
|
+
changed ||= child.changed;
|
|
990
|
+
}
|
|
991
|
+
return {
|
|
992
|
+
value: changed ? out : value,
|
|
993
|
+
changed
|
|
994
|
+
};
|
|
995
|
+
}
|
|
996
|
+
function guardField(value, path, options) {
|
|
997
|
+
const guarded = guardValue(value, path, path, 0, options, /* @__PURE__ */ new WeakMap());
|
|
998
|
+
return {
|
|
999
|
+
value: guarded.value,
|
|
1000
|
+
changed: guarded.changed
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
function maybeSet(target, key, value, changed) {
|
|
1004
|
+
if (!changed) return target;
|
|
1005
|
+
return {
|
|
1006
|
+
...target,
|
|
1007
|
+
[key]: value
|
|
1008
|
+
};
|
|
1009
|
+
}
|
|
1010
|
+
function privacyGuardProcessor(options = {}) {
|
|
1011
|
+
const normalized = {
|
|
1012
|
+
targets: new Set(options.targets ?? [
|
|
1013
|
+
"message",
|
|
1014
|
+
"data",
|
|
1015
|
+
"context",
|
|
1016
|
+
"tags",
|
|
1017
|
+
"error"
|
|
1018
|
+
]),
|
|
1019
|
+
denyKeys: options.denyKeys ?? DEFAULT_DENY_KEYS,
|
|
1020
|
+
allowKeys: options.allowKeys ?? [],
|
|
1021
|
+
patterns: options.patterns ?? DEFAULT_PATTERNS,
|
|
1022
|
+
replacement: options.replacement ?? "[REDACTED]",
|
|
1023
|
+
maxDepth: Math.max(0, Math.floor(options.maxDepth ?? 8)),
|
|
1024
|
+
maxStringLength: Math.max(1, Math.floor(options.maxStringLength ?? 8192)),
|
|
1025
|
+
truncateSuffix: options.truncateSuffix ?? "...",
|
|
1026
|
+
onRedact: options.onRedact
|
|
1027
|
+
};
|
|
1028
|
+
return (event) => {
|
|
1029
|
+
let next = event;
|
|
1030
|
+
if (normalized.targets.has("message")) {
|
|
1031
|
+
const result = guardString(event.message, "message", normalized);
|
|
1032
|
+
next = maybeSet(next, "message", result.value, result.changed);
|
|
1033
|
+
}
|
|
1034
|
+
if (normalized.targets.has("data")) {
|
|
1035
|
+
const result = guardField(event.data, "data", normalized);
|
|
1036
|
+
next = maybeSet(next, "data", result.value, result.changed);
|
|
1037
|
+
}
|
|
1038
|
+
if (normalized.targets.has("context")) {
|
|
1039
|
+
const result = guardField(event.context, "context", normalized);
|
|
1040
|
+
next = maybeSet(next, "context", result.value, result.changed);
|
|
1041
|
+
}
|
|
1042
|
+
if (normalized.targets.has("tags")) {
|
|
1043
|
+
const result = guardField(event.tags, "tags", normalized);
|
|
1044
|
+
next = maybeSet(next, "tags", result.value, result.changed);
|
|
1045
|
+
}
|
|
1046
|
+
if (normalized.targets.has("error")) {
|
|
1047
|
+
const result = guardField(event.error, "error", normalized);
|
|
1048
|
+
next = maybeSet(next, "error", result.value, result.changed);
|
|
1049
|
+
}
|
|
1050
|
+
return next;
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
//#endregion
|
|
1054
|
+
//#region src/schema-dev-check.ts
|
|
1055
|
+
function resultToErrors(result) {
|
|
1056
|
+
if (result === void 0 || result === true) return [];
|
|
1057
|
+
if (result === false) return ["schema validation failed"];
|
|
1058
|
+
if (typeof result === "string") return [result];
|
|
1059
|
+
return result;
|
|
1060
|
+
}
|
|
1061
|
+
function validatorFor(event, context, options) {
|
|
1062
|
+
return options.validate ?? options.select?.(event, context) ?? (event.type ? options.validators?.[event.type] : void 0);
|
|
1063
|
+
}
|
|
1064
|
+
function tagInvalid(event, options, errors) {
|
|
1065
|
+
return {
|
|
1066
|
+
...event,
|
|
1067
|
+
tags: {
|
|
1068
|
+
...event.tags,
|
|
1069
|
+
[options.tagKey ?? "schemaInvalid"]: true
|
|
1070
|
+
},
|
|
1071
|
+
context: {
|
|
1072
|
+
...event.context,
|
|
1073
|
+
[options.contextKey ?? "schemaErrors"]: [...errors]
|
|
1074
|
+
}
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
function reportInvalid(event, context, options, errors) {
|
|
1078
|
+
options.onInvalid?.(event, errors);
|
|
1079
|
+
context.reportInternalError(/* @__PURE__ */ new Error(`loggerjs schema validation failed: ${errors.join("; ")}`), {
|
|
1080
|
+
phase: "processor",
|
|
1081
|
+
processor: "schema-dev-check",
|
|
1082
|
+
eventType: event.type,
|
|
1083
|
+
logger: event.logger
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
function schemaDevCheckProcessor(options = {}) {
|
|
1087
|
+
const enabled = options.enabled ?? true;
|
|
1088
|
+
const action = options.action ?? "report";
|
|
1089
|
+
return (event, context) => {
|
|
1090
|
+
if (!enabled) return event;
|
|
1091
|
+
const validator = validatorFor(event, context, options);
|
|
1092
|
+
if (!validator) return event;
|
|
1093
|
+
let errors;
|
|
1094
|
+
try {
|
|
1095
|
+
errors = resultToErrors(validator(event.data, event, context));
|
|
1096
|
+
} catch (error) {
|
|
1097
|
+
context.reportInternalError(error, {
|
|
1098
|
+
phase: "processor",
|
|
1099
|
+
processor: "schema-dev-check",
|
|
1100
|
+
eventType: event.type,
|
|
1101
|
+
logger: event.logger
|
|
1102
|
+
});
|
|
1103
|
+
return event;
|
|
1104
|
+
}
|
|
1105
|
+
if (errors.length === 0) return event;
|
|
1106
|
+
if (action === "drop") {
|
|
1107
|
+
options.onInvalid?.(event, errors);
|
|
1108
|
+
return false;
|
|
1109
|
+
}
|
|
1110
|
+
if (action === "tag") {
|
|
1111
|
+
reportInvalid(event, context, options, errors);
|
|
1112
|
+
return tagInvalid(event, options, errors);
|
|
1113
|
+
}
|
|
1114
|
+
reportInvalid(event, context, options, errors);
|
|
1115
|
+
return event;
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
//#endregion
|
|
1119
|
+
//#region src/dynamic-sampler.ts
|
|
1120
|
+
const DEFAULT_EXEMPT_LEVELS = new Set(["error", "fatal"]);
|
|
1121
|
+
function defaultKey$1(event) {
|
|
1122
|
+
return event.trace?.traceId ?? `${event.logger}:${event.levelName}:${event.type ?? "manual"}`;
|
|
1123
|
+
}
|
|
1124
|
+
function clampRate(rate) {
|
|
1125
|
+
if (!Number.isFinite(rate) || Number.isNaN(rate)) return 1;
|
|
1126
|
+
return Math.max(0, Math.min(1, rate));
|
|
1127
|
+
}
|
|
1128
|
+
function hashRatio(input) {
|
|
1129
|
+
let hash = 2166136261;
|
|
1130
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
1131
|
+
hash ^= input.charCodeAt(index);
|
|
1132
|
+
hash = Math.imul(hash, 16777619);
|
|
1133
|
+
}
|
|
1134
|
+
return (hash >>> 0) / 4294967296;
|
|
1135
|
+
}
|
|
1136
|
+
function snapshot$1(stats) {
|
|
1137
|
+
return {
|
|
1138
|
+
key: stats.key,
|
|
1139
|
+
seen: stats.seen,
|
|
1140
|
+
kept: stats.kept,
|
|
1141
|
+
dropped: stats.dropped,
|
|
1142
|
+
lastSeenMs: stats.lastSeenMs
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
function decisionContext(stats, now) {
|
|
1146
|
+
return {
|
|
1147
|
+
...snapshot$1(stats),
|
|
1148
|
+
now
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
function resolveRule(event, context, options) {
|
|
1152
|
+
const rule = options.rules?.find((item) => !item.when || item.when(event, context));
|
|
1153
|
+
return {
|
|
1154
|
+
rate: rule?.rate ?? options.defaultRate ?? 1,
|
|
1155
|
+
key: rule?.key ?? options.key ?? defaultKey$1,
|
|
1156
|
+
stickyBy: rule?.stickyBy ?? options.stickyBy
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
function prune$1(statsByKey, maxKeys) {
|
|
1160
|
+
while (statsByKey.size > maxKeys) {
|
|
1161
|
+
let oldest;
|
|
1162
|
+
for (const item of statsByKey.values()) if (!oldest || item.lastSeenMs < oldest.lastSeenMs) oldest = item;
|
|
1163
|
+
if (!oldest) return;
|
|
1164
|
+
statsByKey.delete(oldest.key);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
function shouldKeep(event, rule, rate, random) {
|
|
1168
|
+
if (rate >= 1) return true;
|
|
1169
|
+
if (rate <= 0) return false;
|
|
1170
|
+
const stickyKey = rule.stickyBy?.(event);
|
|
1171
|
+
return (stickyKey ? hashRatio(stickyKey) : random()) < rate;
|
|
1172
|
+
}
|
|
1173
|
+
function dynamicSamplerProcessor(options = {}) {
|
|
1174
|
+
const random = options.random ?? Math.random;
|
|
1175
|
+
const exemptLevels = new Set(options.exemptLevels ?? DEFAULT_EXEMPT_LEVELS);
|
|
1176
|
+
const maxKeys = Math.max(1, Math.floor(options.maxKeys ?? 1e4));
|
|
1177
|
+
const statsByKey = /* @__PURE__ */ new Map();
|
|
1178
|
+
const processor = ((event, context) => {
|
|
1179
|
+
if (exemptLevels.has(event.levelName)) return event;
|
|
1180
|
+
const now = context.now();
|
|
1181
|
+
const rule = resolveRule(event, context, options);
|
|
1182
|
+
const key = (rule.key ?? defaultKey$1)(event);
|
|
1183
|
+
let stats = statsByKey.get(key);
|
|
1184
|
+
if (!stats) {
|
|
1185
|
+
stats = {
|
|
1186
|
+
key,
|
|
1187
|
+
seen: 0,
|
|
1188
|
+
kept: 0,
|
|
1189
|
+
dropped: 0,
|
|
1190
|
+
lastSeenMs: now
|
|
1191
|
+
};
|
|
1192
|
+
statsByKey.set(key, stats);
|
|
1193
|
+
prune$1(statsByKey, maxKeys);
|
|
1194
|
+
}
|
|
1195
|
+
stats.seen += 1;
|
|
1196
|
+
stats.lastSeenMs = now;
|
|
1197
|
+
const rate = clampRate(typeof rule.rate === "function" ? rule.rate(event, decisionContext(stats, now)) : rule.rate);
|
|
1198
|
+
if (shouldKeep(event, rule, rate, random)) {
|
|
1199
|
+
stats.kept += 1;
|
|
1200
|
+
return event;
|
|
1201
|
+
}
|
|
1202
|
+
stats.dropped += 1;
|
|
1203
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)("processor.dynamicSampler.dropped");
|
|
1204
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)(`processor.dynamicSampler.dropped.${event.levelName}`);
|
|
1205
|
+
options.onDrop?.(event, key, rate);
|
|
1206
|
+
return false;
|
|
1207
|
+
});
|
|
1208
|
+
processor.stats = () => [...statsByKey.values()].map(snapshot$1);
|
|
1209
|
+
processor.reset = (key) => {
|
|
1210
|
+
if (key) statsByKey.delete(key);
|
|
1211
|
+
else statsByKey.clear();
|
|
1212
|
+
};
|
|
1213
|
+
return processor;
|
|
1214
|
+
}
|
|
1215
|
+
//#endregion
|
|
1216
|
+
//#region src/breadcrumb-buffer.ts
|
|
1217
|
+
function defaultKey(event) {
|
|
1218
|
+
const contextKey = event.context?.sessionId ?? event.context?.userId;
|
|
1219
|
+
return event.trace?.traceId ?? (contextKey === void 0 ? event.logger : String(contextKey));
|
|
1220
|
+
}
|
|
1221
|
+
function defaultBreadcrumb(event) {
|
|
1222
|
+
return {
|
|
1223
|
+
time: event.time,
|
|
1224
|
+
levelName: event.levelName,
|
|
1225
|
+
logger: event.logger,
|
|
1226
|
+
message: event.message,
|
|
1227
|
+
type: event.type,
|
|
1228
|
+
tags: event.tags,
|
|
1229
|
+
source: event.source
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
function normalizeCount(value, fallback) {
|
|
1233
|
+
if (value === void 0 || !Number.isFinite(value)) return fallback;
|
|
1234
|
+
return Math.max(0, Math.floor(value));
|
|
1235
|
+
}
|
|
1236
|
+
function normalizeBucketCount(value) {
|
|
1237
|
+
if (value === void 0 || !Number.isFinite(value)) return 1024;
|
|
1238
|
+
return Math.max(1, Math.floor(value));
|
|
1239
|
+
}
|
|
1240
|
+
function snapshot(state) {
|
|
1241
|
+
return {
|
|
1242
|
+
key: state.key,
|
|
1243
|
+
buffered: state.buffer.length,
|
|
1244
|
+
lastSeenMs: state.lastSeenMs
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
function prune(states, maxBuckets) {
|
|
1248
|
+
while (states.size > maxBuckets) {
|
|
1249
|
+
let oldest;
|
|
1250
|
+
for (const state of states.values()) if (!oldest || state.lastSeenMs < oldest.lastSeenMs) oldest = state;
|
|
1251
|
+
if (!oldest) return;
|
|
1252
|
+
states.delete(oldest.key);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
function attachBreadcrumbs(event, target, field, breadcrumbs) {
|
|
1256
|
+
if (breadcrumbs.length === 0) return event;
|
|
1257
|
+
if (target === "data" && event.data && typeof event.data === "object" && !Array.isArray(event.data)) return {
|
|
1258
|
+
...event,
|
|
1259
|
+
data: {
|
|
1260
|
+
...event.data,
|
|
1261
|
+
[field]: breadcrumbs
|
|
1262
|
+
}
|
|
1263
|
+
};
|
|
1264
|
+
if (target === "data") return {
|
|
1265
|
+
...event,
|
|
1266
|
+
data: {
|
|
1267
|
+
value: event.data,
|
|
1268
|
+
[field]: breadcrumbs
|
|
1269
|
+
}
|
|
1270
|
+
};
|
|
1271
|
+
return {
|
|
1272
|
+
...event,
|
|
1273
|
+
context: {
|
|
1274
|
+
...event.context,
|
|
1275
|
+
[field]: breadcrumbs
|
|
1276
|
+
}
|
|
1277
|
+
};
|
|
1278
|
+
}
|
|
1279
|
+
function breadcrumbBufferProcessor(options = {}) {
|
|
1280
|
+
const triggerLevel = (0, _loggerjs_core.toLevelValue)(options.triggerLevel ?? "error");
|
|
1281
|
+
const shouldAttach = options.shouldAttach ?? ((event) => event.level >= triggerLevel);
|
|
1282
|
+
const shouldBuffer = options.shouldBuffer ?? ((event) => event.level < triggerLevel);
|
|
1283
|
+
const bufferSize = normalizeCount(options.bufferSize, 50);
|
|
1284
|
+
const maxBuckets = normalizeBucketCount(options.maxBuckets);
|
|
1285
|
+
const keyFor = options.key ?? defaultKey;
|
|
1286
|
+
const map = options.map ?? defaultBreadcrumb;
|
|
1287
|
+
const target = options.target ?? "context";
|
|
1288
|
+
const field = options.field ?? "breadcrumbs";
|
|
1289
|
+
const includeTrigger = options.includeTrigger ?? false;
|
|
1290
|
+
const clearOnTrigger = options.clearOnTrigger ?? false;
|
|
1291
|
+
const states = /* @__PURE__ */ new Map();
|
|
1292
|
+
const getState = (key, now) => {
|
|
1293
|
+
let state = states.get(key);
|
|
1294
|
+
if (!state) {
|
|
1295
|
+
state = {
|
|
1296
|
+
key,
|
|
1297
|
+
buffer: [],
|
|
1298
|
+
lastSeenMs: now
|
|
1299
|
+
};
|
|
1300
|
+
states.set(key, state);
|
|
1301
|
+
prune(states, maxBuckets);
|
|
1302
|
+
}
|
|
1303
|
+
state.lastSeenMs = now;
|
|
1304
|
+
return state;
|
|
1305
|
+
};
|
|
1306
|
+
const processor = ((event) => {
|
|
1307
|
+
const state = getState(keyFor(event), event.time);
|
|
1308
|
+
if (shouldAttach(event)) {
|
|
1309
|
+
const next = attachBreadcrumbs(event, target, field, includeTrigger ? [...state.buffer, map(event)] : [...state.buffer]);
|
|
1310
|
+
if (clearOnTrigger) state.buffer.splice(0, state.buffer.length);
|
|
1311
|
+
return next;
|
|
1312
|
+
}
|
|
1313
|
+
if (bufferSize > 0 && shouldBuffer(event)) {
|
|
1314
|
+
state.buffer.push(map(event));
|
|
1315
|
+
if (state.buffer.length > bufferSize) state.buffer.splice(0, state.buffer.length - bufferSize);
|
|
1316
|
+
}
|
|
1317
|
+
return event;
|
|
1318
|
+
});
|
|
1319
|
+
processor.states = () => [...states.values()].map(snapshot);
|
|
1320
|
+
processor.reset = (key) => {
|
|
1321
|
+
if (key) states.delete(key);
|
|
1322
|
+
else states.clear();
|
|
1323
|
+
};
|
|
1324
|
+
return processor;
|
|
1325
|
+
}
|
|
1326
|
+
//#endregion
|
|
1327
|
+
exports.breadcrumbBuffer = breadcrumbBufferProcessor;
|
|
1328
|
+
exports.breadcrumbBufferProcessor = breadcrumbBufferProcessor;
|
|
1329
|
+
exports.context = contextProcessor;
|
|
1330
|
+
exports.contextMiddleware = contextMiddleware;
|
|
1331
|
+
exports.contextMw = contextMiddleware;
|
|
1332
|
+
exports.contextProcessor = contextProcessor;
|
|
1333
|
+
exports.dedupe = dedupeProcessor;
|
|
1334
|
+
exports.dedupeProcessor = dedupeProcessor;
|
|
1335
|
+
exports.dynamicSampler = dynamicSamplerProcessor;
|
|
1336
|
+
exports.dynamicSamplerProcessor = dynamicSamplerProcessor;
|
|
1337
|
+
exports.enrich = enrichProcessor;
|
|
1338
|
+
exports.enrichMiddleware = enrichMiddleware;
|
|
1339
|
+
exports.enrichMw = enrichMiddleware;
|
|
1340
|
+
exports.enrichProcessor = enrichProcessor;
|
|
1341
|
+
exports.filter = filterProcessor;
|
|
1342
|
+
exports.filterProcessor = filterProcessor;
|
|
1343
|
+
exports.fingerprint = fingerprintProcessor;
|
|
1344
|
+
exports.fingerprintProcessor = fingerprintProcessor;
|
|
1345
|
+
exports.fingersCrossed = fingersCrossedProcessor;
|
|
1346
|
+
exports.fingersCrossedProcessor = fingersCrossedProcessor;
|
|
1347
|
+
exports.levelOverride = levelOverrideProcessor;
|
|
1348
|
+
exports.levelOverrideProcessor = levelOverrideProcessor;
|
|
1349
|
+
exports.logType = typeProcessor;
|
|
1350
|
+
exports.logTypeMw = typeMiddleware;
|
|
1351
|
+
exports.normalizeError = normalizeErrorProcessor;
|
|
1352
|
+
exports.normalizeErrorProcessor = normalizeErrorProcessor;
|
|
1353
|
+
exports.parseStack = parseStack;
|
|
1354
|
+
exports.privacyGuard = privacyGuardProcessor;
|
|
1355
|
+
exports.privacyGuardProcessor = privacyGuardProcessor;
|
|
1356
|
+
exports.rateLimit = rateLimitProcessor;
|
|
1357
|
+
exports.rateLimitProcessor = rateLimitProcessor;
|
|
1358
|
+
exports.redact = redactProcessor;
|
|
1359
|
+
exports.redactProcessor = redactProcessor;
|
|
1360
|
+
exports.route = routeProcessor;
|
|
1361
|
+
exports.routeProcessor = routeProcessor;
|
|
1362
|
+
exports.sample = sampleProcessor;
|
|
1363
|
+
exports.sampleProcessor = sampleProcessor;
|
|
1364
|
+
exports.schemaDevCheck = schemaDevCheckProcessor;
|
|
1365
|
+
exports.schemaDevCheckProcessor = schemaDevCheckProcessor;
|
|
1366
|
+
exports.stackParser = stackParserProcessor;
|
|
1367
|
+
exports.stackParserProcessor = stackParserProcessor;
|
|
1368
|
+
exports.tags = tagsProcessor;
|
|
1369
|
+
exports.tagsMiddleware = tagsMiddleware;
|
|
1370
|
+
exports.tagsMw = tagsMiddleware;
|
|
1371
|
+
exports.tagsProcessor = tagsProcessor;
|
|
1372
|
+
exports.traceContext = traceContextProcessor;
|
|
1373
|
+
exports.traceContextMiddleware = traceContextMiddleware;
|
|
1374
|
+
exports.traceContextMw = traceContextMiddleware;
|
|
1375
|
+
exports.traceContextProcessor = traceContextProcessor;
|
|
1376
|
+
exports.typeMiddleware = typeMiddleware;
|
|
1377
|
+
exports.typeProcessor = typeProcessor;
|
|
1378
|
+
|
|
1379
|
+
//# sourceMappingURL=index.cjs.map
|