Message Tracing/Debug On Per Message Basis

I have a number of flows that generate a lot of traffic. Just enabling the debug nodes on a given path can output an overwhelming amount of data making it extremely difficult to follow a specific message through the system.

I have on occasion used switch nodes to limit traffic to debug nodes by only passing messages with a specific property, but I end up with a lot of extra nodes that I end up having to cleanup later.

I assume that all messages sent by nodes (i.e. node.send(...) or return msg;) get sent to a central dispatch event loop that could handle this more efficiently.

I would like to be able to attach a (reserved) property to a specific message, for example "msg._debug='payload'" then have the dispatch event handler send info to the debug panel for every node that processes that message sending it on with the _debug property. Seems as though my assumed dispatch event handler could perform this efficiently without having to change any nodes per se. This could be further enhanced by using the _debug value to determine what gets sent to the debug window, for example the whole msg, msg.payload, or some other message property.

Alternately, this could be achieved perhaps by enhancing the debug panel filtering, adding the ability to filter on msg properties, to only display messages with a specific property.

You can easily create a custom debug handler using link calls, perhaps like this

No, not really. Though NR talks about message handling, it isn't really a message router at all. The "messages" are in-memory variables passed by reference between node runtimes. Each node runtime has an "input" callback function that handles the passed variable.

I agree with jbudd here - the way to do this is to have a separate flow that does the filtering and route outputs to it using a link.

Just remember that every time you have more than a single wire coming out of a node, that means that Node-RED has to make a COPY of the msg variable - normally you don't notice but this is a relatively slow task and so sometimes, it can really catch you out with performance issues. This is one of the reasons that, from time-to-time, a request comes up for a passthrough option on the debug node.

You do have some other options though. Various people have created separate logging and/or debugging nodes so you should check those out.

In addition, you could output to the Node-RED log instead of the debug panel and then create a custom logger which you can do in settings.js. I've done this on my dev instance for when things get hairy with uibuilder and I need to turn up the logging levels but don't want to have to wade through all the detailed logs for all nodes. I output the uibuilder detail log entries to MQTT and have a uibuilder web page than displays them.

There isn't but there are hooks that are triggered when messages are passed around.

That is what I did in the message tracing part of the introspection package was to listen to those hooks:

const OnReceiveTracingHookName = "onReceive.introspectionMsgTracer"

...

function msgTracerOnReceiveHook(evnt) {
    try {
      let nde = RED.nodes.getNode(evnt.destination.id)

      nde.status({ fill: "green", shape: "ring", text: "msg received" })
      setTimeout(() => { nde.status({}) }, 1000)

      RED.comms.publish("msgtracer:node-received",
        RED.util.encodeObject({
          nodeid: evnt.destination.id
        })
      )
    } catch (ex) {
      console.error(ex)
    }
  }

....

RED.hooks.add(OnReceiveDebugHookName, msgTracerOnReceiveHookWithDebug)

What this is does is allow for tracing on a per node basis - I can select a node and have all its messages logged to the debug panel.

To adapt this to a per message basis is trivial because just implements a different filter on the message.

This all works without redeployment and so is suitable for just-in-time debugging.

2 Likes