How to store the logs in text file in node red

I need to store the node.warn and node.error in a txt file.
what setting i need to do in setting.js file in .node-red directory ??
Any help is appreciated .
thank you.

Assuming you are on a Linux system they already go to /var/log/syslog and can also be accessed using journalctl.

Hi,

I am using windows system and I have a function node in node-red where i am printing logs.
I need to store those log messages to a txt file.
So what changes I shall do to store the logs..

The "best" approach would be to create a custom logger in settings.js. With that, you could output all warn and error msgs direct to a log file.

However, that is slightly more complex to set up than doing a flow since you will need to write a small amount of node.js code. If you are reasonably comfortable with doing that, it will be the most effective approach. It has the advantage that it does not impact any of your flows so is transparent to flow editors.

The less efficient way would be to add a catch node. But this materially impacts the way that the flows work so might not be optimal.

Either way, you may also need to think about log rotation to prevent log files from getting too large.

I recently saw a technique that you could use - send your log messages to a second function node output using node.send instead of node.warn.

eg

function warn(str) {
    node.send(([null, {payload: {warn:str}}]))
} 
function error(str) {
    node.send(([null, { payload: { error: str } }]))
}
warn ("The sky is falling")  //goes to output 2
error ("Sky fell")          // goes to output 2

return msg;  // output 1

And wire the second output up to a Write file node.

ps Not sure all of those brackets are strictly necessary!

1 Like

Good point. I was thinking of a general approach whereas perhaps the need is for a specific function node? In that case, your approach is a nice one, especially as the default setting for the file-out node is
image

but is there any possibility that we can do some configuration changes in setting.js file and We can specify the file path to store it.

Or else If we follow the above approach we need to make changes in every function node.

I followed approach given below but it did not work out.
If you want to store node.warn messages directly to a text file in Node-RED, you can do so by using the built-in logging feature of Node-RED itself, which can write log messages to a log file. Here's how you can set it up:

  1. Open your Node-RED settings file. You can usually find this file at /path/to/.node-red/settings.js.

  2. In the settings file, locate the logging section. If it's not present, you can add it. It might look something like this:

logging: {
    console: {
        level: "info",
        metrics: false,
        audit: false
    }
},
  1. To capture and store node.warn messages, you can add a file logger under the logging section, specifying the log file path and log level. For example:
logging: {
    console: {
        level: "info",
        metrics: false,
        audit: false
    },
    file: {
        level: "warn",
        filename: "/path/to/your/logfile.log"
    }
},

Replace "/path/to/your/logfile.log" with the actual path and filename where you want to store the log messages.

  1. Save your settings file.

  2. Restart your Node-RED server to apply the changes.

With these settings, Node-RED will automatically capture node.warn messages and store them in the specified log file. You don't need to manually handle these messages in your Function nodes; Node-RED's built-in logger will take care of it for you.

Absolutely, I think I shared an example custom logger quite a while back. Doesn't do what you want but it may help you understand what is needed. ... Actually, here is an early example I did that I no longer use. I think if may be close to what you want though you might want to remove the colour stuff.

