From 8e35b9220eb81ea24b61b694f8b16a5f36225ad6 Mon Sep 17 00:00:00 2001 From: git-ev Date: Fri, 7 May 2021 10:26:29 +0200 Subject: [PATCH] use json-stringify-safe to support circular references --- log-elk-logger.js | 92 ++++++++++++----------------------------------- log-elk.js | 15 +++----- package.json | 5 +-- 3 files changed, 30 insertions(+), 82 deletions(-) diff --git a/log-elk-logger.js b/log-elk-logger.js index d5a42af..8ee4923 100644 --- a/log-elk-logger.js +++ b/log-elk-logger.js @@ -1,7 +1,7 @@ module.exports = function (RED) { "use strict"; var debuglength = RED.settings.debugMaxLength || 1000; - var util = require("util"); + const safeJSONStringify = require("json-stringify-safe"); function LogElkLoggerNode(config) { var winston = require('winston'); @@ -114,66 +114,11 @@ module.exports = function (RED) { return transformed; }; + function sendDebug(msg) { - if (msg.msg instanceof Error) { - msg.format = "error"; - msg.msg = msg.msg.toString(); - } else if (msg.msg instanceof Buffer) { - msg.format = "buffer [" + msg.msg.length + "]"; - msg.msg = msg.msg.toString('hex'); - } else if (msg.msg && typeof msg.msg === 'object') { - var seen = []; - try { - msg.format = msg.msg.constructor.name || "Object"; - } catch (err) { - msg.format = "Object"; - } - var isArray = util.isArray(msg.msg); - if (isArray) { - msg.format = "array [" + msg.msg.length + "]"; - } - if (isArray || (msg.format === "Object")) { - msg.msg = JSON.stringify(msg.msg, function (key, value) { - if (typeof value === 'object' && value !== null) { - if (seen.indexOf(value) !== -1) { - return "[circular]"; - } - seen.push(value); - } - return value; - }, " "); - } else { - try { - msg.msg = msg.msg.toString(); - } - catch (e) { - msg.msg = "[Type not printable]"; - } - } - seen = null; - } else if (typeof msg.msg === "boolean") { - msg.format = "boolean"; - msg.msg = msg.msg.toString(); - } else if (typeof msg.msg === "number") { - msg.format = "number"; - msg.msg = msg.msg.toString(); - } else if (msg.msg === 0) { - msg.format = "number"; - msg.msg = "0"; - } else if (msg.msg === null || typeof msg.msg === "undefined") { - msg.format = (msg.msg === null) ? "null" : "undefined"; - msg.msg = "(undefined)"; - } else { - msg.format = "string [" + msg.msg.length + "]"; - msg.msg = msg.msg; - } - - if (msg.msg.length > debuglength) { - msg.msg = msg.msg.substr(0, debuglength) + " ...."; - } - RED.comms.publish("debug", msg); + msg = RED.util.encodeObject(msg, {maxLength:debuglength}); + RED.comms.publish("debug",msg); } - RED.nodes.registerType("log-elk-logger", LogElkLoggerNode, { @@ -183,29 +128,36 @@ module.exports = function (RED) { } }); - // get a value for a message path seperated with '.' - const get = (obj, path) => - path - .replace(/\[([^\[\]]*)\]/g, '.$1.') - .split('.') - .filter(t => t !== '') - .reduce((prev, cur) => prev && prev[cur], obj); - LogElkLoggerNode.prototype.addToLog = function addTolog(loglevel, msg, complete) { if (complete === true || complete === "complete" || complete === "true") { + // Log complete message if (this.debugLog === true || this.debugLog === "true") { sendDebug({id: this.id, name: this.name, topic: msg.topic, msg: msg, _path: msg._path}); } if (this.logger) { - this.logger.log(loglevel, JSON.stringify(msg), msg.meta); + this.logger.log(loglevel, safeJSONStringify(msg), msg.meta); } } else if (complete !== undefined && complete !== null && complete !== "" && complete !== false && complete !== "false") { + // Log part of message + var output; + try { output = RED.util.getMessageProperty(msg, complete); } + catch(err) { + node.error(err); + return; + } + if (this.debugLog === true || this.debugLog === "true") { - sendDebug({id: this.id, name: this.name, topic: msg.topic, msg: get(msg, complete), _path: msg._path}); + sendDebug({id: this.id, name: this.name, topic: msg.topic, msg: output, _path: msg._path}); } if (this.logger) { - this.logger.log(loglevel, JSON.stringify(get(msg, complete)), msg.meta); + if (typeof output === "string") { + this.logger.log(loglevel, output, msg.meta); + } else if (typeof output === "object") { + this.logger.log(loglevel, safeJSONStringify(output), msg.meta); + } else { + this.logger.log(loglevel, safeJSONStringify(output), msg.meta); + } } } } diff --git a/log-elk.js b/log-elk.js index 75841e5..713afe6 100644 --- a/log-elk.js +++ b/log-elk.js @@ -10,15 +10,6 @@ module.exports = function (RED) { var complete = config.complete; var loglevel = config.loglevel || "debug"; - // get a value for a message path seperated with '.' - const get = (obj, path) => - path - .replace(/\[([^\[\]]*)\]/g, '.$1.') - .split('.') - .filter(t => t !== '') - .reduce((prev, cur) => prev && prev[cur], obj); - - this.on('input', function(msg, send, done) { if (node.logger) { @@ -28,7 +19,11 @@ module.exports = function (RED) { level = loglevel; } else { // get loglevel from message - level = get(msg, loglevel); + try { level = RED.util.getMessageProperty(msg, loglevel); } + catch(err) { + level = "debug"; + } + if (!(level === "error" || level === "warn" || level === "info" || level === "debug")) { // invalid log level, default to debug level = "debug"; diff --git a/package.json b/package.json index c8356bd..0a69fc8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-red-contrib-log-elk", - "version": "1.2.0", + "version": "1.2.1", "description": "A Node-RED logging node with multiple outputs using the winston and winston-elasticsearch logging libraries", "main": "log-elk.js", "scripts": { @@ -27,6 +27,7 @@ "license": "MIT", "dependencies": { "winston": "^3.3.3", - "winston-elasticsearch": "^0.15.2" + "winston-elasticsearch": "^0.15.2", + "json-stringify-safe": "^5.0.1" } }