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