From 2da4b30019782e7b1def85a168c68f4f81d8dc68 Mon Sep 17 00:00:00 2001 From: buenosairesam Date: Mon, 26 Jan 2026 20:36:34 -0300 Subject: [PATCH] Fix edge to handle nested metrics format from gateway forwarding --- .gitignore | 1 + ctrl/.env.example | 3 +++ ctrl/collector.sh | 46 ++++++++++++++++++++++++++++++++++++++++++++++ ctrl/edge/edge.py | 33 +++++++++++++++++++++++++++------ ctrl/run.sh | 23 +++++++++++++++++++++++ 5 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 ctrl/.env.example create mode 100755 ctrl/collector.sh create mode 100755 ctrl/run.sh diff --git a/.gitignore b/.gitignore index 896b048..7c17cef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ def .env +ctrl/.env diff --git a/ctrl/.env.example b/ctrl/.env.example new file mode 100644 index 0000000..642ae79 --- /dev/null +++ b/ctrl/.env.example @@ -0,0 +1,3 @@ +EDGE_URL=wss://sysmonstm.mcrn.ar/ws +EDGE_API_KEY=your-api-key-here +MACHINE_ID=your-hostname diff --git a/ctrl/collector.sh b/ctrl/collector.sh new file mode 100755 index 0000000..4684141 --- /dev/null +++ b/ctrl/collector.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Run sysmonstm collector only (for secondary machines) +# Usage: ./ctrl/collector.sh [aggregator-ip] [--remote] +# +# Examples: +# ./ctrl/collector.sh 192.168.1.33 # Build locally (default) +# ./ctrl/collector.sh 192.168.1.33 --remote # Use registry image + +cd "$(dirname "$0")/.." + +AGGREGATOR_IP=${1:-192.168.1.33} +MACHINE_ID=$(hostname) +USE_REMOTE=false + +if [ "$2" = "--remote" ]; then + USE_REMOTE=true +fi + +# Check if aggregator is reachable +echo "Checking connection to aggregator at $AGGREGATOR_IP:50051..." +if ! nc -z -w 3 "$AGGREGATOR_IP" 50051 2>/dev/null; then + echo "" + echo "ERROR: Cannot connect to aggregator at $AGGREGATOR_IP:50051" + echo "" + echo "Make sure the full stack is running on the main machine first:" + echo " cd ~/wdir/sms && ./ctrl/run.sh" + echo "" + exit 1 +fi +echo "Aggregator reachable." + +if [ "$USE_REMOTE" = true ]; then + IMAGE="registry.mcrn.ar/sysmonstm/collector:latest" + echo "Using remote image: $IMAGE" +else + IMAGE="sysmonstm-collector:local" + echo "Building local image..." + docker build -t $IMAGE -f services/collector/Dockerfile . +fi + +echo "Starting collector for $MACHINE_ID -> $AGGREGATOR_IP:50051" + +docker run --rm --name sysmonstm-collector --network host \ + -e AGGREGATOR_URL=${AGGREGATOR_IP}:50051 \ + -e MACHINE_ID=${MACHINE_ID} \ + $IMAGE diff --git a/ctrl/edge/edge.py b/ctrl/edge/edge.py index 581fe00..bdb1f07 100644 --- a/ctrl/edge/edge.py +++ b/ctrl/edge/edge.py @@ -222,16 +222,37 @@ async def websocket_endpoint(websocket: WebSocket, key: str = Query(default="")) await websocket.close(code=4001, reason="Invalid API key") return - machine_id = data.get("machine_id", "unknown") - machines[machine_id] = data - log.debug(f"Metrics from {machine_id}: cpu={data.get('cpu')}%") + # Handle both formats: + # 1. Direct: {"type": "metrics", "machine_id": "...", "cpu": ...} + # 2. Nested (from gateway): {"type": "metrics", "data": {...}, "timestamp": "..."} + if "data" in data and isinstance(data["data"], dict): + # Nested format from gateway forwarding + payload = data["data"] + machine_id = payload.get("machine_id", "unknown") + # Extract metrics from nested structure + metrics = payload.get("metrics", {}) + metric_data = { + "type": "metrics", + "machine_id": machine_id, + "hostname": payload.get("hostname", ""), + "timestamp": data.get("timestamp"), + } + # Flatten metrics for dashboard display + for key_name, value in metrics.items(): + metric_data[key_name.lower()] = value + machines[machine_id] = metric_data + log.debug(f"Metrics (forwarded) from {machine_id}") + else: + # Direct format from collector + machine_id = data.get("machine_id", "unknown") + machines[machine_id] = data + log.debug(f"Metrics from {machine_id}: cpu={data.get('cpu')}%") # Broadcast to all connected clients + broadcast_data = machines[machine_id] for conn in connections: try: - await conn.send_json( - {"type": "metrics", "machine_id": machine_id, **data} - ) + await conn.send_json(broadcast_data) except Exception: pass diff --git a/ctrl/run.sh b/ctrl/run.sh new file mode 100755 index 0000000..0018ba4 --- /dev/null +++ b/ctrl/run.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Run sysmonstm full stack locally with edge forwarding +# Usage: ./ctrl/run.sh [--remote] +# +# Examples: +# ./ctrl/run.sh # Build locally (default) +# ./ctrl/run.sh --remote # Use registry images + +cd "$(dirname "$0")/.." + +# Load env from ctrl/.env +set -a +source ctrl/.env +set +a + +if [ "$1" = "--remote" ]; then + echo "Using remote images from registry" + docker compose pull + docker compose up "${@:2}" +else + echo "Building locally..." + docker compose up --build "$@" +fi