Connections to Node-Red Instances

Here's something you might find useful. I'm running several instances of Node-RED. This flow displays the number of connections to each instance using the exec node
and ss -tn src :port command
This is the flow

[{"id":"02e760e71e4cfd95","type":"group","z":"d63da7d39b03706f","name":"Connections","style":{"fill":"#3f93cf","label":true,"color":"#000000"},"nodes":["c9446a4dbf68dc73","87b499c95dfc64c4","84a0ab1c3b808b5e","1bf01e75855d284a","c92fd42fc96f79dc","4e67396e1882ef72"],"x":34,"y":879,"w":792,"h":142},{"id":"c9446a4dbf68dc73","type":"exec","z":"d63da7d39b03706f","g":"02e760e71e4cfd95","command":"","addpay":"payload","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"Connected","x":390,"y":960,"wires":[["84a0ab1c3b808b5e"],[],[]]},{"id":"87b499c95dfc64c4","type":"inject","z":"d63da7d39b03706f","g":"02e760e71e4cfd95","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"300","crontab":"","once":false,"onceDelay":0.1,"topic":"OS Info","x":95,"y":960,"wires":[["1bf01e75855d284a"]],"l":false},{"id":"84a0ab1c3b808b5e","type":"function","z":"d63da7d39b03706f","g":"02e760e71e4cfd95","name":"Map","func":"\nlet counts =msg.payload.split('\\n')\n// specify the names of the instances\nlet names=[\"Production\",\"Zone 1\",\"Zone 2\",\"Zone 3\",\"Zone 4\",\"Operations\",\"Development\"]\n\nlet stats=[]\nfor(let i=0;i<names.length;i++){\n    let stat={\"Name\" :names[i],\"Connections\": parseInt(counts[i])}\n    stats.push(stat)\n}\n \n\nmsg.payload=stats\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":550,"y":920,"wires":[["c92fd42fc96f79dc","4e67396e1882ef72"]]},{"id":"1bf01e75855d284a","type":"function","z":"d63da7d39b03706f","g":"02e760e71e4cfd95","name":"cmd","func":"\n// specify the ports in use\nlet ports=[1880,1881,1882,1885,1886,1887,1888]\nlet cmd=''\nfor(let i=0;i< ports.length;i++){\n    cmd +=`ss -tn src :${ports[i]}  | wc -l && `\n}\nmsg.payload=cmd.slice(0,-3)\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":230,"y":960,"wires":[["c9446a4dbf68dc73"]]},{"id":"c92fd42fc96f79dc","type":"ui-chart","z":"d63da7d39b03706f","g":"02e760e71e4cfd95","group":"935703926b104cfd","name":"connections","label":"Dashboard Connections","order":1,"chartType":"pie","category":"Connections","categoryType":"str","xAxisLabel":"","xAxisProperty":"Name","xAxisPropertyType":"property","xAxisType":"radial","xAxisFormat":"","xAxisFormatType":"auto","xmin":"","xmax":"","yAxisLabel":"","yAxisProperty":"Connections","yAxisPropertyType":"property","ymin":"","ymax":"","bins":10,"action":"replace","stackSeries":false,"pointShape":"circle","pointRadius":4,"showLegend":true,"removeOlder":1,"removeOlderUnit":"3600","removeOlderPoints":"","colors":["#0095ff","#ff0000","#ff7f0e","#2ca02c","#a347e1","#d62728","#ff9896","#9467bd","#c5b0d5"],"textColor":["#ffffff"],"textColorDefault":false,"gridColor":["#e5e5e5"],"gridColorDefault":true,"width":"6","height":"8","className":"","interpolation":"linear","x":730,"y":940,"wires":[[]]},{"id":"4e67396e1882ef72","type":"debug","z":"d63da7d39b03706f","g":"02e760e71e4cfd95","name":"debug 3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":600,"y":980,"wires":[]},{"id":"935703926b104cfd","type":"ui-group","name":"Connections","page":"40b1bea1d5488e9d","width":6,"height":1,"order":5,"showTitle":false,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"40b1bea1d5488e9d","type":"ui-page","name":"System Status","ui":"4740393b964cb7af","path":"/system","icon":"mdi-cog","layout":"tabs","theme":"11edfaf96d0baec1","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":16,"className":"","visible":"true","disabled":"false"},{"id":"4740393b964cb7af","type":"ui-base","name":"Tiger","path":"/dashboard","appIcon":"","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control","ui-dropdown","ui-chart","ui-gauge","ui-button","ui-template","ui-text","ui-table","ui-form"],"showPathInSidebar":false,"headerContent":"page","navigationStyle":"fixed","titleBarStyle":"hidden","showReconnectNotification":true,"notificationDisplayTime":"1","showDisconnectNotification":true},{"id":"11edfaf96d0baec1","type":"ui-theme","name":"Dark1","colors":{"surface":"#424242","primary":"#0094ce","bgPage":"#424242","groupBg":"#424242","groupOutline":"#424242"},"sizes":{"density":"default","pagePadding":"2px","groupGap":"6px","groupBorderRadius":"4px","widgetGap":"10px"}}]

