const _ = require("lodash") const dayjs = require("dayjs") const colors = require("colors/safe") const fs = require("node:fs/promises") ///////////////////////////////////////////////////////////////////////// const LEVELS = {debug: 10, info: 20, warn: 30, error: 40} const DEFAULT_LEVEL = "info" // level configured from settings (see settings.js); env LOG_LEVEL overrides it let settingsLevel = null module.exports = { debug: msg => log("DEBUG", msg), info: msg => log("INFO", msg), warn: msg => log("WARN", msg), error: msg => log("ERROR", msg), setLevel, level: currentLevel, } ///////////////////////////////////////////////////////////////////////// /** * Set the level from settings. The LOG_LEVEL env var still takes precedence. */ function setLevel (level) { settingsLevel = level ? level.toString().trim().toLowerCase() : null } /** * Resolve the active log level: LOG_LEVEL env var > settings level > "info". */ function currentLevel () { const level = process.env.LOG_LEVEL || settingsLevel || DEFAULT_LEVEL return level.toString().trim().toLowerCase() } function log (level, msg) { const threshold = currentLevel() if (threshold === "silent" || threshold === "off") return if (LEVELS[level.toLowerCase()] < (LEVELS[threshold] ?? LEVELS[DEFAULT_LEVEL])) return if (!_.isString(msg)) { if (msg.message) { msg = msg.message } else { try { msg = JSON.stringify(msg) } catch (ex) { msg = msg?.toString() } } } level = _.padEnd(level, 5) level = format(level.toLowerCase()) let message = `${level} ${dayjs().format("DD.MM.YYYY HH:mm:ss")} - ${msg}` console.log(message) return fs.appendFile("log.log", message + "\n") } function format (level) { switch (level.trim()) { case "info": return colors.green(level.toUpperCase()) case "warn": return colors.blue(level.toUpperCase()) case "error": return colors.red(level.toUpperCase()) case "debug": return colors.grey(level.toUpperCase()) } return level }