@rawnodes/logger 1.7.0 → 1.8.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 +200 -2
- package/dist/index.d.mts +142 -6
- package/dist/index.d.ts +142 -6
- package/dist/index.js +509 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +503 -22
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
package/dist/index.mjs
CHANGED
|
@@ -2,6 +2,8 @@ import { createLogger, transports, format } from 'winston';
|
|
|
2
2
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
3
3
|
import DailyRotateFile from 'winston-daily-rotate-file';
|
|
4
4
|
import { inspect } from 'util';
|
|
5
|
+
import TransportStream from 'winston-transport';
|
|
6
|
+
import { CloudWatchLogsClient, PutLogEventsCommand, CreateLogGroupCommand, CreateLogStreamCommand, DescribeLogStreamsCommand } from '@aws-sdk/client-cloudwatch-logs';
|
|
5
7
|
import { randomUUID } from 'crypto';
|
|
6
8
|
|
|
7
9
|
// src/state.ts
|
|
@@ -15,6 +17,26 @@ var LoggerStore = class {
|
|
|
15
17
|
}
|
|
16
18
|
};
|
|
17
19
|
|
|
20
|
+
// src/types.ts
|
|
21
|
+
var LOG_LEVELS = {
|
|
22
|
+
off: -1,
|
|
23
|
+
error: 0,
|
|
24
|
+
warn: 1,
|
|
25
|
+
info: 2,
|
|
26
|
+
http: 3,
|
|
27
|
+
verbose: 4,
|
|
28
|
+
debug: 5,
|
|
29
|
+
silly: 6
|
|
30
|
+
};
|
|
31
|
+
function isValidLogLevel(level) {
|
|
32
|
+
return level in LOG_LEVELS;
|
|
33
|
+
}
|
|
34
|
+
function assertLogLevel(level) {
|
|
35
|
+
if (!isValidLogLevel(level)) {
|
|
36
|
+
throw new Error(`Invalid log level: "${level}". Valid levels: ${Object.keys(LOG_LEVELS).join(", ")}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
18
40
|
// src/utils/mask-secrets.ts
|
|
19
41
|
var DEFAULT_SECRET_PATTERNS = [
|
|
20
42
|
"password",
|
|
@@ -169,6 +191,20 @@ function maskSecretsFormat(options) {
|
|
|
169
191
|
return maskSecrets(info, options);
|
|
170
192
|
})();
|
|
171
193
|
}
|
|
194
|
+
function createFilterFormat(defaultLevel, rules, store) {
|
|
195
|
+
if (!rules?.length && defaultLevel === void 0) {
|
|
196
|
+
return format((info) => info)();
|
|
197
|
+
}
|
|
198
|
+
return format((info) => {
|
|
199
|
+
const logLevel = info.level;
|
|
200
|
+
const context = info.context;
|
|
201
|
+
const storeContext = store.getStore();
|
|
202
|
+
const matchingRule = rules?.find((rule) => matchesContext(storeContext, context, rule.match));
|
|
203
|
+
const effectiveLevel = matchingRule?.level ?? defaultLevel ?? "silly";
|
|
204
|
+
if (effectiveLevel === "off") return false;
|
|
205
|
+
return LOG_LEVELS[logLevel] <= LOG_LEVELS[effectiveLevel] ? info : false;
|
|
206
|
+
})();
|
|
207
|
+
}
|
|
172
208
|
function createPlainFormat(store) {
|
|
173
209
|
return format.combine(
|
|
174
210
|
format.errors({ stack: true }),
|
|
@@ -233,17 +269,457 @@ function createFormat(logFormat, store) {
|
|
|
233
269
|
}
|
|
234
270
|
}
|
|
235
271
|
|
|
272
|
+
// src/transports/buffer.ts
|
|
273
|
+
var MessageBuffer = class {
|
|
274
|
+
constructor(options) {
|
|
275
|
+
this.options = options;
|
|
276
|
+
}
|
|
277
|
+
queue = [];
|
|
278
|
+
timer = null;
|
|
279
|
+
flushing = false;
|
|
280
|
+
closed = false;
|
|
281
|
+
add(message) {
|
|
282
|
+
if (this.closed) return;
|
|
283
|
+
this.queue.push(message);
|
|
284
|
+
if (this.queue.length >= this.options.batchSize) {
|
|
285
|
+
void this.flush();
|
|
286
|
+
} else {
|
|
287
|
+
this.scheduleFlush();
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
async flush() {
|
|
291
|
+
if (this.flushing || this.queue.length === 0) return;
|
|
292
|
+
this.flushing = true;
|
|
293
|
+
this.clearTimer();
|
|
294
|
+
const messages = this.queue.splice(0, this.options.batchSize);
|
|
295
|
+
try {
|
|
296
|
+
await this.sendWithRetry(messages);
|
|
297
|
+
} catch (error) {
|
|
298
|
+
this.options.onError?.(error, messages);
|
|
299
|
+
} finally {
|
|
300
|
+
this.flushing = false;
|
|
301
|
+
if (this.queue.length > 0 && !this.closed) {
|
|
302
|
+
void this.flush();
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
async close() {
|
|
307
|
+
this.closed = true;
|
|
308
|
+
this.clearTimer();
|
|
309
|
+
while (this.queue.length > 0) {
|
|
310
|
+
await this.flush();
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
scheduleFlush() {
|
|
314
|
+
if (this.timer || this.closed) return;
|
|
315
|
+
this.timer = setTimeout(() => {
|
|
316
|
+
this.timer = null;
|
|
317
|
+
void this.flush();
|
|
318
|
+
}, this.options.flushInterval);
|
|
319
|
+
}
|
|
320
|
+
clearTimer() {
|
|
321
|
+
if (this.timer) {
|
|
322
|
+
clearTimeout(this.timer);
|
|
323
|
+
this.timer = null;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
async sendWithRetry(messages) {
|
|
327
|
+
let lastError = null;
|
|
328
|
+
for (let attempt = 0; attempt < this.options.maxRetries; attempt++) {
|
|
329
|
+
try {
|
|
330
|
+
await this.options.onFlush(messages);
|
|
331
|
+
return;
|
|
332
|
+
} catch (error) {
|
|
333
|
+
lastError = error;
|
|
334
|
+
if (attempt < this.options.maxRetries - 1) {
|
|
335
|
+
await this.delay(this.options.retryDelay * Math.pow(2, attempt));
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
throw lastError;
|
|
340
|
+
}
|
|
341
|
+
delay(ms) {
|
|
342
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
// src/transports/base-http.ts
|
|
347
|
+
var DEFAULT_OPTIONS = {
|
|
348
|
+
batchSize: 10,
|
|
349
|
+
flushInterval: 5e3,
|
|
350
|
+
maxRetries: 3,
|
|
351
|
+
retryDelay: 1e3
|
|
352
|
+
};
|
|
353
|
+
var BaseHttpTransport = class extends TransportStream {
|
|
354
|
+
buffer;
|
|
355
|
+
constructor(opts = {}) {
|
|
356
|
+
super();
|
|
357
|
+
this.buffer = new MessageBuffer({
|
|
358
|
+
batchSize: opts.batchSize ?? DEFAULT_OPTIONS.batchSize,
|
|
359
|
+
flushInterval: opts.flushInterval ?? DEFAULT_OPTIONS.flushInterval,
|
|
360
|
+
maxRetries: opts.maxRetries ?? DEFAULT_OPTIONS.maxRetries,
|
|
361
|
+
retryDelay: opts.retryDelay ?? DEFAULT_OPTIONS.retryDelay,
|
|
362
|
+
onFlush: this.sendBatch.bind(this),
|
|
363
|
+
onError: this.handleError.bind(this)
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
log(info, callback) {
|
|
367
|
+
const message = this.transformMessage(info);
|
|
368
|
+
this.buffer.add(message);
|
|
369
|
+
callback();
|
|
370
|
+
}
|
|
371
|
+
close() {
|
|
372
|
+
return this.buffer.close();
|
|
373
|
+
}
|
|
374
|
+
transformMessage(info) {
|
|
375
|
+
const { level, message, timestamp, context, ...meta } = info;
|
|
376
|
+
return {
|
|
377
|
+
level,
|
|
378
|
+
message: String(message),
|
|
379
|
+
timestamp: timestamp ? new Date(String(timestamp)) : /* @__PURE__ */ new Date(),
|
|
380
|
+
context,
|
|
381
|
+
meta: Object.keys(meta).length > 0 ? meta : void 0
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
handleError(error, messages) {
|
|
385
|
+
console.error(
|
|
386
|
+
`[${this.constructor.name}] Failed to send ${messages.length} messages:`,
|
|
387
|
+
error.message
|
|
388
|
+
);
|
|
389
|
+
this.emit("error", error);
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
// src/transports/discord.ts
|
|
394
|
+
var DEFAULT_EMBED_COLORS = {
|
|
395
|
+
off: 0,
|
|
396
|
+
error: 15548997,
|
|
397
|
+
warn: 16705372,
|
|
398
|
+
info: 5763719,
|
|
399
|
+
http: 5793266,
|
|
400
|
+
verbose: 10181046,
|
|
401
|
+
debug: 3447003,
|
|
402
|
+
silly: 9807270
|
|
403
|
+
};
|
|
404
|
+
var DiscordTransport = class extends BaseHttpTransport {
|
|
405
|
+
config;
|
|
406
|
+
constructor(config) {
|
|
407
|
+
super({
|
|
408
|
+
batchSize: config.batchSize ?? 10,
|
|
409
|
+
flushInterval: config.flushInterval ?? 2e3,
|
|
410
|
+
maxRetries: config.maxRetries,
|
|
411
|
+
retryDelay: config.retryDelay
|
|
412
|
+
});
|
|
413
|
+
this.config = config;
|
|
414
|
+
}
|
|
415
|
+
async sendBatch(messages) {
|
|
416
|
+
const chunks = this.chunkArray(messages, 10);
|
|
417
|
+
for (const chunk of chunks) {
|
|
418
|
+
const payload = {
|
|
419
|
+
username: this.config.username,
|
|
420
|
+
avatar_url: this.config.avatarUrl,
|
|
421
|
+
embeds: chunk.map((msg) => this.createEmbed(msg))
|
|
422
|
+
};
|
|
423
|
+
await this.sendWebhook(payload);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
createEmbed(msg) {
|
|
427
|
+
const color = this.config.embedColors?.[msg.level] ?? DEFAULT_EMBED_COLORS[msg.level];
|
|
428
|
+
const embed = {
|
|
429
|
+
title: `[${msg.level.toUpperCase()}] ${msg.context || "APP"}`,
|
|
430
|
+
description: msg.message.slice(0, 4096),
|
|
431
|
+
// Discord limit
|
|
432
|
+
color
|
|
433
|
+
};
|
|
434
|
+
if (this.config.includeTimestamp !== false) {
|
|
435
|
+
embed.timestamp = msg.timestamp.toISOString();
|
|
436
|
+
}
|
|
437
|
+
if (this.config.includeMeta !== false && msg.meta) {
|
|
438
|
+
embed.fields = this.metaToFields(msg.meta);
|
|
439
|
+
}
|
|
440
|
+
return embed;
|
|
441
|
+
}
|
|
442
|
+
metaToFields(meta) {
|
|
443
|
+
const maxFields = this.config.maxEmbedFields ?? 25;
|
|
444
|
+
const fields = [];
|
|
445
|
+
for (const [key, value] of Object.entries(meta)) {
|
|
446
|
+
if (fields.length >= maxFields) break;
|
|
447
|
+
let strValue;
|
|
448
|
+
if (typeof value === "object") {
|
|
449
|
+
strValue = "```json\n" + JSON.stringify(value, null, 2).slice(0, 1e3) + "\n```";
|
|
450
|
+
} else {
|
|
451
|
+
strValue = String(value).slice(0, 1024);
|
|
452
|
+
}
|
|
453
|
+
fields.push({
|
|
454
|
+
name: key.slice(0, 256),
|
|
455
|
+
value: strValue,
|
|
456
|
+
inline: typeof value !== "object" && String(value).length < 50
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
return fields;
|
|
460
|
+
}
|
|
461
|
+
async sendWebhook(payload) {
|
|
462
|
+
const response = await fetch(this.config.webhookUrl, {
|
|
463
|
+
method: "POST",
|
|
464
|
+
headers: { "Content-Type": "application/json" },
|
|
465
|
+
body: JSON.stringify(payload)
|
|
466
|
+
});
|
|
467
|
+
if (!response.ok) {
|
|
468
|
+
const text = await response.text();
|
|
469
|
+
throw new Error(`Discord webhook failed: ${response.status} ${text}`);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
chunkArray(array, size) {
|
|
473
|
+
const chunks = [];
|
|
474
|
+
for (let i = 0; i < array.length; i += size) {
|
|
475
|
+
chunks.push(array.slice(i, i + size));
|
|
476
|
+
}
|
|
477
|
+
return chunks;
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
// src/transports/telegram.ts
|
|
482
|
+
var LEVEL_EMOJI = {
|
|
483
|
+
off: "",
|
|
484
|
+
error: "\u{1F534}",
|
|
485
|
+
warn: "\u{1F7E1}",
|
|
486
|
+
info: "\u{1F7E2}",
|
|
487
|
+
http: "\u{1F535}",
|
|
488
|
+
verbose: "\u{1F7E3}",
|
|
489
|
+
debug: "\u26AA",
|
|
490
|
+
silly: "\u26AB"
|
|
491
|
+
};
|
|
492
|
+
var TelegramTransport = class extends BaseHttpTransport {
|
|
493
|
+
config;
|
|
494
|
+
apiUrl;
|
|
495
|
+
constructor(config) {
|
|
496
|
+
super({
|
|
497
|
+
batchSize: config.batchSize ?? 20,
|
|
498
|
+
flushInterval: config.flushInterval ?? 1e3,
|
|
499
|
+
maxRetries: config.maxRetries,
|
|
500
|
+
retryDelay: config.retryDelay
|
|
501
|
+
});
|
|
502
|
+
this.config = config;
|
|
503
|
+
this.apiUrl = `https://api.telegram.org/bot${config.botToken}`;
|
|
504
|
+
}
|
|
505
|
+
async sendBatch(messages) {
|
|
506
|
+
const text = this.formatBatchMessage(messages);
|
|
507
|
+
await this.sendMessage(text, messages);
|
|
508
|
+
}
|
|
509
|
+
formatBatchMessage(messages) {
|
|
510
|
+
const parseMode = this.config.parseMode ?? "Markdown";
|
|
511
|
+
return messages.map((msg) => {
|
|
512
|
+
if (parseMode === "HTML") {
|
|
513
|
+
return this.formatHtml(msg);
|
|
514
|
+
}
|
|
515
|
+
return this.formatMarkdown(msg, parseMode === "MarkdownV2");
|
|
516
|
+
}).join("\n\n---\n\n");
|
|
517
|
+
}
|
|
518
|
+
formatMarkdown(msg, v2) {
|
|
519
|
+
const emoji = LEVEL_EMOJI[msg.level];
|
|
520
|
+
const escape = v2 ? this.escapeMarkdownV2.bind(this) : (s) => s;
|
|
521
|
+
let text = `${emoji} *${msg.level.toUpperCase()}* \\[${escape(msg.context || "APP")}\\]
|
|
522
|
+
`;
|
|
523
|
+
text += escape(msg.message);
|
|
524
|
+
if (msg.meta && Object.keys(msg.meta).length > 0) {
|
|
525
|
+
const metaStr = JSON.stringify(msg.meta, null, 2);
|
|
526
|
+
text += "\n```json\n" + metaStr + "\n```";
|
|
527
|
+
}
|
|
528
|
+
return text;
|
|
529
|
+
}
|
|
530
|
+
formatHtml(msg) {
|
|
531
|
+
const emoji = LEVEL_EMOJI[msg.level];
|
|
532
|
+
let text = `${emoji} <b>${msg.level.toUpperCase()}</b> [${this.escapeHtml(msg.context || "APP")}]
|
|
533
|
+
`;
|
|
534
|
+
text += this.escapeHtml(msg.message);
|
|
535
|
+
if (msg.meta && Object.keys(msg.meta).length > 0) {
|
|
536
|
+
const metaStr = JSON.stringify(msg.meta, null, 2);
|
|
537
|
+
text += "\n<pre>" + this.escapeHtml(metaStr) + "</pre>";
|
|
538
|
+
}
|
|
539
|
+
return text;
|
|
540
|
+
}
|
|
541
|
+
shouldMute(messages) {
|
|
542
|
+
if (this.config.disableNotification !== void 0) {
|
|
543
|
+
return this.config.disableNotification;
|
|
544
|
+
}
|
|
545
|
+
return !messages.some((m) => m.level === "error");
|
|
546
|
+
}
|
|
547
|
+
async sendMessage(text, messages) {
|
|
548
|
+
const body = {
|
|
549
|
+
chat_id: this.config.chatId,
|
|
550
|
+
text,
|
|
551
|
+
parse_mode: this.config.parseMode ?? "Markdown",
|
|
552
|
+
disable_notification: this.shouldMute(messages)
|
|
553
|
+
};
|
|
554
|
+
if (this.config.threadId) {
|
|
555
|
+
body.message_thread_id = this.config.threadId;
|
|
556
|
+
}
|
|
557
|
+
if (this.config.replyToMessageId) {
|
|
558
|
+
body.reply_to_message_id = this.config.replyToMessageId;
|
|
559
|
+
}
|
|
560
|
+
const response = await fetch(`${this.apiUrl}/sendMessage`, {
|
|
561
|
+
method: "POST",
|
|
562
|
+
headers: { "Content-Type": "application/json" },
|
|
563
|
+
body: JSON.stringify(body)
|
|
564
|
+
});
|
|
565
|
+
if (!response.ok) {
|
|
566
|
+
const result = await response.json();
|
|
567
|
+
throw new Error(`Telegram API failed: ${response.status} ${JSON.stringify(result)}`);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
escapeMarkdownV2(text) {
|
|
571
|
+
return text.replace(/[_*[\]()~`>#+\-=|{}.!]/g, "\\$&");
|
|
572
|
+
}
|
|
573
|
+
escapeHtml(text) {
|
|
574
|
+
const entities = {
|
|
575
|
+
"&": "&",
|
|
576
|
+
"<": "<",
|
|
577
|
+
">": ">",
|
|
578
|
+
'"': """,
|
|
579
|
+
"'": "'"
|
|
580
|
+
};
|
|
581
|
+
return text.replace(/[&<>"']/g, (c) => entities[c] || c);
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
var CloudWatchTransport = class extends BaseHttpTransport {
|
|
585
|
+
config;
|
|
586
|
+
client;
|
|
587
|
+
sequenceToken;
|
|
588
|
+
initialized = false;
|
|
589
|
+
initPromise = null;
|
|
590
|
+
constructor(config) {
|
|
591
|
+
super({
|
|
592
|
+
batchSize: config.batchSize ?? 100,
|
|
593
|
+
flushInterval: config.flushInterval ?? 1e3,
|
|
594
|
+
maxRetries: config.maxRetries,
|
|
595
|
+
retryDelay: config.retryDelay
|
|
596
|
+
});
|
|
597
|
+
this.config = config;
|
|
598
|
+
this.client = new CloudWatchLogsClient({
|
|
599
|
+
region: config.region,
|
|
600
|
+
credentials: {
|
|
601
|
+
accessKeyId: config.accessKeyId,
|
|
602
|
+
secretAccessKey: config.secretAccessKey
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
async sendBatch(messages) {
|
|
607
|
+
await this.ensureInitialized();
|
|
608
|
+
const logEvents = messages.map((msg) => ({
|
|
609
|
+
timestamp: msg.timestamp.getTime(),
|
|
610
|
+
message: JSON.stringify({
|
|
611
|
+
level: msg.level,
|
|
612
|
+
message: msg.message,
|
|
613
|
+
context: msg.context,
|
|
614
|
+
...msg.meta
|
|
615
|
+
})
|
|
616
|
+
}));
|
|
617
|
+
logEvents.sort((a, b) => (a.timestamp ?? 0) - (b.timestamp ?? 0));
|
|
618
|
+
const command = new PutLogEventsCommand({
|
|
619
|
+
logGroupName: this.config.logGroupName,
|
|
620
|
+
logStreamName: this.config.logStreamName,
|
|
621
|
+
logEvents,
|
|
622
|
+
sequenceToken: this.sequenceToken
|
|
623
|
+
});
|
|
624
|
+
try {
|
|
625
|
+
const response = await this.client.send(command);
|
|
626
|
+
this.sequenceToken = response.nextSequenceToken;
|
|
627
|
+
} catch (error) {
|
|
628
|
+
if (this.isInvalidSequenceTokenError(error)) {
|
|
629
|
+
await this.fetchSequenceToken();
|
|
630
|
+
const retryCommand = new PutLogEventsCommand({
|
|
631
|
+
logGroupName: this.config.logGroupName,
|
|
632
|
+
logStreamName: this.config.logStreamName,
|
|
633
|
+
logEvents,
|
|
634
|
+
sequenceToken: this.sequenceToken
|
|
635
|
+
});
|
|
636
|
+
const response = await this.client.send(retryCommand);
|
|
637
|
+
this.sequenceToken = response.nextSequenceToken;
|
|
638
|
+
} else {
|
|
639
|
+
throw error;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
async ensureInitialized() {
|
|
644
|
+
if (this.initialized) return;
|
|
645
|
+
if (!this.initPromise) {
|
|
646
|
+
this.initPromise = this.initialize();
|
|
647
|
+
}
|
|
648
|
+
await this.initPromise;
|
|
649
|
+
}
|
|
650
|
+
async initialize() {
|
|
651
|
+
if (this.config.createLogGroup) {
|
|
652
|
+
await this.createLogGroupIfNotExists();
|
|
653
|
+
}
|
|
654
|
+
if (this.config.createLogStream !== false) {
|
|
655
|
+
await this.createLogStreamIfNotExists();
|
|
656
|
+
}
|
|
657
|
+
await this.fetchSequenceToken();
|
|
658
|
+
this.initialized = true;
|
|
659
|
+
}
|
|
660
|
+
async createLogGroupIfNotExists() {
|
|
661
|
+
try {
|
|
662
|
+
await this.client.send(
|
|
663
|
+
new CreateLogGroupCommand({
|
|
664
|
+
logGroupName: this.config.logGroupName
|
|
665
|
+
})
|
|
666
|
+
);
|
|
667
|
+
} catch (error) {
|
|
668
|
+
if (!this.isResourceAlreadyExistsError(error)) {
|
|
669
|
+
throw error;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
async createLogStreamIfNotExists() {
|
|
674
|
+
try {
|
|
675
|
+
await this.client.send(
|
|
676
|
+
new CreateLogStreamCommand({
|
|
677
|
+
logGroupName: this.config.logGroupName,
|
|
678
|
+
logStreamName: this.config.logStreamName
|
|
679
|
+
})
|
|
680
|
+
);
|
|
681
|
+
} catch (error) {
|
|
682
|
+
if (!this.isResourceAlreadyExistsError(error)) {
|
|
683
|
+
throw error;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
async fetchSequenceToken() {
|
|
688
|
+
const response = await this.client.send(
|
|
689
|
+
new DescribeLogStreamsCommand({
|
|
690
|
+
logGroupName: this.config.logGroupName,
|
|
691
|
+
logStreamNamePrefix: this.config.logStreamName,
|
|
692
|
+
limit: 1
|
|
693
|
+
})
|
|
694
|
+
);
|
|
695
|
+
const stream = response.logStreams?.find((s) => s.logStreamName === this.config.logStreamName);
|
|
696
|
+
this.sequenceToken = stream?.uploadSequenceToken;
|
|
697
|
+
}
|
|
698
|
+
isResourceAlreadyExistsError(error) {
|
|
699
|
+
return typeof error === "object" && error !== null && "name" in error && error.name === "ResourceAlreadyExistsException";
|
|
700
|
+
}
|
|
701
|
+
isInvalidSequenceTokenError(error) {
|
|
702
|
+
return typeof error === "object" && error !== null && "name" in error && error.name === "InvalidSequenceTokenException";
|
|
703
|
+
}
|
|
704
|
+
};
|
|
705
|
+
|
|
236
706
|
// src/transports.ts
|
|
237
707
|
function createTransports(config, store) {
|
|
238
708
|
const result = [
|
|
239
709
|
new transports.Console({
|
|
240
|
-
format:
|
|
710
|
+
format: format.combine(
|
|
711
|
+
createFilterFormat(config.console.level, config.console.rules, store),
|
|
712
|
+
createFormat(config.console.format, store)
|
|
713
|
+
)
|
|
241
714
|
})
|
|
242
715
|
];
|
|
243
716
|
if (config.file) {
|
|
244
717
|
result.push(
|
|
245
718
|
new DailyRotateFile({
|
|
246
|
-
format:
|
|
719
|
+
format: format.combine(
|
|
720
|
+
createFilterFormat(config.file.level, config.file.rules, store),
|
|
721
|
+
createFormat(config.file.format, store)
|
|
722
|
+
),
|
|
247
723
|
dirname: config.file.dirname,
|
|
248
724
|
filename: config.file.filename,
|
|
249
725
|
datePattern: config.file.datePattern ?? "YYYY-MM-DD",
|
|
@@ -253,6 +729,30 @@ function createTransports(config, store) {
|
|
|
253
729
|
})
|
|
254
730
|
);
|
|
255
731
|
}
|
|
732
|
+
if (config.discord) {
|
|
733
|
+
const discord = new DiscordTransport(config.discord);
|
|
734
|
+
discord.format = format.combine(
|
|
735
|
+
createFilterFormat(config.discord.level, config.discord.rules, store),
|
|
736
|
+
format.timestamp()
|
|
737
|
+
);
|
|
738
|
+
result.push(discord);
|
|
739
|
+
}
|
|
740
|
+
if (config.telegram) {
|
|
741
|
+
const telegram = new TelegramTransport(config.telegram);
|
|
742
|
+
telegram.format = format.combine(
|
|
743
|
+
createFilterFormat(config.telegram.level, config.telegram.rules, store),
|
|
744
|
+
format.timestamp()
|
|
745
|
+
);
|
|
746
|
+
result.push(telegram);
|
|
747
|
+
}
|
|
748
|
+
if (config.cloudwatch) {
|
|
749
|
+
const cloudwatch = new CloudWatchTransport(config.cloudwatch);
|
|
750
|
+
cloudwatch.format = format.combine(
|
|
751
|
+
createFilterFormat(config.cloudwatch.level, config.cloudwatch.rules, store),
|
|
752
|
+
format.timestamp()
|
|
753
|
+
);
|
|
754
|
+
result.push(cloudwatch);
|
|
755
|
+
}
|
|
256
756
|
return result;
|
|
257
757
|
}
|
|
258
758
|
function createExceptionHandlers(config, store) {
|
|
@@ -277,25 +777,6 @@ function createExceptionHandlers(config, store) {
|
|
|
277
777
|
return result;
|
|
278
778
|
}
|
|
279
779
|
|
|
280
|
-
// src/types.ts
|
|
281
|
-
var LOG_LEVELS = {
|
|
282
|
-
error: 0,
|
|
283
|
-
warn: 1,
|
|
284
|
-
info: 2,
|
|
285
|
-
http: 3,
|
|
286
|
-
verbose: 4,
|
|
287
|
-
debug: 5,
|
|
288
|
-
silly: 6
|
|
289
|
-
};
|
|
290
|
-
function isValidLogLevel(level) {
|
|
291
|
-
return level in LOG_LEVELS;
|
|
292
|
-
}
|
|
293
|
-
function assertLogLevel(level) {
|
|
294
|
-
if (!isValidLogLevel(level)) {
|
|
295
|
-
throw new Error(`Invalid log level: "${level}". Valid levels: ${Object.keys(LOG_LEVELS).join(", ")}`);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
780
|
// src/state.ts
|
|
300
781
|
function parseLevelConfig(level) {
|
|
301
782
|
if (typeof level === "string") {
|
|
@@ -538,6 +1019,6 @@ function getOrGenerateRequestId(headers, options = {}) {
|
|
|
538
1019
|
return extractRequestId(headers) ?? generateRequestId(options);
|
|
539
1020
|
}
|
|
540
1021
|
|
|
541
|
-
export { LOG_LEVELS, Logger, LoggerStore, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatLogfmt, formatLogfmtValue, generateRequestId, getOrGenerateRequestId, isValidLogLevel, maskSecrets, measureAsync, measureSync };
|
|
1022
|
+
export { BaseHttpTransport, CloudWatchTransport, DiscordTransport, LOG_LEVELS, Logger, LoggerStore, MessageBuffer, TelegramTransport, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatLogfmt, formatLogfmtValue, generateRequestId, getOrGenerateRequestId, isValidLogLevel, maskSecrets, matchesContext, measureAsync, measureSync };
|
|
542
1023
|
//# sourceMappingURL=index.mjs.map
|
|
543
1024
|
//# sourceMappingURL=index.mjs.map
|