1 Like

what would be equivalent for windows OS?

Try netstat -n | find /c "1880"

1 Like
C:\Users\OEEHo>netstat -n | find /c "1881"
4

C:\Users\OEEHo>netstat -n | find /c "1880"
0

C:\Users\OEEHo>netstat -n | find /c "1881"
4

C:\Users\OEEHo>netstat -n | find /c "1882"
8

C:\Users\OEEHo>netstat -n | find /c "1883"
14

C:\Users\OEEHo>netstat -n | find /c "1884"
0

I get results when i type this in command line. dont know how to get the function node changed to get the same result in a for loop

// specify the ports in use
let ports=[1880,1881,1882,1885,1886,1887]
let cmd=''
for(let i=0;i< ports.length;i++){
    cmd +=`netstat -n | find /c "1881" `
}
msg.payload=cmd.slice(0,-3)
return msg;

i get an error message with above in function node, obviously it is not correct.

You could try something like:

const ports = [1880, 1881, 1882, 1885, 1886, 1887];
ports.forEach(port => {
    const cmd = `netstat -n | find /c "${port}"`
    node.send({payload:cmd})
});

return null

this did not work, however the below worked. i am not really sure what is the code doing, this was just trial and error...

// specify the ports in use
let ports=[1882,1881,1882,1881,1882,1885]
let cmd=''
for(let i=0;i< ports.length;i++){
    cmd +=`netstat -n | find /c "${ports[i]}" &&`
} 
msg.payload=cmd.slice(0,-1)
return msg;

So this is what the code is doing
${ports[i]} will substitute the value here with the port at index i i.e. ports[0] is 1882

find /c "1882" will return the number of lines netstat returned containing the value 1882

&& runs the commands in sequence

cmd.slice(0,-3) removes the last &&

I see you are repeating several ports? Not sure why

Nice idea but cmd passed to exec node for each port overwriting the previous payload to chart. Probably would work with a join node to combine them before passing to chart

Thanks for the explanation

Somehow the code fails to give results if there's a zero return, so I was testing repeating ports which are giving non zero results

Hadn't tested that on windows. Single commands return 0 if no connections but empty if we send multiple commands. I'll have to investigate this further

I think I have found the solution for windows

cmd +=netstat -n | find /c "${ports[i]}" &

If we use && and the command returns nothing then subsequent command return nothing even if they have a count
By using a single ampersand & it correctly returns a count for each port including 0

1 Like

Yes it works!

// specify the ports in use
let ports = [1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887]
let cmd=''
for(let i=0;i< ports.length;i++){
    cmd += `netstat -n | find /c "${ports[i]}" &`
} 
msg.payload=cmd.slice(0,-1)
return msg;
[
{"Name":"Live","Connections":0},
{"Name":"Dashboard","Connections":1},
{"Name":"Downtime","Connections":4},
{"Name":"MQTT","Connections":14},
{"Name":"UIB","Connections":0},
{"Name":"Reports","Connections":0},
{"Name":"Utilities","Connections":0}
]

1 Like

Just wanted to stop by and thanks for this flow @gerrybartley
I've had to split my Node-RED project into 11 to stop memory leaks, slow dashboard v2 load times and general crash-happy issues.
I've always wondered what the connection load spread was on them and have jumped through a ton of hoops trying to get some data on them. (Mainly an exec node calling pm2 jlist and getting the bits that help monitor dashboard performance).

This flow was a joy to install and get running straight out the gate.

Glad it was of some use. I've gotten a lot of help from this forum, so time I gave something back :slightly_smiling_face:
I'm using pm2 as well to control my instances. I'll share another flow using jlist next week, although I suspect you may have already done something similar

2 Likes