log-vault
Version:
A generator of Winston logger instance with pre-defined configurable transports and formats and extra functionality.
114 lines (111 loc) • 4.04 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TelegramNotificationChannel = void 0;
const NotificationChannel_1 = require("./NotificationChannel");
const axios_1 = __importDefault(require("axios"));
const mustache_1 = require("mustache");
const basicTemplate = `{{emojiLevel}} *{{level}} log message* {{#timestamp}}⏱ _{{timestamp}}_{{/timestamp}}
{{#meta}}
\`[{{label}}]: {{value}}\`
{{/meta}}
{{#shrinked}}
>The message is shrinked as it's over {{shrinked}} characters length\\.
>Please, consider a more accurate handler for this log entry in your code\\.
{{/shrinked}}
\`\`\`json
{{{message}}}
\`\`\``;
const emojiLevels = [
{ level: "error", emoji: "🔴" },
{ level: "warn", emoji: "🟡" },
{ level: "info", emoji: "🟢" },
{ level: "http", emoji: "🔵" },
{ level: "verbose", emoji: "🟣" },
{ level: "debug", emoji: "🪲" },
{ level: "silly", emoji: "🐤" }
];
function getEmojiLevel(level) {
const item = emojiLevels.find((item) => item.level === level);
return (item === null || item === void 0 ? void 0 : item.emoji) || "🔵";
}
function renderLogMessage(template, log) {
const { level, message, timestamp, meta = {} } = log;
const limit = 2048;
const { shrinked, shrinkedMessage } = shrinkStringSize(JSON.stringify(message, null, 2), limit);
const unescaped = {
level: unescape(level),
message: unescape(shrinkedMessage),
timestamp: unescape(timestamp),
meta: Object.keys(meta).map((label) => {
var _a;
return ({
label,
value: unescape((_a = meta[label]) === null || _a === void 0 ? void 0 : _a.toString())
});
})
};
const rendered = (0, mustache_1.render)(template, {
...unescaped,
emojiLevel: getEmojiLevel(log.level),
shrinked: shrinked ? limit : undefined
});
return rendered;
function unescape(str) {
return (str === null || str === void 0 ? void 0 : str.replace(/([|{[\]*_~}+)(#>!=\-.])/gm, "\\$1")) || "";
}
}
function shrinkStringSize(str, limit) {
const safe = str !== null && str !== void 0 ? str : "";
const shrinked = safe.length > limit;
return {
shrinkedMessage: safe.substring(0, limit),
shrinked
};
}
class TelegramNotificationChannel extends NotificationChannel_1.NotificationChannel {
constructor(opts) {
super(opts);
const { host = "https://api.telegram.org/bot", token, workerOptions = {}, queueOptions = {}, jobOptions = {}, chatId, template = basicTemplate } = opts;
const baseURL = new URL(`/bot${token}`, host).toString();
this.token = token;
this.chatId = chatId;
this.process({
queueName: this.queueName,
processor: async (job) => {
const log = job.data;
await (0, axios_1.default)({
method: "post",
baseURL,
url: "sendMessage",
data: {
chat_id: chatId,
text: renderLogMessage(template, log),
parse_mode: "MarkdownV2"
}
});
return job.data;
},
workerOptions: {
limiter: {
max: 1,
duration: 5000
},
...workerOptions
},
queueOptions,
jobOptions: {
attempts: 5,
backoff: { type: "exponential", delay: 5000 },
...jobOptions
}
});
}
get queueName() {
const sanitizedToken = this.token.replace(":", ".");
return `${sanitizedToken}.${this.chatId}`;
}
}
exports.TelegramNotificationChannel = TelegramNotificationChannel;