Repository: node-red/node-red (js)

Issue:
When flows runtime is stopped, diagnostics reports `runtime: { isStarted: true }`
### Current Behavior

When flows runtime is stopped, diagnostics reports ...

```JSON
    "runtime": {
        "isStarted": true,
        ...
```

### Expected Behavior

Should be `false` 
Alternatively, an additional property of `flowsRunTime`

### Steps To Reproduce

1. stop the flows from deploy menu
2. run the action "Show System Info" 9or call the diagnostics endpoint)

### Example flow

NA

### Environment

- Node-RED version: 3.0.0
- Node.js version: 16
- npm version:
- Platform/OS: Windows
- Browser:


Pull request description:
Sys info (diagnostics report) amendments
fixes #3771

## Types of changes
- [x] Bugfix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)

## Proposed changes

* [include flows stop/start state](https://github.com/node-red/node-red/commit/af4f07cb263f98d27ed424fca48a3eb1212afa6a)
  * Include flows run / stop state in the report 
  * This differs from the existing `runtime.isStarted` (which is true if the runtime is finished initialising)

* [add a handful of missing settings to basic report](https://github.com/node-red/node-red/commit/a4d66622a5130728e5391e0478db8fa6746e4d45)
  * Opportunistic chance to add a few missing items that are (functionally) inconsequential but useful for diagnostics
  * I can remove from PR if you prefer these to be in 3.1.0


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I have read the [contribution guidelines](https://github.com/node-red/node-red/blob/master/CONTRIBUTING.md)
- [ ] For non-bugfix PRs, I have discussed this change on the forum/slack team.
- [x] I have run `grunt` to verify the unit tests pass
- [ ] I have added suitable unit tests to cover the new/changed functionality


Patch:
diff --git a/packages/node_modules/@node-red/runtime/lib/api/diagnostics.js b/packages/node_modules/@node-red/runtime/lib/api/diagnostics.js
index cbf9fc9d7..b0debf96e 100644
--- a/packages/node_modules/@node-red/runtime/lib/api/diagnostics.js
+++ b/packages/node_modules/@node-red/runtime/lib/api/diagnostics.js
@@ -100,9 +100,13 @@ function buildDiagnosticReport(scope, callback) {
             version: os.version(),
         },
         runtime: {
+            version: runtime.settings.version,
             isStarted: runtime.isStarted(),
+            flows: {
+                state: runtime.flows && runtime.flows.state(),
+                started: runtime.flows && runtime.flows.started,
+            },
             modules: modules,
-            version: runtime.settings.version,
             settings: {
                 available: runtime.settings.available(),
                 apiMaxLength: runtime.settings.apiMaxLength || "UNSET",
@@ -114,6 +118,11 @@ function buildDiagnosticReport(scope, callback) {
                 flowFile: runtime.settings.flowFile || "UNSET",
                 mqttReconnectTime: runtime.settings.mqttReconnectTime || "UNSET",
                 serialReconnectTime: runtime.settings.serialReconnectTime || "UNSET",
+                socketReconnectTime: runtime.settings.socketReconnectTime || "UNSET",
+                socketTimeout: runtime.settings.socketTimeout || "UNSET",
+                tcpMsgQueueSize: runtime.settings.tcpMsgQueueSize || "UNSET",
+                inboundWebSocketTimeout: runtime.settings.inboundWebSocketTimeout || "UNSET",
+                runtimeState: runtime.settings.runtimeState || "UNSET",
 
                 adminAuth: runtime.settings.adminAuth ? "SET" : "UNSET",
 
@@ -131,6 +140,7 @@ function buildDiagnosticReport(scope, callback) {
                 uiHost: runtime.settings.uiHost ? "SET" : "UNSET",
                 uiPort: runtime.settings.uiPort ? "SET" : "UNSET",
                 userDir: runtime.settings.userDir ? "SET" : "UNSET",
+                nodesDir: runtime.settings.nodesDir && runtime.settings.nodesDir.length ? "SET" : "UNSET",
             }
         }
     }


Test patch:
diff --git a/test/unit/@node-red/runtime/lib/api/diagnostics_spec.js b/test/unit/@node-red/runtime/lib/api/diagnostics_spec.js
index 07e499344..136e4826c 100644
--- a/test/unit/@node-red/runtime/lib/api/diagnostics_spec.js
+++ b/test/unit/@node-red/runtime/lib/api/diagnostics_spec.js
@@ -33,6 +33,11 @@ describe("runtime-api/diagnostics", function() {
                     flowFile: "flows.json",
                     mqttReconnectTime: 321,
                     serialReconnectTime: 432,
+                    socketReconnectTime: 2222,
+                    socketTimeout: 3333,
+                    tcpMsgQueueSize: 4444,
+                    inboundWebSocketTimeout: 5555,
+                    runtimeState: {enabled: true, ui: false},
                     adminAuth: {},//should be sanitised to "SET"
                     httpAdminRoot: "/admin/root/",
                     httpAdminCors: {},//should be sanitised to "SET"
@@ -45,6 +50,7 @@ describe("runtime-api/diagnostics", function() {
                     uiHost: "something.secret.com",//should be sanitised to "SET"
                     uiPort: 1337,//should be sanitised to "SET"
                     userDir: "/var/super/secret/",//should be sanitised to "SET",
+                    nodesDir: "/var/super/secret/",//should be sanitised to "SET",
                     contextStorage: {
                         default    : { module: "memory" },
                         file: { module: "localfilesystem" },
@@ -73,8 +79,9 @@ describe("runtime-api/diagnostics", function() {
 
                 //result.runtime.xxxxx
                 const runtimeCount = Object.keys(result.runtime).length;
-                runtimeCount.should.eql(4);//ensure no more than 4 keys are present in runtime 
+                runtimeCount.should.eql(5);//ensure 5 keys are present in runtime 
                 result.runtime.should.have.property('isStarted',true)
+                result.runtime.should.have.property('flows')
                 result.runtime.should.have.property('modules').type("object");
                 result.runtime.should.have.property('settings').type("object");
                 result.runtime.should.have.property('version','7.7.7');
@@ -87,7 +94,7 @@ describe("runtime-api/diagnostics", function() {
 
                 //result.runtime.settings.xxxxx
                 const settingsCount = Object.keys(result.runtime.settings).length;
-                settingsCount.should.eql(21);//ensure no more than the 21 settings listed below are present in the settings object
+                settingsCount.should.eql(27);//ensure no more than the 21 settings listed below are present in the settings object
                 result.runtime.settings.should.have.property('available',true);
                 result.runtime.settings.should.have.property('apiMaxLength', "UNSET");//deliberately disabled to ensure UNSET is returned
                 result.runtime.settings.should.have.property('debugMaxLength', 1111);
@@ -96,6 +103,11 @@ describe("runtime-api/diagnostics", function() {
                 result.runtime.settings.should.have.property('flowFile', "flows.json");
                 result.runtime.settings.should.have.property('mqttReconnectTime', 321);
                 result.runtime.settings.should.have.property('serialReconnectTime', 432);
+                result.runtime.settings.should.have.property('socketReconnectTime', 2222);
+                result.runtime.settings.should.have.property('socketTimeout', 3333);
+                result.runtime.settings.should.have.property('tcpMsgQueueSize', 4444);
+                result.runtime.settings.should.have.property('inboundWebSocketTimeout', 5555);
+                result.runtime.settings.should.have.property('runtimeState', {enabled: true, ui: false});
                 result.runtime.settings.should.have.property("adminAuth", "SET"); //should be sanitised to "SET"
                 result.runtime.settings.should.have.property("httpAdminCors", "SET"); //should be sanitised to "SET"
                 result.runtime.settings.should.have.property('httpAdminRoot', "/admin/root/");
@@ -109,6 +121,7 @@ describe("runtime-api/diagnostics", function() {
                 result.runtime.settings.should.have.property("uiPort", "SET"); //should be sanitised to "SET"
                 result.runtime.settings.should.have.property("userDir", "SET"); //should be sanitised to "SET"
                 result.runtime.settings.should.have.property('contextStorage').type("object");
+                result.runtime.settings.should.have.property('nodesDir', "SET")
 
                 //result.runtime.settings.contextStorage.xxxxx
                 const contextCount = Object.keys(result.runtime.settings.contextStorage).length;