From 9f6842bc8ad68658045a1141f2a7f6c268b0e95e Mon Sep 17 00:00:00 2001 From: Ryan Melton Date: Sun, 20 Sep 2026 21:49:07 -0600 Subject: [PATCH 1/4] Add metrics to data flows --- docs.openc3.com/docs/tools/cmd-tlm-server.md | 6 + .../package.json | 1 + .../InterfaceComponents/CosmosNode.vue | 18 +- .../InterfaceComponents/DetailsTable.vue | 14 ++ .../FlowHealthIndicator.vue | 61 ++++++ .../InterfaceComponents/FlowMetricsPanel.vue | 87 ++++++++ .../InterfaceFlowChart.vue | 67 +++++- .../InterfaceComponents/InterfaceNode.vue | 16 +- .../InterfaceComponents/RouterNode.vue | 16 +- .../InterfaceComponents/TargetNode.vue | 2 +- .../TargetProcessingDetails.vue | 48 +++++ .../InterfaceComponents/flowMetrics.js | 196 ++++++++++++++++++ .../InterfaceComponents/useFlowMetrics.js | 52 +++++ .../src/tools/CmdTlmServer/InterfacesTab.vue | 5 +- .../src/tools/CmdTlmServer/RoutersTab.vue | 5 +- .../tests/flowMetrics.test.js | 185 +++++++++++++++++ .../src/services/openc3Api.js | 4 +- openc3/lib/openc3/api/metrics_api.rb | 6 +- openc3/spec/api/metrics_api_spec.rb | 58 ++++++ 19 files changed, 826 insertions(+), 21 deletions(-) create mode 100644 openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/FlowHealthIndicator.vue create mode 100644 openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/FlowMetricsPanel.vue create mode 100644 openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/TargetProcessingDetails.vue create mode 100644 openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/flowMetrics.js create mode 100644 openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/useFlowMetrics.js create mode 100644 openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/tests/flowMetrics.test.js create mode 100644 openc3/spec/api/metrics_api_spec.rb diff --git a/docs.openc3.com/docs/tools/cmd-tlm-server.md b/docs.openc3.com/docs/tools/cmd-tlm-server.md index 3dcea62c13..45a87146f9 100644 --- a/docs.openc3.com/docs/tools/cmd-tlm-server.md +++ b/docs.openc3.com/docs/tools/cmd-tlm-server.md @@ -73,6 +73,12 @@ The Data Flows tab displays all the Interface data flows through the system. ![Data Flows](/img/cmd_tlm_server/data_flows.png) +Click an Interface or Router node to see its processing metrics below the properties and raw data. Click a Target Processing node on the left to see metrics for that target's services, including decommutation, logging, and database ingestion. Each service instance is listed separately so a slow instance is visible. The same metrics are available in the connection maps opened from the Interfaces and Routers tabs. + +Nodes show an amber or red outline and a **Falling behind** indicator when a reported queue delay or processing duration reaches 1 second (amber) or 5 seconds (red), or buffered input reaches 1 MiB (amber) or 10 MiB (red). Click the indicator to see the affected metric and service. These thresholds are diagnostic indicators; normal buffering and processing times depend on your configuration and traffic. + +Metrics refresh approximately every 5 seconds. Reports older than 30 seconds are marked **Stale metrics**, and request failures show **Metrics unavailable**. Services with no delay or buffer samples show **No delay samples**. Measurements describe the last processed data, so idle services retain their last measurement; they do not measure the current age of unprocessed data. Counters are cumulative and reset when a service restarts. Use the pause button in either details dialog to freeze the displayed values for inspection. + You can disconnect the interface from the COSMOS Processing by clicking and deleting the lines connecting the Processing to the Interface. This will leave the interface "connected" but no commands are sent out or telemetry processed. Removing the lines from the Interface to the Target will effectively "unmap" the interface and restart it. This may require re-installing the plugin to restore the interface. From the Details dialog you can also view details about the individual Protocols applied to the Interface. In the EXAMPLE_INT Interface, when you click on the Length protocol you can see the details of the protocol. diff --git a/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/package.json b/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/package.json index 09fc1eb4aa..8504e79820 100644 --- a/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/package.json +++ b/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/package.json @@ -4,6 +4,7 @@ "private": true, "type": "module", "scripts": { + "test": "node --test tests/*.test.js", "serve": "vite build --watch --mode dev-server", "build": "vite build", "lint": "eslint src", diff --git a/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/CosmosNode.vue b/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/CosmosNode.vue index 59650918e6..5d07a73c23 100644 --- a/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/CosmosNode.vue +++ b/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/CosmosNode.vue @@ -12,7 +12,7 @@ --> diff --git a/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/FlowMetricsPanel.vue b/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/FlowMetricsPanel.vue new file mode 100644 index 0000000000..adbf09cb16 --- /dev/null +++ b/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/FlowMetricsPanel.vue @@ -0,0 +1,87 @@ + + + + + + + diff --git a/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/InterfaceFlowChart.vue b/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/InterfaceFlowChart.vue index b52258555b..43760d20d4 100644 --- a/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/InterfaceFlowChart.vue +++ b/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/InterfaceFlowChart.vue @@ -17,6 +17,8 @@ import { VueFlow, useVueFlow } from '@vue-flow/core' import { ControlButton, Controls } from '@vue-flow/controls' import { Background } from '@vue-flow/background' import DetailsTable from './DetailsTable.vue' +import TargetProcessingDetails from './TargetProcessingDetails.vue' +import { useFlowMetrics } from './useFlowMetrics' import InterfaceNode from './InterfaceNode.vue' import RouterNode from './RouterNode.vue' import CosmosNode from './CosmosNode.vue' @@ -44,9 +46,10 @@ const dialog = inject('dialog') const api = new OpenC3Api() const props = defineProps({ - interfaceDetails: { type: Array, default: () => [] }, - routerDetails: { type: Array, default: () => [] }, + interfaceDetails: { type: Object, default: () => ({}) }, + routerDetails: { type: Object, default: () => ({}) }, }) +const nodeHealth = useFlowMetrics(api) const nodes = ref([]) const edges = ref([]) @@ -430,6 +433,7 @@ const PROTOCOL_CHROME = 40 // Icon, padding and border of a protocol node const PROTOCOL_MIN_WIDTH = 60 const PROTOCOL_WRITE_Y = 98 // Upper row const PROTOCOL_READ_Y = 148 // Lower row +const NODE_HEIGHT = 212 // Leave space between the lower row and metrics button // Position a row of protocols, returning the label, width, relative x position // and original protocol index of each. Nodes are laid out in the direction the @@ -514,9 +518,14 @@ const selectedMode = ref(null) const selectedDetails = ref(null) const selectedWriteProtocolIndex = ref(null) const selectedReadProtocolIndex = ref(null) +const processingDialog = ref(false) +const selectedTarget = ref('') function onNodeClick(event) { - if (event.node.type === 'interface') { + if (event.node.type === 'cosmos') { + selectedTarget.value = event.node.data.label + processingDialog.value = true + } else if (event.node.type === 'interface') { selectedMode.value = 'Interface' selectedDetails.value = props.interfaceDetails[event.node.data.label] selectedWriteProtocolIndex.value = null @@ -775,7 +784,7 @@ function updateFlowChart() { let x, y // Single target: place to the right x = 0 - y = index * (200 + 50) + y = index * (NODE_HEIGHT + 50) // Create cosmos node const cosmosNode = { @@ -799,7 +808,7 @@ function updateFlowChart() { if (protocols.width > maxInterfaceOrRouterWidth) { maxInterfaceOrRouterWidth = protocols.width } - const interfaceHeight = 200 // Fixed height for two protocol rows + const interfaceHeight = NODE_HEIGHT // Create interface node (center) with dynamic size const interfaceNode = { @@ -826,7 +835,7 @@ function updateFlowChart() { if (protocols.width > maxInterfaceOrRouterWidth) { maxInterfaceOrRouterWidth = protocols.width } - const routerHeight = 200 // Fixed height for two protocol rows + const routerHeight = NODE_HEIGHT // Create router node (center) with dynamic size const routerNode = { @@ -851,7 +860,7 @@ function updateFlowChart() { let x, y // Single target: place to the right x = 200 + 200 + maxInterfaceOrRouterWidth + 200 - y = index * (200 + 50) + y = index * (NODE_HEIGHT + 50) // Create target node const targetNode = { @@ -950,11 +959,19 @@ watch( @@ -1030,6 +1065,18 @@ watch( background-color: rgb(23, 38, 53); } +.interface-flow-chart .flow-node--warning, +.interface-flow-chart .flow-node--stale, +.interface-flow-chart .flow-node--unavailable { + border-color: #b45309; + box-shadow: 0 0 0 2px #fbbf24; +} + +.interface-flow-chart .flow-node--critical { + border-color: #b91c1c; + box-shadow: 0 0 0 2px #f87171; +} + .vue-flow__edges path { stroke-width: 2; } diff --git a/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/InterfaceNode.vue b/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/InterfaceNode.vue index 79933d206d..9a2dd7eae5 100644 --- a/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/InterfaceNode.vue +++ b/openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-cmdtlmserver/src/tools/CmdTlmServer/InterfaceComponents/InterfaceNode.vue @@ -12,10 +12,19 @@ -->