tilog: {
    level: 'trace',
    metrics: false,
    audit: false,
    handler: function(settings) {
        // Called when the logger is initialised
        const fs = require('fs')
        const util = require('util')
        const Chalk = require('chalk')
        const chalk = new Chalk.Instance({level: 3})
        // Use flags 'a' to append or 'w' to create new on restart
        const log_file = fs.createWriteStream(__dirname + '/uibuilder.log', {flags : 'w'})

        const tilogLevels = {
            10: 'FATAL', 20: 'ERROR', 30: 'WARN ', 40: 'INFO ', 50: 'DEBUG', 60: 'TRACE', 98: 'AUDIT', 99: 'MTRIC'
        }

        const tilog = function(d) { //
            log_file.write(util.format.apply(null, arguments) + '\n')
            //log_stdout.write(util.format(d) + '\n');
        }

        /** Return the logging function
         * msg schema: { id, level, type, msg, timestamp}
         * id = The node instance that produces the msg
         * level = 10: fatal, 20: error, 30: warn, 40: Info, 50: Debug, 60: Trace
         * timestamp = Javascript timestamp. Use `(new Date(msg.timestamp)).toIsoString()` or similar to convert
         * type = 'flow' - not clear when/why this is produced
         */
        return function(msg) {
            if ( msg.level < 51 || msg.msg.includes('[uibuilder') || msg.msg.startsWith('+-') || msg.msg.startsWith('| ') || msg.msg.startsWith('>>') ) {
                //console.log('TOLOG: ', msg)
                if (msg.msg.includes('[uibuilder:')) msg.msg = msg.msg.replace('[uibuilder:', '[')
                let msgColor, introColor
                switch (msg.level) {
                    case 10: { // fatal
                        msgColor = chalk.redBright
                        introColor = msgColor.bold.inverse
                        break
                    }

                    case 20: { // error
                        msgColor = chalk.red
                        introColor = msgColor.inverse
                        break
                    }

                    case 30: { // warn
                        msgColor = chalk.rgb(255, 185, 0)
                        introColor = msgColor.inverse
                        break
                    }

                    case 40: { // info
                        msgColor = chalk.yellow
                        introColor = msgColor.inverse
                        break
                    }

                    case 50: { // debug
                        msgColor = chalk.greenBright
                        introColor = msgColor.inverse
                        break
                    }

                    case 60: { // trace
                        msgColor = chalk.cyanBright
                        introColor = msgColor.inverse
                        break
                    }

                    default: {
                        msgColor = chalk.reset
                        introColor = msgColor.inverse
                        break
                    }
                }
                let intro = introColor(tilogLevels[msg.level]+'|')
                tilog( intro, msgColor(msg.msg) )
            }
            // else {
            //     tilog(
            //         `?? ${tilogLevels[msg.level]}:`, msg.msg
            //     )
            // }
        }
    }
},

As I say, I don't use this any more so can't say for sure that it doesn't have some errors.

You could also use a 3rd-party logging library like Winston if you want more control. I've a basic example for that as well if you need it.

You need to add another property to the logging section of settings.js - the above example is what you add - in that example, I've called it tilog but you can call it what you want of course.

Presumably Node-red on Windows stores these error and warning messages somewhere?

You could use operating system tools to extract then into a smaller file.

On Linux you could have a process tailing the log file and grepping for selected messages. Presumably you could do the same in Windows (I would probably use Linux commands embedded in Windows eg with cygwin, I don't know Dos syntax)

Depends how you start Node-RED. If started manually, it only displays on the console - same as Linux.

Even Linux won't necessarily save the logs to permanent files if you are using systemd.

as af now I started manually and i am using windows system.

and Do I need to give file path in setting.js file ,if yes how ?

currently my setting.js file look like below for logging
logging: {
/** Only console logging is currently supported /
console: {
/
* Level of logging to be recorded. Options are:
* fatal - only those errors which make the application unusable should be recorded
* error - record errors which are deemed fatal for a particular request + fatal errors
* warn - record problems which are non fatal + errors + fatal errors
* info - record information about the general running of the application + warn + error + fatal errors
* debug - record information which is more verbose than info + info + warn + error + fatal errors
* trace - record very detailed logging + debug + info + warn + error + fatal errors
* off - turn off all logging (doesn't affect metrics or audit)
/
level: "info",
/
* Whether or not to include metric events in the log output /
metrics: true,
/
* Whether or not to include audit events in the log output */
audit: true
},
file : {
level : "info",
filename: "D:\testing\logfile.log"
//filename : "C:/Users/565656/.node-red/datalog.log"
}
},

is this correct ?

Use forward slashes in file paths. In strings, backslash is interpreted as an escape character, so for example \t is the tab character. Windows works perfectly well with forward slashes.

I tried ,It did not work.

Well it would have worked even less with backslashes, as the path you were providing was invalid.

Does the node red user have permission to write to D:/testing?

Yes Node-RED have the permission to write as I already used write file node to store the some other information in a flow.

DO i need to give fileName instead of filename ?

Where did you see those instructions? Please post a link.

A far easier solution would be to run node-red as a service with nssm and redirect stout and stderr to a log file. You can even set rotation.

https://nssm.cc/usage

1 Like

I hadn't thought of that, that is a good idea.

In fact the same idea should work on Pi etc by specifying the redirection in the node red service script.