UNPKG

@iobroker/js-controller-common-db

Version:

The Library contains the common utils for the ioBroker controller which can be used by db classes too, as they do not rely on the db (circular dependencies).

384 lines (383 loc) 16.7 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var logger_exports = {}; __export(logger_exports, { logger: () => logger }); module.exports = __toCommonJS(logger_exports); var __import_meta_url = typeof document === "undefined" ? new (require("url".replace("", ""))).URL("file:" + __filename).href : document.currentScript && document.currentScript.src || new URL("main.js", document.baseURI).href; var import_winston = __toESM(require("winston"), 1); var import_winston_daily_rotate_file = __toESM(require("winston-daily-rotate-file"), 1); var import_node_fs = __toESM(require("node:fs"), 1); var import_node_path = __toESM(require("node:path"), 1); var import_node_os = __toESM(require("node:os"), 1); var tools = __toESM(require("../../lib/common/tools.js"), 1); var import_winston_transport = __toESM(require("winston-transport"), 1); var import_triple_beam = require("triple-beam"); var import_deep_clone = __toESM(require("deep-clone"), 1); var url = __toESM(require("node:url"), 1); var import_node_module = require("node:module"); const thisDir = url.fileURLToPath(new URL(".", __import_meta_url || `file://${__filename}`)); const require2 = (0, import_node_module.createRequire)(__import_meta_url || `file://${__filename}`); const hostname = tools.getHostName(); let SysLog; try { SysLog = require2("winston-syslog").Syslog; } catch { } let Seq; try { Seq = require2("@datalust/winston-seq").SeqTransport; } catch { } const IoSysLog = SysLog && class extends SysLog { constructor(options) { super(options); } log(info, callback) { const ioInfo = info; if (ioInfo[import_triple_beam.LEVEL] === "warn") { ioInfo[import_triple_beam.LEVEL] = "warning"; } if (ioInfo[import_triple_beam.LEVEL] === "info") { ioInfo[import_triple_beam.LEVEL] = "notice"; } if (ioInfo[import_triple_beam.LEVEL] === "debug") { ioInfo[import_triple_beam.LEVEL] = "info"; } if (ioInfo[import_triple_beam.LEVEL] === "silly") { ioInfo[import_triple_beam.LEVEL] = "debug"; } super.log?.(ioInfo, callback); } }; const IoSeq = Seq && class extends Seq { log(info, callback) { const ioInfo = (0, import_deep_clone.default)(info); ioInfo.props = ioInfo.props || {}; const level = (ioInfo.level || "").toLowerCase(); if (level.includes("error")) { ioInfo.level = "Error"; } else if (level.includes("warn")) { ioInfo.level = "Warning"; } else if (level.includes("info")) { ioInfo.level = "Information"; } else if (level.includes("debug")) { ioInfo.level = "Debug"; } else if (level.includes("silly")) { ioInfo.level = "Verbose"; } else { ioInfo.level = "Information"; } ioInfo.props.Hostname = tools.getHostName(); if (ioInfo.message) { const msgParts = ioInfo.message.match(/^([^.]+\.[0-9]+) \(([^)]+)\) (.*)$/s); if (msgParts) { ioInfo.props.Source = msgParts[1]; ioInfo.props.Pid = msgParts[2]; } else { ioInfo.props.Source = "js-controller"; } } super.log(ioInfo, callback); } }; class NotifierTransport extends import_winston_transport.default { name; constructor(opts) { super(opts); this.name = "NT"; } log(info, callback) { const msg = { severity: info[import_triple_beam.LEVEL], ts: new Date(info.timestamp).getTime(), message: info.message }; setImmediate(() => this.emit("logged", msg)); callback(); } } function logger(level, files, noStdout, prefix) { const options = { transports: [] }; if (typeof files === "string") { files = [files]; } const formatter = (info) => `${timestamp(info.timestamp)} - ${info.level}: ${info.message}`; files = files || []; const isNpm = !thisDir.replace(/\\/g, "/").toLowerCase().includes(`${tools.appName.toLowerCase()}.js-controller/packages/`); if (tools.isObject(level)) { const userOptions = (0, import_deep_clone.default)(level); level = userOptions.level; prefix = userOptions.prefix || ""; noStdout = userOptions.noStdout; const winstonFormats = []; winstonFormats.push(import_winston.default.format.timestamp({ format: timestamp })); if (userOptions.json === void 0 || userOptions.json) { winstonFormats.push(import_winston.default.format.json()); } if (prefix) { winstonFormats.push(import_winston.default.format.label({ label: prefix })); } if (userOptions.colorize === void 0 || userOptions.colorize) { winstonFormats.push(import_winston.default.format.colorize()); } options.format = import_winston.default.format.combine.apply(null, winstonFormats); if (userOptions.prefix !== void 0) { delete userOptions.prefix; } if (userOptions.transport) { let fName = 0; const isWindows = import_node_os.default.platform().startsWith("win"); for (const transport of Object.values(userOptions.transport)) { transport._defaultConfigLoglevel = transport.level; transport.level = transport.level || level; if (transport.type === "file" && transport.enabled !== false) { transport.filename = transport.filename || `log/${tools.appName}`; if (!transport.fileext && transport.filename.indexOf(".log") === -1) { transport.fileext = ".log"; } if (!fName) { transport.systemLog = true; } transport.handleExceptions = false; transport.name = fName ? `dailyRotateFile${fName}` : tools.appName; fName++; transport.filename = transport.filename.replace(/\\/g, "/"); if (transport.filename.match(/^\w:\/|^\//)) { transport.filename = import_node_path.default.normalize(transport.filename); } else { transport.filename = import_node_path.default.normalize(`${tools.getControllerDir()}${isNpm ? "/../../" : "/"}${transport.filename}`); } transport.auditFile = `${transport.filename}-audit.json`; transport.createSymlink = transport.createSymlink !== void 0 ? transport.createSymlink : !isWindows; transport.symlinkName = transport.symlinkName !== void 0 ? transport.symlinkName : import_node_path.default.basename(`${transport.filename}.current.log`); transport.filename += `.%DATE%${transport.fileext || ""}`; transport.silent = transport.silent !== void 0 ? transport.silent : false; transport.localTime = transport.localTime !== void 0 ? transport.localTime : userOptions.localTime === void 0 ? true : userOptions.localTime; transport.datePattern = "YYYY-MM-DD"; transport.format = import_winston.default.format.combine(import_winston.default.format.printf(formatter)); transport.zippedArchive = isWindows ? false : transport.zippedArchive !== void 0 ? transport.zippedArchive : true; if (transport.maxFiles === null && userOptions.maxDays) { transport.maxFiles = `${userOptions.maxDays}d`; } try { const _log = new import_winston_daily_rotate_file.default(transport); _log.on("error", (err) => { console.error(`Error on log file rotation: ${err.message}`); }); options.transports.push(_log); } catch (e) { if (e.code === "EACCES") { e.code = "EACCES_LOG"; } throw e; } } else if (transport.type === "syslog" && transport.enabled !== false) { if (!IoSysLog) { console.error("Syslog configured, but not installed! Ignore"); continue; } transport.localhost = transport.localhost || hostname; transport.format = import_winston.default.format.combine(import_winston.default.format.printf(formatter)); if (transport.sysLogType) { transport.type = transport.sysLogType; delete transport.sysLogType; } else { delete transport.type; } try { options.transports.push(new IoSysLog(transport)); } catch (e) { console.error(`Cannot activate Syslog: ${e.message}`); } } else if (transport.type === "http" && transport.enabled !== false) { transport.host = transport.host || "localhost"; try { options.transports.push(new import_winston.default.transports.Http(transport)); } catch (e) { console.error(`Cannot activate HTTP: ${e.message}`); } } else if (transport.type === "stream" && transport.enabled !== false) { transport.host = transport.host || "localhost"; try { if (typeof transport.stream === "string") { transport.stream = import_node_fs.default.createWriteStream(transport.stream); transport.stream.on("error", (err) => { console.error(`Error in Stream: ${err.message}`); }); } options.transports.push(new import_winston.default.transports.Stream(transport)); } catch (e) { console.error(`Cannot activate Stream: ${e.message}`); } } else if (transport.type === "seq" && transport.enabled !== false) { if (!IoSeq) { console.error("Seq configured, but not installed! Ignore"); continue; } if (transport.serverUrl) { try { transport.onError = (e) => { console.log(`SEQ error: ${e.message}`); }; const seqLogger = new IoSeq(transport); options.transports.push(seqLogger); } catch (e) { console.error(`Cannot activate SEQ: ${e.message}`); } } else { console.error("Cannot activate SEQ: No serverUrl specified"); } } } } } else { for (let i = 0; i < files.length; i++) { const opt = { name: i ? `dailyRotateFile${i}` : tools.appName, filename: import_node_path.default.normalize(isNpm ? `${thisDir}/../../../log/${files[i]}` : `${thisDir}/../log/${files[i]}`), extension: ".log", datePattern: "YYYY-MM-DD", //json: false, // If true, messages will be logged as JSON (default true). TODO format.json() level, silent: false, localTime: true, //colorize: (userOptions.colorize === undefined) ? true : userOptions.colorize, // TODO format.colorize() //timestamp: timestamp, // TODO: format.timestamp() //label: prefix || '', // TODO format.label() handleExceptions: false //maxSize: defaultMaxSize }; options.transports.push(new import_winston_daily_rotate_file.default(opt)); } } if (!noStdout) { options.transports.push(new import_winston.default.transports.Console({ level, silent: false, format: import_winston.default.format.combine(import_winston.default.format.printf(formatter)) //colorize: (userOptions.colorize === undefined) ? true : userOptions.colorize, // TODO format.colorize() //timestamp: timestamp, // TODO: format.timestamp() //label: prefix || '' // TODO format.label() })); } options.transports.push(new NotifierTransport({ level, silent: false })); const log = import_winston.default.createLogger(options); log.getFileName = function() { let transport = this.transports.find((t) => t.transport && t.transport.dirname || t.dirname); if (transport) { transport = transport.transport ? transport.transport : transport; return `${transport.dirname}/${transport.filename.replace("%DATE%", getDate())}`; } return ""; }; log.on("error", (error) => { console.log(`Logger error: ${error.message}`); }); log.activateDateChecker = function(isEnabled, daysCount) { if (!isEnabled && this._fileChecker) { clearInterval(this._fileChecker); } else if (isEnabled && !this._fileChecker) { if (!daysCount) { daysCount = 3; } this._fileChecker = setInterval(() => { this.transports.forEach((transport) => { if ( /** @ts-expect-error we use undocumented stuff here TODO */ transport.name !== "dailyRotateFile" || /** @ts-expect-error we use undocumented stuff here TODO */ !transport.options || /** @ts-expect-error we use undocumented stuff here TODO */ transport.options.name !== tools.appName ) { return; } if (transport && import_node_fs.default.existsSync(transport.dirname)) { let files2; try { files2 = import_node_fs.default.readdirSync(transport.dirname); } catch (e) { console.error(`host.${hostname} Cannot read log directory: ${e.message}`); return; } const forXdays = /* @__PURE__ */ new Date(); forXdays.setDate(forXdays.getDate() - daysCount - 1); for (let i = 0; i < files2.length; i++) { const match = files2[i].match(/.+\.(\d+-\d+-\d+)/); if (match) { const date = new Date(match[1]); if (date < forXdays) { try { this.log({ level: "info", message: `host.${hostname} Delete log file ${files2[i]}` }); console.log(`host.${hostname} Delete log file ${files2[i]}`); import_node_fs.default.unlinkSync(`${transport.dirname}/${files2[i]}`); } catch (e) { this.log({ level: import_node_os.default.platform().startsWith("win") ? "info" : "error", message: `host.${hostname} Cannot delete file "${import_node_path.default.normalize( /** @ts-expect-error we use undocumented stuff here TODO */ `${transport.dirname}/${files2[i]}` )}": ${e}` }); console.log(`host.${hostname} Cannot delete file "${import_node_path.default.normalize( /** @ts-expect-error we use undocumented stuff here TODO */ `${transport.dirname}/${files2[i]}` )}": ${e.message}`); } } } } } }); }, 36e5); } }; return log; } function getDate() { const ts = /* @__PURE__ */ new Date(); return `${ts.getFullYear()}-${(ts.getMonth() + 1).toString().padStart(2, "0")}-${ts.getDate().toString().padStart(2, "0")}`; } function timestamp(date) { const ts = date ? new Date(date) : /* @__PURE__ */ new Date(); return `${ts.getFullYear()}-${(ts.getMonth() + 1).toString().padStart(2, "0")}-${ts.getDate().toString().padStart(2, "0")} ${ts.getHours().toString().padStart(2, "0")}:${ts.getMinutes().toString().padStart(2, "0")}:${ts.getSeconds().toString().padStart(2, "0")}.${ts.getMilliseconds().toString().padStart(3, "0")} `; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { logger }); //# sourceMappingURL=logger.js.map