Custom logger in setting.js to log in file

Hello everyone,
I would like to save the messages from the console in a new log every day so that I can receive the error message if Node-RED crashes.
What do I need to change in the settings.js file to create a daily log file in the folder where the settings.js file is located? Saving the logs in a subfolder called “logs” would also be an option.
The log should save the following information, which can also be seen in the console:

20 Aug 09:50:36 - [info]

Welcome to Node-RED
===================

20 Aug 09:50:36 - [info] Node-RED version: v4.0.9
20 Aug 09:50:36 - [info] Node.js  version: v22.17.1
20 Aug 09:50:36 - [info] Windows_NT 10.0.26100 x64 LE
20 Aug 09:50:37 - [info] Loading palette nodes
20 Aug 09:50:37 - [info] Settings file  : C:\Users\RS7340\.node-red\settings.js
20 Aug 09:50:37 - [info] Context store  : 'default' [module=memory]
20 Aug 09:50:37 - [info] User directory : \Users\RS7340\.node-red
20 Aug 09:50:37 - [warn] Projects disabled : editorTheme.projects.enabled=false
20 Aug 09:50:37 - [info] Flows file     : \Users\RS7340\.node-red\flows.json
20 Aug 09:50:37 - [info] Creating new flow file

Thanks!

Hi, you need to look at the logging property in the settings. It is an object and you can add new sub-properties to create a new logging instance.

{
    level: 'trace',
    metrics: false,
    audit: false,
    handler: function(settings) {
        // ...
    }
}

I found the logging property in the settings, but I don't know what to write in the handler so that the logging is saved in a file.

I no longer use this but it is an example of the type you mention. (I have a separate log output to MQTT on my dev instance so that I can view detailed logs from uibuilder on a web page).

        /** Custom logging: https://nodered.org/docs/user-guide/runtime/logging */
        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 an alternative, you might want to look at using the winston logging tool.

A potential alternative approach:

Run as a service (search NSSM on this forum). NSSM can redirect logs to a text file.

Alternatively, if you can, run Node-RED in linux and use the system journal.

In your service invocation script, make sure you redirect the output to the log file with >> (append) and not > (replace).

A problem I encountered when running as a service with NSSM, is that it automatically restarts the Node-RED server process upon crash. Hence the process may be constantly crashing & restarting without me knowing about it.
Does anyone know how to control this?

Open the Windows Services tool, find the nssm Node-RED service and double-click. Then go to the Recovery tab:

You can control everything from there. You can even run another programme on error failure. You could use an AutoHotKey script to show a dialog box for example.

1 Like

Thanks Julian!