Compare commits
11 Commits
9ddcb68131
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a15de4f72b | |||
| 8c6ec2e683 | |||
| 6dc3c01637 | |||
| 0f60556e81 | |||
|
|
91f95d55a5 | ||
|
|
3106bc835e | ||
|
|
a013e0116f | ||
|
|
8ecd702b63 | ||
|
|
2da4b30019 | ||
|
|
754d3e55fb | ||
|
|
761bca20b0 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1 +1,5 @@
|
||||
def
|
||||
.env
|
||||
ctrl/.env
|
||||
|
||||
#
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# sysmonstm Pipeline
|
||||
|
||||
when:
|
||||
- event: push
|
||||
- event: manual
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: registry.mcrn.ar/sysmonstm
|
||||
registry: registry.mcrn.ar
|
||||
tags:
|
||||
- latest
|
||||
- ${CI_COMMIT_SHA:0:7}
|
||||
dockerfile: ctrl/edge/Dockerfile
|
||||
context: ctrl/edge
|
||||
25
.woodpecker/build.yml
Normal file
25
.woodpecker/build.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
# sysmonstm Pipeline
|
||||
|
||||
when:
|
||||
- event: push
|
||||
- event: manual
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: registry.mcrn.ar/sysmonstm/edge
|
||||
registry: registry.mcrn.ar
|
||||
tags:
|
||||
- latest
|
||||
- ${CI_COMMIT_SHA:0:7}
|
||||
dockerfile: ctrl/edge/Dockerfile
|
||||
context: ctrl/edge
|
||||
|
||||
- name: deploy
|
||||
image: docker:24-cli
|
||||
commands:
|
||||
- docker pull registry.mcrn.ar/sysmonstm/edge:latest
|
||||
- docker stop sysmonstm-edge || true
|
||||
- docker rm sysmonstm-edge || true
|
||||
- docker run -d --name sysmonstm-edge --restart unless-stopped --network gateway -p 8080:8080 registry.mcrn.ar/sysmonstm/edge:latest
|
||||
3
ctrl/.env.example
Normal file
3
ctrl/.env.example
Normal file
@@ -0,0 +1,3 @@
|
||||
EDGE_URL=wss://sysmonstm.mcrn.ar/ws
|
||||
EDGE_API_KEY=your-api-key-here
|
||||
MACHINE_ID=your-hostname
|
||||
46
ctrl/collector.sh
Executable file
46
ctrl/collector.sh
Executable file
@@ -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
|
||||
@@ -90,6 +90,8 @@ services:
|
||||
HTTP_PORT: 8000
|
||||
AGGREGATOR_URL: aggregator:50051
|
||||
SERVICE_NAME: gateway
|
||||
EDGE_URL: ${EDGE_URL:-}
|
||||
EDGE_API_KEY: ${EDGE_API_KEY:-}
|
||||
ports:
|
||||
- "${GATEWAY_PORT:-8000}:8000"
|
||||
depends_on:
|
||||
|
||||
@@ -2,9 +2,10 @@ FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN pip install --no-cache-dir fastapi uvicorn[standard] websockets
|
||||
RUN pip install --no-cache-dir fastapi uvicorn[standard] websockets jinja2
|
||||
|
||||
COPY edge.py .
|
||||
COPY templates/ templates/
|
||||
|
||||
ENV API_KEY=""
|
||||
ENV LOG_LEVEL=INFO
|
||||
|
||||
15
ctrl/edge/deploy.sh
Executable file
15
ctrl/edge/deploy.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
# Deploy sysmonstm edge service
|
||||
# Called by Woodpecker or manually
|
||||
|
||||
set -e
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
echo "Pulling latest image..."
|
||||
docker compose pull
|
||||
|
||||
echo "Deploying edge service..."
|
||||
docker compose up -d --remove-orphans
|
||||
|
||||
echo "Deploy complete"
|
||||
docker compose ps
|
||||
@@ -4,10 +4,12 @@ import asyncio
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import FastAPI, Query, WebSocket, WebSocketDisconnect
|
||||
from fastapi.requests import Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
|
||||
# Configuration
|
||||
API_KEY = os.environ.get("API_KEY", "")
|
||||
@@ -23,162 +25,19 @@ log = logging.getLogger("gateway")
|
||||
|
||||
app = FastAPI(title="sysmonstm")
|
||||
|
||||
# Templates
|
||||
templates_path = Path(__file__).parent / "templates"
|
||||
templates = Jinja2Templates(directory=str(templates_path))
|
||||
|
||||
# Store connected websockets
|
||||
connections: list[WebSocket] = []
|
||||
# Store latest metrics from collectors
|
||||
machines: dict = {}
|
||||
|
||||
HTML = """
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>sysmonstm</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #1a1a2e;
|
||||
--bg2: #16213e;
|
||||
--text: #eee;
|
||||
--accent: #e94560;
|
||||
--success: #4ade80;
|
||||
--muted: #666;
|
||||
}
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: system-ui, sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
min-height: 100vh;
|
||||
padding: 2rem;
|
||||
}
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 2px solid var(--accent);
|
||||
}
|
||||
h1 { font-size: 1.5rem; }
|
||||
.status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent);
|
||||
}
|
||||
.dot.ok { background: var(--success); }
|
||||
.machines {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
.machine {
|
||||
background: var(--bg2);
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
}
|
||||
.machine h3 { margin-bottom: 0.5rem; }
|
||||
.metric {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0.25rem 0;
|
||||
border-bottom: 1px solid #333;
|
||||
}
|
||||
.empty {
|
||||
text-align: center;
|
||||
color: var(--muted);
|
||||
padding: 4rem;
|
||||
}
|
||||
.empty p { margin-top: 1rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>sysmonstm</h1>
|
||||
<div class="status">
|
||||
<span class="dot" id="ws-status"></span>
|
||||
<span id="status-text">connecting...</span>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<div id="machines" class="machines">
|
||||
<div class="empty">
|
||||
<h2>No collectors connected</h2>
|
||||
<p>Start a collector to see metrics</p>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<script>
|
||||
const machinesEl = document.getElementById('machines');
|
||||
const statusDot = document.getElementById('ws-status');
|
||||
const statusText = document.getElementById('status-text');
|
||||
let machines = {};
|
||||
|
||||
function connect() {
|
||||
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const ws = new WebSocket(`${protocol}//${location.host}/ws`);
|
||||
|
||||
ws.onopen = () => {
|
||||
statusDot.classList.add('ok');
|
||||
statusText.textContent = 'connected';
|
||||
};
|
||||
|
||||
ws.onclose = () => {
|
||||
statusDot.classList.remove('ok');
|
||||
statusText.textContent = 'disconnected';
|
||||
setTimeout(connect, 2000);
|
||||
};
|
||||
|
||||
ws.onmessage = (e) => {
|
||||
const data = JSON.parse(e.data);
|
||||
if (data.type === 'metrics') {
|
||||
machines[data.machine_id] = data;
|
||||
render();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function render() {
|
||||
const ids = Object.keys(machines).sort();
|
||||
if (ids.length === 0) {
|
||||
machinesEl.innerHTML = '<div class="empty"><h2>No collectors connected</h2><p>Start a collector to see metrics</p></div>';
|
||||
return;
|
||||
}
|
||||
|
||||
machinesEl.innerHTML = ids.map(id => {
|
||||
const m = machines[id];
|
||||
const ts = m.timestamp ? new Date(m.timestamp * 1000).toLocaleTimeString() : '-';
|
||||
return `
|
||||
<div class="machine">
|
||||
<h3>${id}</h3>
|
||||
<div class="metric"><span>CPU</span><span>${m.cpu?.toFixed(1) || '-'}%</span></div>
|
||||
<div class="metric"><span>Memory</span><span>${m.memory?.toFixed(1) || '-'}%</span></div>
|
||||
<div class="metric"><span>Disk</span><span>${m.disk?.toFixed(1) || '-'}%</span></div>
|
||||
<div class="metric"><span>Load (1m)</span><span>${m.load_1m?.toFixed(2) || '-'}</span></div>
|
||||
<div class="metric"><span>Processes</span><span>${m.processes || '-'}</span></div>
|
||||
<div class="metric"><span>Updated</span><span>${ts}</span></div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
connect();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
|
||||
@app.get("/", response_class=HTMLResponse)
|
||||
async def index():
|
||||
return HTML
|
||||
async def index(request: Request):
|
||||
return templates.TemplateResponse("dashboard.html", {"request": request})
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
@@ -194,7 +53,6 @@ async def get_machines():
|
||||
@app.websocket("/ws")
|
||||
async def websocket_endpoint(websocket: WebSocket, key: str = Query(default="")):
|
||||
# API key validation for collectors (browsers don't need key)
|
||||
# Check if this looks like a collector (will send metrics) or browser (will receive)
|
||||
# We validate key only when metrics are received, allowing browsers to connect freely
|
||||
|
||||
await websocket.accept()
|
||||
@@ -222,16 +80,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
|
||||
|
||||
|
||||
349
ctrl/edge/templates/dashboard.html
Normal file
349
ctrl/edge/templates/dashboard.html
Normal file
@@ -0,0 +1,349 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>System Monitor Dashboard</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg-primary: #1a1a2e;
|
||||
--bg-secondary: #16213e;
|
||||
--bg-card: #0f3460;
|
||||
--text-primary: #eee;
|
||||
--text-secondary: #a0a0a0;
|
||||
--accent: #e94560;
|
||||
--success: #4ade80;
|
||||
--warning: #fbbf24;
|
||||
--danger: #ef4444;
|
||||
--border: #2a2a4a;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
|
||||
body {
|
||||
font-family: system-ui, -apple-system, sans-serif;
|
||||
background: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
header {
|
||||
background: var(--bg-secondary);
|
||||
padding: 1rem 2rem;
|
||||
border-bottom: 2px solid var(--accent);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
header h1 { font-size: 1.5rem; }
|
||||
|
||||
.status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background: var(--danger);
|
||||
}
|
||||
|
||||
.status-dot.connected { background: var(--success); }
|
||||
|
||||
main {
|
||||
padding: 1.5rem;
|
||||
max-width: 1600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.machines-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.machine-card {
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 8px;
|
||||
padding: 1.25rem;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.machine-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 1rem;
|
||||
padding-bottom: 0.75rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.machine-name {
|
||||
font-weight: 600;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.machine-id {
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.machine-status {
|
||||
font-size: 0.75rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
background: var(--success);
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.machine-status.warning { background: var(--warning); }
|
||||
.machine-status.critical { background: var(--danger); color: #fff; }
|
||||
|
||||
.metrics-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.metric {
|
||||
background: var(--bg-card);
|
||||
padding: 0.75rem;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.metric-label {
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.metric-value {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.metric-bar {
|
||||
height: 4px;
|
||||
background: var(--border);
|
||||
border-radius: 2px;
|
||||
margin-top: 0.5rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.metric-bar-fill {
|
||||
height: 100%;
|
||||
background: var(--success);
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.metric-bar-fill.warning { background: var(--warning); }
|
||||
.metric-bar-fill.critical { background: var(--danger); }
|
||||
|
||||
.last-seen {
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-secondary);
|
||||
margin-top: 1rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.no-machines {
|
||||
text-align: center;
|
||||
padding: 3rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.no-machines h2 {
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.machines-grid { grid-template-columns: 1fr; }
|
||||
.metrics-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>System Monitor</h1>
|
||||
<div class="status">
|
||||
<span class="status-dot" id="status-dot"></span>
|
||||
<span id="status-text">Connecting...</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="machines-grid" id="machines-grid">
|
||||
<div class="no-machines">
|
||||
<h2>No machines connected</h2>
|
||||
<p>Waiting for collectors to send metrics...</p>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
const machinesGrid = document.getElementById('machines-grid');
|
||||
const statusDot = document.getElementById('status-dot');
|
||||
const statusText = document.getElementById('status-text');
|
||||
|
||||
const machines = new Map();
|
||||
|
||||
function formatBytes(bytes) {
|
||||
if (bytes === 0) return '0 B';
|
||||
const k = 1024;
|
||||
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
function formatRate(bytesPerSec) {
|
||||
return formatBytes(bytesPerSec) + '/s';
|
||||
}
|
||||
|
||||
function getBarClass(value, warning = 80, critical = 95) {
|
||||
if (value >= critical) return 'critical';
|
||||
if (value >= warning) return 'warning';
|
||||
return '';
|
||||
}
|
||||
|
||||
function getStatusClass(m) {
|
||||
const cpu = m.cpu_percent || 0;
|
||||
const mem = m.memory_percent || 0;
|
||||
const disk = m.disk_percent || 0;
|
||||
|
||||
if (cpu > 95 || mem > 95 || disk > 90) return 'critical';
|
||||
if (cpu > 80 || mem > 85 || disk > 80) return 'warning';
|
||||
return '';
|
||||
}
|
||||
|
||||
function timeSince(timestamp) {
|
||||
if (!timestamp) return '-';
|
||||
const date = typeof timestamp === 'string' ? new Date(timestamp) : new Date(timestamp);
|
||||
const seconds = Math.floor((Date.now() - date.getTime()) / 1000);
|
||||
if (seconds < 5) return 'just now';
|
||||
if (seconds < 60) return seconds + 's ago';
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
if (minutes < 60) return minutes + 'm ago';
|
||||
return Math.floor(minutes / 60) + 'h ago';
|
||||
}
|
||||
|
||||
function renderMachine(data) {
|
||||
const m = data;
|
||||
const statusClass = getStatusClass(m);
|
||||
|
||||
return `
|
||||
<div class="machine-card" data-machine="${data.machine_id}">
|
||||
<div class="machine-header">
|
||||
<div>
|
||||
<div class="machine-name">${data.hostname || data.machine_id}</div>
|
||||
<div class="machine-id">${data.machine_id}</div>
|
||||
</div>
|
||||
<span class="machine-status ${statusClass}">${statusClass || 'healthy'}</span>
|
||||
</div>
|
||||
<div class="metrics-grid">
|
||||
<div class="metric">
|
||||
<div class="metric-label">CPU</div>
|
||||
<div class="metric-value">${(m.cpu_percent || 0).toFixed(1)}%</div>
|
||||
<div class="metric-bar">
|
||||
<div class="metric-bar-fill ${getBarClass(m.cpu_percent || 0)}"
|
||||
style="width: ${m.cpu_percent || 0}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<div class="metric-label">Memory</div>
|
||||
<div class="metric-value">${(m.memory_percent || 0).toFixed(1)}%</div>
|
||||
<div class="metric-bar">
|
||||
<div class="metric-bar-fill ${getBarClass(m.memory_percent || 0, 85, 95)}"
|
||||
style="width: ${m.memory_percent || 0}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<div class="metric-label">Disk</div>
|
||||
<div class="metric-value">${(m.disk_percent || 0).toFixed(1)}%</div>
|
||||
<div class="metric-bar">
|
||||
<div class="metric-bar-fill ${getBarClass(m.disk_percent || 0, 80, 90)}"
|
||||
style="width: ${m.disk_percent || 0}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<div class="metric-label">Load (1m)</div>
|
||||
<div class="metric-value">${(m.load_avg_1m || 0).toFixed(2)}</div>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<div class="metric-label">Network In</div>
|
||||
<div class="metric-value">${formatRate(m.network_recv_bytes_sec || 0)}</div>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<div class="metric-label">Network Out</div>
|
||||
<div class="metric-value">${formatRate(m.network_sent_bytes_sec || 0)}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="last-seen">Last seen: ${timeSince(m.timestamp)}</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function updateUI() {
|
||||
if (machines.size === 0) {
|
||||
machinesGrid.innerHTML = `
|
||||
<div class="no-machines">
|
||||
<h2>No machines connected</h2>
|
||||
<p>Waiting for collectors to send metrics...</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
machinesGrid.innerHTML = Array.from(machines.values())
|
||||
.map(renderMachine)
|
||||
.join('');
|
||||
}
|
||||
|
||||
function connect() {
|
||||
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const ws = new WebSocket(`${protocol}//${location.host}/ws`);
|
||||
|
||||
ws.onopen = () => {
|
||||
statusDot.classList.add('connected');
|
||||
statusText.textContent = 'Connected';
|
||||
};
|
||||
|
||||
ws.onclose = () => {
|
||||
statusDot.classList.remove('connected');
|
||||
statusText.textContent = 'Disconnected - Reconnecting...';
|
||||
setTimeout(connect, 3000);
|
||||
};
|
||||
|
||||
ws.onerror = () => {
|
||||
statusDot.classList.remove('connected');
|
||||
statusText.textContent = 'Connection error';
|
||||
};
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
try {
|
||||
const msg = JSON.parse(event.data);
|
||||
if (msg.type === 'metrics' || msg.type === 'initial') {
|
||||
machines.set(msg.machine_id, msg);
|
||||
updateUI();
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to parse message:', e);
|
||||
}
|
||||
};
|
||||
|
||||
setInterval(() => {
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
ws.send('ping');
|
||||
}
|
||||
}, 30000);
|
||||
}
|
||||
|
||||
setInterval(updateUI, 5000);
|
||||
connect();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
23
ctrl/run.sh
Executable file
23
ctrl/run.sh
Executable file
@@ -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
|
||||
@@ -24,9 +24,19 @@ digraph SystemOverview {
|
||||
machines [label="Monitored\nMachines", fillcolor="#FFF3E0", shape=box3d];
|
||||
}
|
||||
|
||||
// Edge (AWS)
|
||||
subgraph cluster_edge {
|
||||
label="AWS (sysmonstm.mcrn.ar)";
|
||||
style=filled;
|
||||
color="#F3E5F5";
|
||||
fillcolor="#F3E5F5";
|
||||
|
||||
edge_relay [label="Edge\n(WebSocket Relay)", fillcolor="#E1BEE7"];
|
||||
}
|
||||
|
||||
// Core Services
|
||||
subgraph cluster_services {
|
||||
label="Application Services";
|
||||
label="Local Stack";
|
||||
style=filled;
|
||||
color="#E8F5E9";
|
||||
fillcolor="#E8F5E9";
|
||||
@@ -59,7 +69,10 @@ digraph SystemOverview {
|
||||
}
|
||||
|
||||
// Connections
|
||||
browser -> gateway [label="WebSocket\nREST", color="#1976D2"];
|
||||
browser -> edge_relay [label="WebSocket", color="#1976D2"];
|
||||
edge_relay -> gateway [label="WebSocket\nForward", color="#1976D2", dir=back];
|
||||
|
||||
browser -> gateway [label="WebSocket\n(local dev)", color="#1976D2", style=dashed];
|
||||
gateway -> aggregator [label="gRPC", color="#388E3C"];
|
||||
gateway -> redis [label="State\nQuery", style=dashed];
|
||||
gateway -> timescale [label="Historical\nQuery", style=dashed];
|
||||
@@ -73,6 +86,4 @@ digraph SystemOverview {
|
||||
|
||||
events -> alerts [label="Subscribe", color="#7B1FA2"];
|
||||
events -> gateway [label="Subscribe", color="#7B1FA2"];
|
||||
|
||||
alerts -> timescale [label="Store\nAlerts", style=dashed];
|
||||
}
|
||||
|
||||
@@ -1,193 +1,212 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.1 (0)
|
||||
<!-- Generated by graphviz version 14.1.2 (0)
|
||||
-->
|
||||
<!-- Title: SystemOverview Pages: 1 -->
|
||||
<svg width="444pt" height="508pt"
|
||||
viewBox="0.00 0.00 444.00 508.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 503.78)">
|
||||
<svg width="577pt" height="618pt"
|
||||
viewBox="0.00 0.00 577.00 618.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 614.03)">
|
||||
<title>SystemOverview</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-503.78 440,-503.78 440,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="218" y="-480.58" font-family="Helvetica,sans-Serif" font-size="16.00">System Monitoring Platform - Architecture Overview</text>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-614.03 573,-614.03 573,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="284.5" y="-590.83" font-family="Helvetica,sans-Serif" font-size="16.00">System Monitoring Platform - Architecture Overview</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_external</title>
|
||||
<polygon fill="none" stroke="gray" stroke-dasharray="5,2" points="45.5,-374.2 45.5,-453.7 235.5,-453.7 235.5,-374.2 45.5,-374.2"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="140.5" y="-434.5" font-family="Helvetica,sans-Serif" font-size="16.00">External</text>
|
||||
<polygon fill="none" stroke="gray" stroke-dasharray="5,2" points="208,-495.03 208,-574.53 398,-574.53 398,-495.03 208,-495.03"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="303" y="-555.33" font-family="Helvetica,sans-Serif" font-size="16.00">External</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_services</title>
|
||||
<polygon fill="#e8f5e9" stroke="#e8f5e9" points="101.5,-143.12 101.5,-320.12 363.5,-320.12 363.5,-143.12 101.5,-143.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="232.5" y="-300.93" font-family="Helvetica,sans-Serif" font-size="16.00">Application Services</text>
|
||||
<title>cluster_edge</title>
|
||||
<polygon fill="#f3e5f5" stroke="#f3e5f5" points="8,-374.2 8,-453.7 238,-453.7 238,-374.2 8,-374.2"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="123" y="-434.5" font-family="Helvetica,sans-Serif" font-size="16.00">AWS (sysmonstm.mcrn.ar)</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_data</title>
|
||||
<polygon fill="#fff8e1" stroke="#fff8e1" points="22.5,-8 22.5,-99.62 260.5,-99.62 260.5,-8 22.5,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="141.5" y="-80.42" font-family="Helvetica,sans-Serif" font-size="16.00">Data Layer</text>
|
||||
<title>cluster_services</title>
|
||||
<polygon fill="#e8f5e9" stroke="#e8f5e9" points="227,-143.12 227,-320.12 489,-320.12 489,-143.12 227,-143.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="358" y="-300.93" font-family="Helvetica,sans-Serif" font-size="16.00">Local Stack</text>
|
||||
</g>
|
||||
<g id="clust4" class="cluster">
|
||||
<title>cluster_data</title>
|
||||
<polygon fill="#fff8e1" stroke="#fff8e1" points="162,-8 162,-99.62 400,-99.62 400,-8 162,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="281" y="-80.42" font-family="Helvetica,sans-Serif" font-size="16.00">Data Layer</text>
|
||||
</g>
|
||||
<g id="clust5" class="cluster">
|
||||
<title>cluster_events</title>
|
||||
<polygon fill="#f3e5f5" stroke="#f3e5f5" points="243.5,-363.62 243.5,-464.28 413.5,-464.28 413.5,-363.62 243.5,-363.62"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="328.5" y="-445.08" font-family="Helvetica,sans-Serif" font-size="16.00">Event Stream</text>
|
||||
<polygon fill="#f3e5f5" stroke="#f3e5f5" points="391,-363.62 391,-464.28 561,-464.28 561,-363.62 391,-363.62"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="476" y="-445.08" font-family="Helvetica,sans-Serif" font-size="16.00">Event Stream</text>
|
||||
</g>
|
||||
<!-- browser -->
|
||||
<g id="node1" class="node">
|
||||
<title>browser</title>
|
||||
<path fill="#e3f2fd" stroke="black" d="M125.62,-418.2C125.62,-418.2 65.38,-418.2 65.38,-418.2 59.38,-418.2 53.38,-412.2 53.38,-406.2 53.38,-406.2 53.38,-394.2 53.38,-394.2 53.38,-388.2 59.38,-382.2 65.38,-382.2 65.38,-382.2 125.62,-382.2 125.62,-382.2 131.62,-382.2 137.62,-388.2 137.62,-394.2 137.62,-394.2 137.62,-406.2 137.62,-406.2 137.62,-412.2 131.62,-418.2 125.62,-418.2"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="95.5" y="-403.25" font-family="Helvetica,sans-Serif" font-size="11.00">Browser</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="95.5" y="-389.75" font-family="Helvetica,sans-Serif" font-size="11.00">(Dashboard)</text>
|
||||
<path fill="#e3f2fd" stroke="black" d="M288.12,-539.03C288.12,-539.03 227.88,-539.03 227.88,-539.03 221.88,-539.03 215.88,-533.03 215.88,-527.03 215.88,-527.03 215.88,-515.03 215.88,-515.03 215.88,-509.03 221.88,-503.03 227.88,-503.03 227.88,-503.03 288.12,-503.03 288.12,-503.03 294.12,-503.03 300.12,-509.03 300.12,-515.03 300.12,-515.03 300.12,-527.03 300.12,-527.03 300.12,-533.03 294.12,-539.03 288.12,-539.03"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="258" y="-524.08" font-family="Helvetica,sans-Serif" font-size="11.00">Browser</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="258" y="-510.58" font-family="Helvetica,sans-Serif" font-size="11.00">(Dashboard)</text>
|
||||
</g>
|
||||
<!-- edge_relay -->
|
||||
<g id="node3" class="node">
|
||||
<title>edge_relay</title>
|
||||
<path fill="#e1bee7" stroke="black" d="M217.12,-418.2C217.12,-418.2 120.88,-418.2 120.88,-418.2 114.88,-418.2 108.88,-412.2 108.88,-406.2 108.88,-406.2 108.88,-394.2 108.88,-394.2 108.88,-388.2 114.88,-382.2 120.88,-382.2 120.88,-382.2 217.12,-382.2 217.12,-382.2 223.12,-382.2 229.12,-388.2 229.12,-394.2 229.12,-394.2 229.12,-406.2 229.12,-406.2 229.12,-412.2 223.12,-418.2 217.12,-418.2"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="169" y="-403.25" font-family="Helvetica,sans-Serif" font-size="11.00">Edge</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="169" y="-389.75" font-family="Helvetica,sans-Serif" font-size="11.00">(WebSocket Relay)</text>
|
||||
</g>
|
||||
<!-- browser->edge_relay -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>browser->edge_relay</title>
|
||||
<path fill="none" stroke="#1976d2" d="M218.56,-502.6C210.86,-497.79 203.43,-491.95 197.75,-485.03 184.82,-469.28 177.57,-447.39 173.59,-429.93"/>
|
||||
<polygon fill="#1976d2" stroke="#1976d2" points="177.03,-429.28 171.62,-420.16 170.17,-430.66 177.03,-429.28"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="224.38" y="-475.53" font-family="Helvetica,sans-Serif" font-size="10.00">WebSocket</text>
|
||||
</g>
|
||||
<!-- gateway -->
|
||||
<g id="node3" class="node">
|
||||
<g id="node4" class="node">
|
||||
<title>gateway</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M161.88,-284.62C161.88,-284.62 121.12,-284.62 121.12,-284.62 115.12,-284.62 109.12,-278.62 109.12,-272.62 109.12,-272.62 109.12,-260.62 109.12,-260.62 109.12,-254.62 115.12,-248.62 121.12,-248.62 121.12,-248.62 161.88,-248.62 161.88,-248.62 167.88,-248.62 173.88,-254.62 173.88,-260.62 173.88,-260.62 173.88,-272.62 173.88,-272.62 173.88,-278.62 167.88,-284.62 161.88,-284.62"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="141.5" y="-269.68" font-family="Helvetica,sans-Serif" font-size="11.00">Gateway</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="141.5" y="-256.18" font-family="Helvetica,sans-Serif" font-size="11.00">(FastAPI)</text>
|
||||
<path fill="#c8e6c9" stroke="black" d="M287.38,-284.62C287.38,-284.62 246.62,-284.62 246.62,-284.62 240.62,-284.62 234.62,-278.62 234.62,-272.62 234.62,-272.62 234.62,-260.62 234.62,-260.62 234.62,-254.62 240.62,-248.62 246.62,-248.62 246.62,-248.62 287.38,-248.62 287.38,-248.62 293.38,-248.62 299.38,-254.62 299.38,-260.62 299.38,-260.62 299.38,-272.62 299.38,-272.62 299.38,-278.62 293.38,-284.62 287.38,-284.62"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="267" y="-269.68" font-family="Helvetica,sans-Serif" font-size="11.00">Gateway</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="267" y="-256.18" font-family="Helvetica,sans-Serif" font-size="11.00">(FastAPI)</text>
|
||||
</g>
|
||||
<!-- browser->gateway -->
|
||||
<g id="edge1" class="edge">
|
||||
<g id="edge3" class="edge">
|
||||
<title>browser->gateway</title>
|
||||
<path fill="none" stroke="#1976d2" d="M92.73,-381.75C91.08,-367.05 90.32,-345.66 96.25,-328.12 100.5,-315.57 108.45,-303.5 116.51,-293.49"/>
|
||||
<polygon fill="#1976d2" stroke="#1976d2" points="119.02,-295.94 122.86,-286.06 113.7,-291.39 119.02,-295.94"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="122.88" y="-344.12" font-family="Helvetica,sans-Serif" font-size="10.00">WebSocket</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="122.88" y="-331.38" font-family="Helvetica,sans-Serif" font-size="10.00">REST</text>
|
||||
<path fill="none" stroke="#1976d2" stroke-dasharray="5,2" d="M258.62,-502.68C260.14,-459.9 264.1,-349.03 265.98,-296.3"/>
|
||||
<polygon fill="#1976d2" stroke="#1976d2" points="269.46,-296.73 266.32,-286.61 262.47,-296.48 269.46,-296.73"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="290.17" y="-403.45" font-family="Helvetica,sans-Serif" font-size="10.00">WebSocket</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="290.17" y="-390.7" font-family="Helvetica,sans-Serif" font-size="10.00">(local dev)</text>
|
||||
</g>
|
||||
<!-- machines -->
|
||||
<g id="node2" class="node">
|
||||
<title>machines</title>
|
||||
<polygon fill="#fff3e0" stroke="black" points="227.25,-418.2 159.75,-418.2 155.75,-414.2 155.75,-382.2 223.25,-382.2 227.25,-386.2 227.25,-418.2"/>
|
||||
<polyline fill="none" stroke="black" points="223.25,-414.2 155.75,-414.2"/>
|
||||
<polyline fill="none" stroke="black" points="223.25,-414.2 223.25,-382.2"/>
|
||||
<polyline fill="none" stroke="black" points="223.25,-414.2 227.25,-418.2"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="191.5" y="-403.25" font-family="Helvetica,sans-Serif" font-size="11.00">Monitored</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="191.5" y="-389.75" font-family="Helvetica,sans-Serif" font-size="11.00">Machines</text>
|
||||
<polygon fill="#fff3e0" stroke="black" points="389.75,-539.03 322.25,-539.03 318.25,-535.03 318.25,-503.03 385.75,-503.03 389.75,-507.03 389.75,-539.03"/>
|
||||
<polyline fill="none" stroke="black" points="385.75,-535.03 318.25,-535.03"/>
|
||||
<polyline fill="none" stroke="black" points="385.75,-535.03 385.75,-503.03"/>
|
||||
<polyline fill="none" stroke="black" points="385.75,-535.03 389.75,-539.03"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="354" y="-524.08" font-family="Helvetica,sans-Serif" font-size="11.00">Monitored</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="354" y="-510.58" font-family="Helvetica,sans-Serif" font-size="11.00">Machines</text>
|
||||
</g>
|
||||
<!-- collector -->
|
||||
<g id="node6" class="node">
|
||||
<g id="node7" class="node">
|
||||
<title>collector</title>
|
||||
<path fill="#dcedc8" stroke="black" d="M343.88,-284.62C343.88,-284.62 279.12,-284.62 279.12,-284.62 273.12,-284.62 267.12,-278.62 267.12,-272.62 267.12,-272.62 267.12,-260.62 267.12,-260.62 267.12,-254.62 273.12,-248.62 279.12,-248.62 279.12,-248.62 343.88,-248.62 343.88,-248.62 349.88,-248.62 355.88,-254.62 355.88,-260.62 355.88,-260.62 355.88,-272.62 355.88,-272.62 355.88,-278.62 349.88,-284.62 343.88,-284.62"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="311.5" y="-269.68" font-family="Helvetica,sans-Serif" font-size="11.00">Collector</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="311.5" y="-256.18" font-family="Helvetica,sans-Serif" font-size="11.00">(gRPC Client)</text>
|
||||
<path fill="#dcedc8" stroke="black" d="M394.38,-284.62C394.38,-284.62 329.62,-284.62 329.62,-284.62 323.62,-284.62 317.62,-278.62 317.62,-272.62 317.62,-272.62 317.62,-260.62 317.62,-260.62 317.62,-254.62 323.62,-248.62 329.62,-248.62 329.62,-248.62 394.38,-248.62 394.38,-248.62 400.38,-248.62 406.38,-254.62 406.38,-260.62 406.38,-260.62 406.38,-272.62 406.38,-272.62 406.38,-278.62 400.38,-284.62 394.38,-284.62"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="362" y="-269.68" font-family="Helvetica,sans-Serif" font-size="11.00">Collector</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="362" y="-256.18" font-family="Helvetica,sans-Serif" font-size="11.00">(gRPC Client)</text>
|
||||
</g>
|
||||
<!-- machines->collector -->
|
||||
<g id="edge5" class="edge">
|
||||
<g id="edge7" class="edge">
|
||||
<title>machines->collector</title>
|
||||
<path fill="none" stroke="#f57c00" stroke-dasharray="1,5" d="M210.81,-381.83C219.12,-375.21 229.26,-368.17 239.5,-363.62 260.21,-354.43 273.06,-369.22 289.5,-353.62 304.98,-338.94 310.15,-314.98 311.64,-296.08"/>
|
||||
<polygon fill="#f57c00" stroke="#f57c00" points="315.12,-296.47 312.08,-286.32 308.13,-296.15 315.12,-296.47"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="318.1" y="-337.75" font-family="Helvetica,sans-Serif" font-size="10.00">psutil</text>
|
||||
<path fill="none" stroke="#f57c00" stroke-dasharray="1,5" d="M354.55,-502.68C355.91,-459.9 359.42,-349.03 361.09,-296.3"/>
|
||||
<polygon fill="#f57c00" stroke="#f57c00" points="364.58,-296.71 361.4,-286.61 357.58,-296.49 364.58,-296.71"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="372.43" y="-397.08" font-family="Helvetica,sans-Serif" font-size="10.00">psutil</text>
|
||||
</g>
|
||||
<!-- edge_relay->gateway -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>edge_relay->gateway</title>
|
||||
<path fill="none" stroke="#1976d2" d="M177.03,-370.92C181.74,-357.23 188.58,-341 197.75,-328.12 209.78,-311.22 227.45,-295.88 241.93,-284.88"/>
|
||||
<polygon fill="#1976d2" stroke="#1976d2" points="173.75,-369.67 174.03,-380.26 180.42,-371.81 173.75,-369.67"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="224.38" y="-344.12" font-family="Helvetica,sans-Serif" font-size="10.00">WebSocket</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="224.38" y="-331.38" font-family="Helvetica,sans-Serif" font-size="10.00">Forward</text>
|
||||
</g>
|
||||
<!-- aggregator -->
|
||||
<g id="node4" class="node">
|
||||
<g id="node5" class="node">
|
||||
<title>aggregator</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M343.12,-187.12C343.12,-187.12 273.88,-187.12 273.88,-187.12 267.88,-187.12 261.88,-181.12 261.88,-175.12 261.88,-175.12 261.88,-163.12 261.88,-163.12 261.88,-157.12 267.88,-151.12 273.88,-151.12 273.88,-151.12 343.12,-151.12 343.12,-151.12 349.12,-151.12 355.12,-157.12 355.12,-163.12 355.12,-163.12 355.12,-175.12 355.12,-175.12 355.12,-181.12 349.12,-187.12 343.12,-187.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="308.5" y="-172.18" font-family="Helvetica,sans-Serif" font-size="11.00">Aggregator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="308.5" y="-158.68" font-family="Helvetica,sans-Serif" font-size="11.00">(gRPC Server)</text>
|
||||
<path fill="#c8e6c9" stroke="black" d="M412.62,-187.12C412.62,-187.12 343.38,-187.12 343.38,-187.12 337.38,-187.12 331.38,-181.12 331.38,-175.12 331.38,-175.12 331.38,-163.12 331.38,-163.12 331.38,-157.12 337.38,-151.12 343.38,-151.12 343.38,-151.12 412.62,-151.12 412.62,-151.12 418.62,-151.12 424.62,-157.12 424.62,-163.12 424.62,-163.12 424.62,-175.12 424.62,-175.12 424.62,-181.12 418.62,-187.12 412.62,-187.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="378" y="-172.18" font-family="Helvetica,sans-Serif" font-size="11.00">Aggregator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="378" y="-158.68" font-family="Helvetica,sans-Serif" font-size="11.00">(gRPC Server)</text>
|
||||
</g>
|
||||
<!-- gateway->aggregator -->
|
||||
<g id="edge2" class="edge">
|
||||
<g id="edge4" class="edge">
|
||||
<title>gateway->aggregator</title>
|
||||
<path fill="none" stroke="#388e3c" d="M171.74,-248.33C198.77,-232.88 238.56,-210.12 268.26,-193.13"/>
|
||||
<polygon fill="#388e3c" stroke="#388e3c" points="269.66,-196.37 276.6,-188.36 266.19,-190.29 269.66,-196.37"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="257.62" y="-214.75" font-family="Helvetica,sans-Serif" font-size="10.00">gRPC</text>
|
||||
<path fill="none" stroke="#388e3c" d="M287.1,-248.33C304.44,-233.41 329.68,-211.69 349.17,-194.93"/>
|
||||
<polygon fill="#388e3c" stroke="#388e3c" points="351.23,-197.78 356.53,-188.6 346.66,-192.47 351.23,-197.78"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="348.46" y="-214.75" font-family="Helvetica,sans-Serif" font-size="10.00">gRPC</text>
|
||||
</g>
|
||||
<!-- redis -->
|
||||
<g id="node7" class="node">
|
||||
<g id="node8" class="node">
|
||||
<title>redis</title>
|
||||
<path fill="#ffecb3" stroke="black" d="M146,-59.75C146,-62.16 120.23,-64.12 88.5,-64.12 56.77,-64.12 31,-62.16 31,-59.75 31,-59.75 31,-20.38 31,-20.38 31,-17.96 56.77,-16 88.5,-16 120.23,-16 146,-17.96 146,-20.38 146,-20.38 146,-59.75 146,-59.75"/>
|
||||
<path fill="none" stroke="black" d="M146,-59.75C146,-57.34 120.23,-55.38 88.5,-55.38 56.77,-55.38 31,-57.34 31,-59.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="88.5" y="-43.11" font-family="Helvetica,sans-Serif" font-size="11.00">Redis</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="88.5" y="-29.61" font-family="Helvetica,sans-Serif" font-size="11.00">(Pub/Sub + State)</text>
|
||||
<path fill="#ffecb3" stroke="black" d="M285.5,-59.75C285.5,-62.16 259.73,-64.12 228,-64.12 196.27,-64.12 170.5,-62.16 170.5,-59.75 170.5,-59.75 170.5,-20.38 170.5,-20.38 170.5,-17.96 196.27,-16 228,-16 259.73,-16 285.5,-17.96 285.5,-20.38 285.5,-20.38 285.5,-59.75 285.5,-59.75"/>
|
||||
<path fill="none" stroke="black" d="M285.5,-59.75C285.5,-57.34 259.73,-55.38 228,-55.38 196.27,-55.38 170.5,-57.34 170.5,-59.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="228" y="-43.11" font-family="Helvetica,sans-Serif" font-size="11.00">Redis</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="228" y="-29.61" font-family="Helvetica,sans-Serif" font-size="11.00">(Pub/Sub + State)</text>
|
||||
</g>
|
||||
<!-- gateway->redis -->
|
||||
<g id="edge3" class="edge">
|
||||
<g id="edge5" class="edge">
|
||||
<title>gateway->redis</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M122.74,-248.35C108.28,-233.68 89.42,-211.2 81.25,-187.12 68.86,-150.62 73.72,-106.03 79.72,-75.79"/>
|
||||
<polygon fill="black" stroke="black" points="83.14,-76.56 81.82,-66.04 76.29,-75.08 83.14,-76.56"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="95.88" y="-172.38" font-family="Helvetica,sans-Serif" font-size="10.00">State</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="95.88" y="-159.62" font-family="Helvetica,sans-Serif" font-size="10.00">Query</text>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M251.25,-248.13C238.89,-233.15 222.67,-210.37 215.75,-187.12 204.73,-150.09 211.09,-105.6 218.09,-75.53"/>
|
||||
<polygon fill="black" stroke="black" points="221.49,-76.39 220.51,-65.84 214.7,-74.69 221.49,-76.39"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="230.38" y="-172.38" font-family="Helvetica,sans-Serif" font-size="10.00">State</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="230.38" y="-159.62" font-family="Helvetica,sans-Serif" font-size="10.00">Query</text>
|
||||
</g>
|
||||
<!-- timescale -->
|
||||
<g id="node8" class="node">
|
||||
<g id="node9" class="node">
|
||||
<title>timescale</title>
|
||||
<path fill="#ffecb3" stroke="black" d="M252.88,-59.75C252.88,-62.16 232.99,-64.12 208.5,-64.12 184.01,-64.12 164.12,-62.16 164.12,-59.75 164.12,-59.75 164.12,-20.38 164.12,-20.38 164.12,-17.96 184.01,-16 208.5,-16 232.99,-16 252.88,-17.96 252.88,-20.38 252.88,-20.38 252.88,-59.75 252.88,-59.75"/>
|
||||
<path fill="none" stroke="black" d="M252.88,-59.75C252.88,-57.34 232.99,-55.38 208.5,-55.38 184.01,-55.38 164.12,-57.34 164.12,-59.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="208.5" y="-43.11" font-family="Helvetica,sans-Serif" font-size="11.00">TimescaleDB</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="208.5" y="-29.61" font-family="Helvetica,sans-Serif" font-size="11.00">(Time-series)</text>
|
||||
<path fill="#ffecb3" stroke="black" d="M392.38,-59.75C392.38,-62.16 372.49,-64.12 348,-64.12 323.51,-64.12 303.62,-62.16 303.62,-59.75 303.62,-59.75 303.62,-20.38 303.62,-20.38 303.62,-17.96 323.51,-16 348,-16 372.49,-16 392.38,-17.96 392.38,-20.38 392.38,-20.38 392.38,-59.75 392.38,-59.75"/>
|
||||
<path fill="none" stroke="black" d="M392.38,-59.75C392.38,-57.34 372.49,-55.38 348,-55.38 323.51,-55.38 303.62,-57.34 303.62,-59.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="348" y="-43.11" font-family="Helvetica,sans-Serif" font-size="11.00">TimescaleDB</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="348" y="-29.61" font-family="Helvetica,sans-Serif" font-size="11.00">(Time-series)</text>
|
||||
</g>
|
||||
<!-- gateway->timescale -->
|
||||
<g id="edge4" class="edge">
|
||||
<g id="edge6" class="edge">
|
||||
<title>gateway->timescale</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M143.41,-248.29C146.34,-224.28 152.82,-179.73 164,-143.12 171.19,-119.57 182.25,-94.18 191.54,-74.62"/>
|
||||
<polygon fill="black" stroke="black" points="194.62,-76.29 195.83,-65.76 188.32,-73.24 194.62,-76.29"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="187.25" y="-172.38" font-family="Helvetica,sans-Serif" font-size="10.00">Historical</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="187.25" y="-159.62" font-family="Helvetica,sans-Serif" font-size="10.00">Query</text>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M266.24,-248.27C265.63,-224.24 266.08,-179.67 275.5,-143.12 282.34,-116.6 300.01,-91.45 316.2,-72.76"/>
|
||||
<polygon fill="black" stroke="black" points="318.64,-75.28 322.72,-65.51 313.43,-70.6 318.64,-75.28"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="298.75" y="-172.38" font-family="Helvetica,sans-Serif" font-size="10.00">Historical</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="298.75" y="-159.62" font-family="Helvetica,sans-Serif" font-size="10.00">Query</text>
|
||||
</g>
|
||||
<!-- aggregator->redis -->
|
||||
<g id="edge7" class="edge">
|
||||
<g id="edge9" class="edge">
|
||||
<title>aggregator->redis</title>
|
||||
<path fill="none" stroke="#ffa000" d="M267.27,-150.69C261,-148.11 254.59,-145.52 248.5,-143.12 236.59,-138.44 233.22,-138.25 221.5,-133.12 191.36,-119.95 182.76,-118.04 155.5,-99.62 143.6,-91.59 131.5,-81.66 120.93,-72.28"/>
|
||||
<polygon fill="#ffa000" stroke="#ffa000" points="123.32,-69.73 113.56,-65.6 118.62,-74.91 123.32,-69.73"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="239.5" y="-123.62" font-family="Helvetica,sans-Serif" font-size="10.00">Current</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="239.5" y="-110.88" font-family="Helvetica,sans-Serif" font-size="10.00">State</text>
|
||||
<path fill="none" stroke="#ffa000" d="M348.99,-150.75C340.7,-145.41 331.8,-139.3 324,-133.12 300.45,-114.48 276.05,-91.01 257.74,-72.44"/>
|
||||
<polygon fill="#ffa000" stroke="#ffa000" points="260.33,-70.08 250.84,-65.37 255.32,-74.97 260.33,-70.08"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="342" y="-123.62" font-family="Helvetica,sans-Serif" font-size="10.00">Current</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="342" y="-110.88" font-family="Helvetica,sans-Serif" font-size="10.00">State</text>
|
||||
</g>
|
||||
<!-- aggregator->timescale -->
|
||||
<g id="edge8" class="edge">
|
||||
<g id="edge10" class="edge">
|
||||
<title>aggregator->timescale</title>
|
||||
<path fill="none" stroke="#ffa000" d="M294.81,-150.72C279.15,-130.84 253.2,-97.86 233.84,-73.25"/>
|
||||
<polygon fill="#ffa000" stroke="#ffa000" points="236.64,-71.16 227.71,-65.47 231.14,-75.49 236.64,-71.16"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="296.95" y="-123.62" font-family="Helvetica,sans-Serif" font-size="10.00">Store</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="296.95" y="-110.88" font-family="Helvetica,sans-Serif" font-size="10.00">Metrics</text>
|
||||
<path fill="none" stroke="#ffa000" d="M373.89,-150.72C369.32,-131.36 361.82,-99.6 356.07,-75.22"/>
|
||||
<polygon fill="#ffa000" stroke="#ffa000" points="359.53,-74.68 353.83,-65.75 352.72,-76.29 359.53,-74.68"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="387.14" y="-123.62" font-family="Helvetica,sans-Serif" font-size="10.00">Store</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="387.14" y="-110.88" font-family="Helvetica,sans-Serif" font-size="10.00">Metrics</text>
|
||||
</g>
|
||||
<!-- events -->
|
||||
<g id="node9" class="node">
|
||||
<g id="node10" class="node">
|
||||
<title>events</title>
|
||||
<path fill="#e1bee7" stroke="black" d="M395.63,-407.37C395.63,-407.37 376.5,-421.61 376.5,-421.61 371.69,-425.2 360.88,-428.78 354.88,-428.78 354.88,-428.78 302.12,-428.78 302.12,-428.78 296.12,-428.78 285.31,-425.2 280.5,-421.61 280.5,-421.61 261.37,-407.37 261.37,-407.37 256.56,-403.79 256.56,-396.62 261.37,-393.04 261.37,-393.04 280.5,-378.79 280.5,-378.79 285.31,-375.21 296.12,-371.62 302.12,-371.62 302.12,-371.62 354.88,-371.62 354.88,-371.62 360.88,-371.62 371.69,-375.21 376.5,-378.79 376.5,-378.79 395.63,-393.04 395.63,-393.04 400.44,-396.62 400.44,-403.79 395.63,-407.37"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="328.5" y="-403.25" font-family="Helvetica,sans-Serif" font-size="11.00">Redis Pub/Sub</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="328.5" y="-389.75" font-family="Helvetica,sans-Serif" font-size="11.00">(Events)</text>
|
||||
<path fill="#e1bee7" stroke="black" d="M543.13,-407.37C543.13,-407.37 524,-421.61 524,-421.61 519.19,-425.2 508.38,-428.78 502.38,-428.78 502.38,-428.78 449.62,-428.78 449.62,-428.78 443.62,-428.78 432.81,-425.2 428,-421.61 428,-421.61 408.87,-407.37 408.87,-407.37 404.06,-403.79 404.06,-396.62 408.87,-393.04 408.87,-393.04 428,-378.79 428,-378.79 432.81,-375.21 443.62,-371.62 449.62,-371.62 449.62,-371.62 502.38,-371.62 502.38,-371.62 508.38,-371.62 519.19,-375.21 524,-378.79 524,-378.79 543.13,-393.04 543.13,-393.04 547.94,-396.62 547.94,-403.79 543.13,-407.37"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="476" y="-403.25" font-family="Helvetica,sans-Serif" font-size="11.00">Redis Pub/Sub</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="476" y="-389.75" font-family="Helvetica,sans-Serif" font-size="11.00">(Events)</text>
|
||||
</g>
|
||||
<!-- aggregator->events -->
|
||||
<g id="edge9" class="edge">
|
||||
<g id="edge11" class="edge">
|
||||
<title>aggregator->events</title>
|
||||
<path fill="none" stroke="#7b1fa2" d="M333.16,-187.49C339.14,-192.63 345.07,-198.63 349.5,-205.12 361.02,-222.03 361.12,-228.46 364.5,-248.62 369.75,-279.97 371.24,-289.07 364.5,-320.12 361.48,-334.06 355.78,-348.49 349.79,-361.14"/>
|
||||
<polygon fill="#7b1fa2" stroke="#7b1fa2" points="346.73,-359.44 345.42,-369.95 353,-362.55 346.73,-359.44"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="386.64" y="-263.5" font-family="Helvetica,sans-Serif" font-size="10.00">Publish</text>
|
||||
<path fill="none" stroke="#7b1fa2" d="M416.67,-187.52C441.53,-200.73 472.36,-221.29 490,-248.62 495.8,-257.61 513.79,-323.42 505,-353.62 504.25,-356.21 503.3,-358.78 502.21,-361.32"/>
|
||||
<polygon fill="#7b1fa2" stroke="#7b1fa2" points="499.15,-359.62 497.75,-370.12 505.39,-362.79 499.15,-359.62"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="524.36" y="-263.5" font-family="Helvetica,sans-Serif" font-size="10.00">Publish</text>
|
||||
</g>
|
||||
<!-- alerts -->
|
||||
<g id="node5" class="node">
|
||||
<g id="node6" class="node">
|
||||
<title>alerts</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M236.75,-284.62C236.75,-284.62 204.25,-284.62 204.25,-284.62 198.25,-284.62 192.25,-278.62 192.25,-272.62 192.25,-272.62 192.25,-260.62 192.25,-260.62 192.25,-254.62 198.25,-248.62 204.25,-248.62 204.25,-248.62 236.75,-248.62 236.75,-248.62 242.75,-248.62 248.75,-254.62 248.75,-260.62 248.75,-260.62 248.75,-272.62 248.75,-272.62 248.75,-278.62 242.75,-284.62 236.75,-284.62"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="220.5" y="-269.68" font-family="Helvetica,sans-Serif" font-size="11.00">Alerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="220.5" y="-256.18" font-family="Helvetica,sans-Serif" font-size="11.00">Service</text>
|
||||
</g>
|
||||
<!-- alerts->timescale -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>alerts->timescale</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M219.58,-248.38C217.61,-211.47 212.94,-124.24 210.34,-75.51"/>
|
||||
<polygon fill="black" stroke="black" points="213.85,-75.6 209.82,-65.8 206.86,-75.97 213.85,-75.6"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="230.53" y="-172.38" font-family="Helvetica,sans-Serif" font-size="10.00">Store</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="230.53" y="-159.62" font-family="Helvetica,sans-Serif" font-size="10.00">Alerts</text>
|
||||
<path fill="#c8e6c9" stroke="black" d="M469.25,-284.62C469.25,-284.62 436.75,-284.62 436.75,-284.62 430.75,-284.62 424.75,-278.62 424.75,-272.62 424.75,-272.62 424.75,-260.62 424.75,-260.62 424.75,-254.62 430.75,-248.62 436.75,-248.62 436.75,-248.62 469.25,-248.62 469.25,-248.62 475.25,-248.62 481.25,-254.62 481.25,-260.62 481.25,-260.62 481.25,-272.62 481.25,-272.62 481.25,-278.62 475.25,-284.62 469.25,-284.62"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="453" y="-269.68" font-family="Helvetica,sans-Serif" font-size="11.00">Alerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="453" y="-256.18" font-family="Helvetica,sans-Serif" font-size="11.00">Service</text>
|
||||
</g>
|
||||
<!-- collector->aggregator -->
|
||||
<g id="edge6" class="edge">
|
||||
<g id="edge8" class="edge">
|
||||
<title>collector->aggregator</title>
|
||||
<path fill="none" stroke="#388e3c" d="M310.96,-248.55C310.53,-234.65 309.9,-214.73 309.39,-198.45"/>
|
||||
<polygon fill="#388e3c" stroke="#388e3c" points="312.9,-198.77 309.09,-188.89 305.91,-198.99 312.9,-198.77"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="327.98" y="-221.12" font-family="Helvetica,sans-Serif" font-size="10.00">gRPC</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="327.98" y="-208.38" font-family="Helvetica,sans-Serif" font-size="10.00">Stream</text>
|
||||
<path fill="none" stroke="#388e3c" d="M364.86,-248.55C367.19,-234.65 370.53,-214.73 373.25,-198.45"/>
|
||||
<polygon fill="#388e3c" stroke="#388e3c" points="376.66,-199.31 374.86,-188.87 369.76,-198.15 376.66,-199.31"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="389.53" y="-221.12" font-family="Helvetica,sans-Serif" font-size="10.00">gRPC</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="389.53" y="-208.38" font-family="Helvetica,sans-Serif" font-size="10.00">Stream</text>
|
||||
</g>
|
||||
<!-- events->gateway -->
|
||||
<g id="edge11" class="edge">
|
||||
<g id="edge13" class="edge">
|
||||
<title>events->gateway</title>
|
||||
<path fill="none" stroke="#7b1fa2" d="M281.13,-378.02C267.86,-372.71 253.29,-367.44 239.5,-363.62 212.49,-356.16 199.25,-370.98 177.25,-353.62 159.49,-339.61 150.46,-315.21 145.93,-295.98"/>
|
||||
<polygon fill="#7b1fa2" stroke="#7b1fa2" points="149.38,-295.39 143.95,-286.29 142.52,-296.79 149.38,-295.39"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="200.88" y="-337.75" font-family="Helvetica,sans-Serif" font-size="10.00">Subscribe</text>
|
||||
<path fill="none" stroke="#7b1fa2" d="M427.23,-379.02C385.24,-361.12 328.44,-335.5 309,-320.12 299.76,-312.82 291.28,-303.11 284.39,-294.03"/>
|
||||
<polygon fill="#7b1fa2" stroke="#7b1fa2" points="287.4,-292.22 278.71,-286.15 281.72,-296.31 287.4,-292.22"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="391.72" y="-337.75" font-family="Helvetica,sans-Serif" font-size="10.00">Subscribe</text>
|
||||
</g>
|
||||
<!-- events->alerts -->
|
||||
<g id="edge10" class="edge">
|
||||
<g id="edge12" class="edge">
|
||||
<title>events->alerts</title>
|
||||
<path fill="none" stroke="#7b1fa2" d="M277.27,-380.98C264.23,-374.18 251.36,-365.21 242.25,-353.62 229.43,-337.32 224.08,-314.36 221.89,-296.26"/>
|
||||
<polygon fill="#7b1fa2" stroke="#7b1fa2" points="225.38,-296.07 220.98,-286.43 218.41,-296.71 225.38,-296.07"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="265.88" y="-337.75" font-family="Helvetica,sans-Serif" font-size="10.00">Subscribe</text>
|
||||
<path fill="none" stroke="#7b1fa2" d="M463.14,-371.21C460.99,-365.5 459.04,-359.45 457.75,-353.62 453.59,-334.83 452.41,-313.19 452.27,-296.31"/>
|
||||
<polygon fill="#7b1fa2" stroke="#7b1fa2" points="455.77,-296.51 452.31,-286.49 448.77,-296.48 455.77,-296.51"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="481.38" y="-337.75" font-family="Helvetica,sans-Serif" font-size="10.00">Subscribe</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
@@ -60,7 +60,16 @@ digraph DataFlow {
|
||||
|
||||
alerts [label="Alert\nService", fillcolor="#C5CAE9"];
|
||||
gateway [label="Gateway\n(WebSocket)", fillcolor="#9FA8DA"];
|
||||
lambda [label="Lambda\nAggregator", fillcolor="#7986CB", style="rounded,filled,dashed"];
|
||||
}
|
||||
|
||||
// Edge + Browser
|
||||
subgraph cluster_delivery {
|
||||
label="Delivery (AWS)";
|
||||
style=filled;
|
||||
fillcolor="#F3E5F5";
|
||||
|
||||
edge_relay [label="Edge\n(WS Relay)", fillcolor="#E1BEE7"];
|
||||
browser [label="Browser\n(Dashboard)", fillcolor="#CE93D8"];
|
||||
}
|
||||
|
||||
// Flow
|
||||
@@ -75,9 +84,9 @@ digraph DataFlow {
|
||||
redis_pubsub -> alerts [label="metrics.*"];
|
||||
redis_pubsub -> gateway [label="metrics.*"];
|
||||
|
||||
gateway -> edge_relay [label="WebSocket\nForward"];
|
||||
edge_relay -> browser [label="WebSocket"];
|
||||
|
||||
raw -> agg_1m [label="Continuous\nAggregate", style=dashed];
|
||||
agg_1m -> agg_1h [label="Hourly\nJob", style=dashed];
|
||||
|
||||
raw -> lambda [label="SQS\nTrigger", style=dotted];
|
||||
lambda -> agg_1m [label="Batch\nWrite", style=dotted];
|
||||
}
|
||||
|
||||
@@ -1,134 +1,139 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.1 (0)
|
||||
<!-- Generated by graphviz version 14.1.2 (0)
|
||||
-->
|
||||
<!-- Title: DataFlow Pages: 1 -->
|
||||
<svg width="1087pt" height="329pt"
|
||||
viewBox="0.00 0.00 1087.00 329.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 325.25)">
|
||||
<svg width="1270pt" height="305pt"
|
||||
viewBox="0.00 0.00 1270.00 305.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 301.25)">
|
||||
<title>DataFlow</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-325.25 1082.5,-325.25 1082.5,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="539.25" y="-303.95" font-family="Helvetica,sans-Serif" font-size="14.00">Metrics Data Flow Pipeline</text>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-301.25 1265.75,-301.25 1265.75,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="630.88" y="-279.95" font-family="Helvetica,sans-Serif" font-size="14.00">Metrics Data Flow Pipeline</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_collect</title>
|
||||
<polygon fill="#e3f2fd" stroke="black" points="8,-111 8,-188 254,-188 254,-111 8,-111"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="131" y="-170.7" font-family="Helvetica,sans-Serif" font-size="14.00">Collection (5s)</text>
|
||||
<polygon fill="#e3f2fd" stroke="black" points="8,-87 8,-164 254,-164 254,-87 8,-87"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="131" y="-146.7" font-family="Helvetica,sans-Serif" font-size="14.00">Collection (5s)</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_ingest</title>
|
||||
<polygon fill="#e8f5e9" stroke="black" points="307,-95 307,-204 562.5,-204 562.5,-95 307,-95"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="434.75" y="-186.7" font-family="Helvetica,sans-Serif" font-size="14.00">Ingestion</text>
|
||||
<polygon fill="#e8f5e9" stroke="black" points="307,-71 307,-180 562.5,-180 562.5,-71 307,-71"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="434.75" y="-162.7" font-family="Helvetica,sans-Serif" font-size="14.00">Ingestion</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_hot</title>
|
||||
<polygon fill="#fff3e0" stroke="black" points="614.75,-34 614.75,-193 769.5,-193 769.5,-34 614.75,-34"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="692.12" y="-175.7" font-family="Helvetica,sans-Serif" font-size="14.00">Hot Path (Real-time)</text>
|
||||
<polygon fill="#fff3e0" stroke="black" points="614.75,-10 614.75,-169 769.5,-169 769.5,-10 614.75,-10"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="692.12" y="-151.7" font-family="Helvetica,sans-Serif" font-size="14.00">Hot Path (Real-time)</text>
|
||||
</g>
|
||||
<g id="clust4" class="cluster">
|
||||
<title>cluster_warm</title>
|
||||
<polygon fill="#fce4ec" stroke="black" points="645.62,-201 645.62,-288 1070.5,-288 1070.5,-201 645.62,-201"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="858.06" y="-270.7" font-family="Helvetica,sans-Serif" font-size="14.00">Warm Path (Historical)</text>
|
||||
<polygon fill="#fce4ec" stroke="black" points="645.62,-177 645.62,-264 1091.5,-264 1091.5,-177 645.62,-177"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="868.56" y="-246.7" font-family="Helvetica,sans-Serif" font-size="14.00">Warm Path (Historical)</text>
|
||||
</g>
|
||||
<g id="clust5" class="cluster">
|
||||
<title>cluster_consume</title>
|
||||
<polygon fill="#e8eaf6" stroke="black" points="840.5,-8 840.5,-193 935.25,-193 935.25,-8 840.5,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="887.88" y="-175.7" font-family="Helvetica,sans-Serif" font-size="14.00">Consumers</text>
|
||||
<polygon fill="#e8eaf6" stroke="black" points="840.5,-8 840.5,-139 935.25,-139 935.25,-8 840.5,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="887.88" y="-121.7" font-family="Helvetica,sans-Serif" font-size="14.00">Consumers</text>
|
||||
</g>
|
||||
<g id="clust6" class="cluster">
|
||||
<title>cluster_delivery</title>
|
||||
<polygon fill="#f3e5f5" stroke="black" points="1005.5,-8 1005.5,-85 1253.75,-85 1253.75,-8 1005.5,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1129.62" y="-67.7" font-family="Helvetica,sans-Serif" font-size="14.00">Delivery (AWS)</text>
|
||||
</g>
|
||||
<!-- psutil -->
|
||||
<g id="node1" class="node">
|
||||
<title>psutil</title>
|
||||
<polygon fill="#bbdefb" stroke="black" points="118.25,-155 16,-155 16,-151 12,-151 12,-147 16,-147 16,-127 12,-127 12,-123 16,-123 16,-119 118.25,-119 118.25,-155"/>
|
||||
<polyline fill="none" stroke="black" points="16,-151 20,-151 20,-147 16,-147"/>
|
||||
<polygon fill="#bbdefb" stroke="black" points="118.25,-131 16,-131 16,-127 12,-127 12,-123 16,-123 16,-103 12,-103 12,-99 16,-99 16,-95 118.25,-95 118.25,-131"/>
|
||||
<polyline fill="none" stroke="black" points="16,-127 20,-127 20,-123 16,-123"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="67.13" y="-140.25" font-family="Helvetica,sans-Serif" font-size="10.00">psutil</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="67.13" y="-127.5" font-family="Helvetica,sans-Serif" font-size="10.00">(CPU, Mem, Disk)</text>
|
||||
<polyline fill="none" stroke="black" points="16,-103 20,-103 20,-99 16,-99"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="67.12" y="-116.25" font-family="Helvetica,sans-Serif" font-size="10.00">psutil</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="67.12" y="-103.5" font-family="Helvetica,sans-Serif" font-size="10.00">(CPU, Mem, Disk)</text>
|
||||
</g>
|
||||
<!-- collector -->
|
||||
<g id="node2" class="node">
|
||||
<title>collector</title>
|
||||
<path fill="#90caf9" stroke="black" d="M234,-155C234,-155 198.5,-155 198.5,-155 192.5,-155 186.5,-149 186.5,-143 186.5,-143 186.5,-131 186.5,-131 186.5,-125 192.5,-119 198.5,-119 198.5,-119 234,-119 234,-119 240,-119 246,-125 246,-131 246,-131 246,-143 246,-143 246,-149 240,-155 234,-155"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="216.25" y="-140.25" font-family="Helvetica,sans-Serif" font-size="10.00">Collector</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="216.25" y="-127.5" font-family="Helvetica,sans-Serif" font-size="10.00">Service</text>
|
||||
<path fill="#90caf9" stroke="black" d="M234,-131C234,-131 198.5,-131 198.5,-131 192.5,-131 186.5,-125 186.5,-119 186.5,-119 186.5,-107 186.5,-107 186.5,-101 192.5,-95 198.5,-95 198.5,-95 234,-95 234,-95 240,-95 246,-101 246,-107 246,-107 246,-119 246,-119 246,-125 240,-131 234,-131"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="216.25" y="-116.25" font-family="Helvetica,sans-Serif" font-size="10.00">Collector</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="216.25" y="-103.5" font-family="Helvetica,sans-Serif" font-size="10.00">Service</text>
|
||||
</g>
|
||||
<!-- psutil->collector -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>psutil->collector</title>
|
||||
<path fill="none" stroke="black" d="M118.35,-137C136.74,-137 157.31,-137 174.75,-137"/>
|
||||
<polygon fill="black" stroke="black" points="174.75,-140.5 184.75,-137 174.75,-133.5 174.75,-140.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="152.38" y="-139.7" font-family="Helvetica,sans-Serif" font-size="9.00">Metrics</text>
|
||||
<path fill="none" stroke="black" d="M118.35,-113C136.74,-113 157.31,-113 174.75,-113"/>
|
||||
<polygon fill="black" stroke="black" points="174.75,-116.5 184.75,-113 174.75,-109.5 174.75,-116.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="152.38" y="-115.7" font-family="Helvetica,sans-Serif" font-size="9.00">Metrics</text>
|
||||
</g>
|
||||
<!-- aggregator -->
|
||||
<g id="node3" class="node">
|
||||
<title>aggregator</title>
|
||||
<path fill="#a5d6a7" stroke="black" d="M373,-155C373,-155 327,-155 327,-155 321,-155 315,-149 315,-143 315,-143 315,-131 315,-131 315,-125 321,-119 327,-119 327,-119 373,-119 373,-119 379,-119 385,-125 385,-131 385,-131 385,-143 385,-143 385,-149 379,-155 373,-155"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="350" y="-140.25" font-family="Helvetica,sans-Serif" font-size="10.00">Aggregator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="350" y="-127.5" font-family="Helvetica,sans-Serif" font-size="10.00">(gRPC)</text>
|
||||
<path fill="#a5d6a7" stroke="black" d="M373,-131C373,-131 327,-131 327,-131 321,-131 315,-125 315,-119 315,-119 315,-107 315,-107 315,-101 321,-95 327,-95 327,-95 373,-95 373,-95 379,-95 385,-101 385,-107 385,-107 385,-119 385,-119 385,-125 379,-131 373,-131"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="350" y="-116.25" font-family="Helvetica,sans-Serif" font-size="10.00">Aggregator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="350" y="-103.5" font-family="Helvetica,sans-Serif" font-size="10.00">(gRPC)</text>
|
||||
</g>
|
||||
<!-- collector->aggregator -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>collector->aggregator</title>
|
||||
<path fill="none" stroke="black" d="M246.49,-137C263.19,-137 284.49,-137 303.35,-137"/>
|
||||
<polygon fill="black" stroke="black" points="303.2,-140.5 313.2,-137 303.2,-133.5 303.2,-140.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="280.5" y="-150.95" font-family="Helvetica,sans-Serif" font-size="9.00">gRPC</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="280.5" y="-139.7" font-family="Helvetica,sans-Serif" font-size="9.00">Stream</text>
|
||||
<path fill="none" stroke="black" d="M246.49,-113C263.19,-113 284.49,-113 303.35,-113"/>
|
||||
<polygon fill="black" stroke="black" points="303.2,-116.5 313.2,-113 303.2,-109.5 303.2,-116.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="280.5" y="-126.95" font-family="Helvetica,sans-Serif" font-size="9.00">gRPC</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="280.5" y="-115.7" font-family="Helvetica,sans-Serif" font-size="9.00">Stream</text>
|
||||
</g>
|
||||
<!-- validate -->
|
||||
<g id="node4" class="node">
|
||||
<title>validate</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M477.54,-165.08C477.54,-165.08 432.71,-142.42 432.71,-142.42 427.35,-139.71 427.35,-134.29 432.71,-131.58 432.71,-131.58 477.54,-108.92 477.54,-108.92 482.9,-106.21 493.6,-106.21 498.96,-108.92 498.96,-108.92 543.79,-131.58 543.79,-131.58 549.15,-134.29 549.15,-139.71 543.79,-142.42 543.79,-142.42 498.96,-165.08 498.96,-165.08 493.6,-167.79 482.9,-167.79 477.54,-165.08"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="488.25" y="-140.25" font-family="Helvetica,sans-Serif" font-size="10.00">Validate &</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="488.25" y="-127.5" font-family="Helvetica,sans-Serif" font-size="10.00">Normalize</text>
|
||||
<path fill="#c8e6c9" stroke="black" d="M477.54,-141.08C477.54,-141.08 432.71,-118.42 432.71,-118.42 427.35,-115.71 427.35,-110.29 432.71,-107.58 432.71,-107.58 477.54,-84.92 477.54,-84.92 482.9,-82.21 493.6,-82.21 498.96,-84.92 498.96,-84.92 543.79,-107.58 543.79,-107.58 549.15,-110.29 549.15,-115.71 543.79,-118.42 543.79,-118.42 498.96,-141.08 498.96,-141.08 493.6,-143.79 482.9,-143.79 477.54,-141.08"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="488.25" y="-116.25" font-family="Helvetica,sans-Serif" font-size="10.00">Validate &</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="488.25" y="-103.5" font-family="Helvetica,sans-Serif" font-size="10.00">Normalize</text>
|
||||
</g>
|
||||
<!-- aggregator->validate -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>aggregator->validate</title>
|
||||
<path fill="none" stroke="black" d="M385.38,-137C392.95,-137 401.25,-137 409.76,-137"/>
|
||||
<polygon fill="black" stroke="black" points="409.49,-140.5 419.49,-137 409.49,-133.5 409.49,-140.5"/>
|
||||
<path fill="none" stroke="black" d="M385.38,-113C392.95,-113 401.25,-113 409.76,-113"/>
|
||||
<polygon fill="black" stroke="black" points="409.49,-116.5 419.49,-113 409.49,-109.5 409.49,-116.5"/>
|
||||
</g>
|
||||
<!-- redis_state -->
|
||||
<g id="node5" class="node">
|
||||
<title>redis_state</title>
|
||||
<path fill="#ffcc80" stroke="black" d="M731.88,-155.84C731.88,-158.15 713.83,-160.03 691.62,-160.03 669.42,-160.03 651.38,-158.15 651.38,-155.84 651.38,-155.84 651.38,-118.16 651.38,-118.16 651.38,-115.85 669.42,-113.97 691.62,-113.97 713.83,-113.97 731.88,-115.85 731.88,-118.16 731.88,-118.16 731.88,-155.84 731.88,-155.84"/>
|
||||
<path fill="none" stroke="black" d="M731.88,-155.84C731.88,-153.53 713.83,-151.66 691.62,-151.66 669.42,-151.66 651.38,-153.53 651.38,-155.84"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.62" y="-140.25" font-family="Helvetica,sans-Serif" font-size="10.00">Redis</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.62" y="-127.5" font-family="Helvetica,sans-Serif" font-size="10.00">Current State</text>
|
||||
<path fill="#ffcc80" stroke="black" d="M731.88,-131.84C731.88,-134.15 713.83,-136.03 691.62,-136.03 669.42,-136.03 651.38,-134.15 651.38,-131.84 651.38,-131.84 651.38,-94.16 651.38,-94.16 651.38,-91.85 669.42,-89.97 691.62,-89.97 713.83,-89.97 731.88,-91.85 731.88,-94.16 731.88,-94.16 731.88,-131.84 731.88,-131.84"/>
|
||||
<path fill="none" stroke="black" d="M731.88,-131.84C731.88,-129.53 713.83,-127.66 691.62,-127.66 669.42,-127.66 651.38,-129.53 651.38,-131.84"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.62" y="-116.25" font-family="Helvetica,sans-Serif" font-size="10.00">Redis</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.62" y="-103.5" font-family="Helvetica,sans-Serif" font-size="10.00">Current State</text>
|
||||
</g>
|
||||
<!-- validate->redis_state -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>validate->redis_state</title>
|
||||
<path fill="none" stroke="black" d="M555.47,-137C582.9,-137 614.22,-137 639.8,-137"/>
|
||||
<polygon fill="black" stroke="black" points="639.6,-140.5 649.6,-137 639.6,-133.5 639.6,-140.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="588.62" y="-139.7" font-family="Helvetica,sans-Serif" font-size="9.00">Upsert</text>
|
||||
<path fill="none" stroke="black" d="M555.47,-113C582.9,-113 614.22,-113 639.8,-113"/>
|
||||
<polygon fill="black" stroke="black" points="639.6,-116.5 649.6,-113 639.6,-109.5 639.6,-116.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="588.63" y="-115.7" font-family="Helvetica,sans-Serif" font-size="9.00">Upsert</text>
|
||||
</g>
|
||||
<!-- redis_pubsub -->
|
||||
<g id="node6" class="node">
|
||||
<title>redis_pubsub</title>
|
||||
<path fill="#ffb74d" stroke="black" d="M729.05,-78.12C729.05,-78.12 721.56,-87.24 721.56,-87.24 717.82,-91.79 708.18,-96.35 702.28,-96.35 702.28,-96.35 680.97,-96.35 680.97,-96.35 675.07,-96.35 665.43,-91.79 661.69,-87.24 661.69,-87.24 654.2,-78.12 654.2,-78.12 650.46,-73.56 650.46,-64.44 654.2,-59.88 654.2,-59.88 661.69,-50.76 661.69,-50.76 665.43,-46.21 675.07,-41.65 680.97,-41.65 680.97,-41.65 702.28,-41.65 702.28,-41.65 708.18,-41.65 717.82,-46.21 721.56,-50.76 721.56,-50.76 729.05,-59.88 729.05,-59.88 732.79,-64.44 732.79,-73.56 729.05,-78.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.62" y="-72.25" font-family="Helvetica,sans-Serif" font-size="10.00">Redis</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.62" y="-59.5" font-family="Helvetica,sans-Serif" font-size="10.00">Pub/Sub</text>
|
||||
<path fill="#ffb74d" stroke="black" d="M729.05,-54.12C729.05,-54.12 721.56,-63.24 721.56,-63.24 717.82,-67.79 708.18,-72.35 702.28,-72.35 702.28,-72.35 680.97,-72.35 680.97,-72.35 675.07,-72.35 665.43,-67.79 661.69,-63.24 661.69,-63.24 654.2,-54.12 654.2,-54.12 650.46,-49.56 650.46,-40.44 654.2,-35.88 654.2,-35.88 661.69,-26.76 661.69,-26.76 665.43,-22.21 675.07,-17.65 680.97,-17.65 680.97,-17.65 702.28,-17.65 702.28,-17.65 708.18,-17.65 717.82,-22.21 721.56,-26.76 721.56,-26.76 729.05,-35.88 729.05,-35.88 732.79,-40.44 732.79,-49.56 729.05,-54.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.62" y="-48.25" font-family="Helvetica,sans-Serif" font-size="10.00">Redis</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.62" y="-35.5" font-family="Helvetica,sans-Serif" font-size="10.00">Pub/Sub</text>
|
||||
</g>
|
||||
<!-- validate->redis_pubsub -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>validate->redis_pubsub</title>
|
||||
<path fill="none" stroke="black" d="M529.04,-123.57C562.44,-112.28 610.18,-96.17 645.1,-84.37"/>
|
||||
<polygon fill="black" stroke="black" points="646.17,-87.71 654.53,-81.19 643.93,-81.07 646.17,-87.71"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="588.62" y="-109.77" font-family="Helvetica,sans-Serif" font-size="9.00">Publish</text>
|
||||
<path fill="none" stroke="black" d="M529.04,-99.57C562.44,-88.28 610.18,-72.17 645.1,-60.37"/>
|
||||
<polygon fill="black" stroke="black" points="646.17,-63.71 654.53,-57.19 643.93,-57.07 646.17,-63.71"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="588.63" y="-85.77" font-family="Helvetica,sans-Serif" font-size="9.00">Publish</text>
|
||||
</g>
|
||||
<!-- raw -->
|
||||
<g id="node7" class="node">
|
||||
<title>raw</title>
|
||||
<path fill="#f8bbd9" stroke="black" d="M729.62,-250.84C729.62,-253.15 712.59,-255.03 691.62,-255.03 670.66,-255.03 653.62,-253.15 653.62,-250.84 653.62,-250.84 653.62,-213.16 653.62,-213.16 653.62,-210.85 670.66,-208.97 691.62,-208.97 712.59,-208.97 729.62,-210.85 729.62,-213.16 729.62,-213.16 729.62,-250.84 729.62,-250.84"/>
|
||||
<path fill="none" stroke="black" d="M729.62,-250.84C729.62,-248.53 712.59,-246.66 691.62,-246.66 670.66,-246.66 653.62,-248.53 653.62,-250.84"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.62" y="-235.25" font-family="Helvetica,sans-Serif" font-size="10.00">metrics_raw</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.62" y="-222.5" font-family="Helvetica,sans-Serif" font-size="10.00">(5s, 24h)</text>
|
||||
<path fill="#f8bbd9" stroke="black" d="M729.62,-226.84C729.62,-229.15 712.59,-231.03 691.62,-231.03 670.66,-231.03 653.62,-229.15 653.62,-226.84 653.62,-226.84 653.62,-189.16 653.62,-189.16 653.62,-186.85 670.66,-184.97 691.62,-184.97 712.59,-184.97 729.62,-186.85 729.62,-189.16 729.62,-189.16 729.62,-226.84 729.62,-226.84"/>
|
||||
<path fill="none" stroke="black" d="M729.62,-226.84C729.62,-224.53 712.59,-222.66 691.62,-222.66 670.66,-222.66 653.62,-224.53 653.62,-226.84"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.62" y="-211.25" font-family="Helvetica,sans-Serif" font-size="10.00">metrics_raw</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.62" y="-198.5" font-family="Helvetica,sans-Serif" font-size="10.00">(5s, 24h)</text>
|
||||
</g>
|
||||
<!-- validate->raw -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>validate->raw</title>
|
||||
<path fill="none" stroke="black" d="M523.01,-153.3C548.24,-165.44 583.6,-182.37 614.75,-197 623.81,-201.26 633.5,-205.76 642.83,-210.07"/>
|
||||
<polygon fill="black" stroke="black" points="641.22,-213.19 651.77,-214.2 644.16,-206.83 641.22,-213.19"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="588.62" y="-194.9" font-family="Helvetica,sans-Serif" font-size="9.00">Insert</text>
|
||||
<path fill="none" stroke="black" d="M523.01,-129.3C548.24,-141.44 583.6,-158.37 614.75,-173 623.81,-177.26 633.5,-181.76 642.83,-186.07"/>
|
||||
<polygon fill="black" stroke="black" points="641.22,-189.19 651.77,-190.2 644.16,-182.83 641.22,-189.19"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="588.63" y="-170.9" font-family="Helvetica,sans-Serif" font-size="9.00">Insert</text>
|
||||
</g>
|
||||
<!-- alerts -->
|
||||
<g id="node10" class="node">
|
||||
@@ -140,9 +145,9 @@
|
||||
<!-- redis_pubsub->alerts -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>redis_pubsub->alerts</title>
|
||||
<path fill="none" stroke="black" d="M733.71,-73.03C767.65,-76.36 815.43,-81.04 848.46,-84.28"/>
|
||||
<polygon fill="black" stroke="black" points="848.11,-87.76 858.4,-85.26 848.79,-80.8 848.11,-87.76"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="805" y="-85.09" font-family="Helvetica,sans-Serif" font-size="9.00">metrics.*</text>
|
||||
<path fill="none" stroke="black" d="M729.98,-53.29C764.26,-60.9 814.78,-72.11 849.05,-79.72"/>
|
||||
<polygon fill="black" stroke="black" points="848.01,-83.07 858.53,-81.82 849.52,-76.24 848.01,-83.07"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="805" y="-77.99" font-family="Helvetica,sans-Serif" font-size="9.00">metrics.*</text>
|
||||
</g>
|
||||
<!-- gateway -->
|
||||
<g id="node11" class="node">
|
||||
@@ -154,64 +159,70 @@
|
||||
<!-- redis_pubsub->gateway -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>redis_pubsub->gateway</title>
|
||||
<path fill="none" stroke="black" d="M731.37,-62C761.89,-56.49 804.64,-48.77 837.51,-42.83"/>
|
||||
<polygon fill="black" stroke="black" points="837.98,-46.3 847.2,-41.08 836.74,-39.41 837.98,-46.3"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="805" y="-55.25" font-family="Helvetica,sans-Serif" font-size="9.00">metrics.*</text>
|
||||
<path fill="none" stroke="black" d="M735.14,-42.59C765.3,-40.87 805.86,-38.57 837.38,-36.78"/>
|
||||
<polygon fill="black" stroke="black" points="837.25,-40.29 847.03,-36.23 836.85,-33.31 837.25,-40.29"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="805" y="-42.53" font-family="Helvetica,sans-Serif" font-size="9.00">metrics.*</text>
|
||||
</g>
|
||||
<!-- agg_1m -->
|
||||
<g id="node8" class="node">
|
||||
<title>agg_1m</title>
|
||||
<path fill="#f48fb1" stroke="black" d="M924.25,-250.84C924.25,-253.15 907.72,-255.03 887.38,-255.03 867.03,-255.03 850.5,-253.15 850.5,-250.84 850.5,-250.84 850.5,-213.16 850.5,-213.16 850.5,-210.85 867.03,-208.97 887.38,-208.97 907.72,-208.97 924.25,-210.85 924.25,-213.16 924.25,-213.16 924.25,-250.84 924.25,-250.84"/>
|
||||
<path fill="none" stroke="black" d="M924.25,-250.84C924.25,-248.53 907.72,-246.66 887.38,-246.66 867.03,-246.66 850.5,-248.53 850.5,-250.84"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="887.38" y="-235.25" font-family="Helvetica,sans-Serif" font-size="10.00">metrics_1m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="887.38" y="-222.5" font-family="Helvetica,sans-Serif" font-size="10.00">(1m, 7d)</text>
|
||||
<path fill="#f48fb1" stroke="black" d="M924.25,-226.84C924.25,-229.15 907.72,-231.03 887.38,-231.03 867.03,-231.03 850.5,-229.15 850.5,-226.84 850.5,-226.84 850.5,-189.16 850.5,-189.16 850.5,-186.85 867.03,-184.97 887.38,-184.97 907.72,-184.97 924.25,-186.85 924.25,-189.16 924.25,-189.16 924.25,-226.84 924.25,-226.84"/>
|
||||
<path fill="none" stroke="black" d="M924.25,-226.84C924.25,-224.53 907.72,-222.66 887.38,-222.66 867.03,-222.66 850.5,-224.53 850.5,-226.84"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="887.38" y="-211.25" font-family="Helvetica,sans-Serif" font-size="10.00">metrics_1m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="887.38" y="-198.5" font-family="Helvetica,sans-Serif" font-size="10.00">(1m, 7d)</text>
|
||||
</g>
|
||||
<!-- raw->agg_1m -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>raw->agg_1m</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M729.98,-232C760.97,-232 805.22,-232 838.74,-232"/>
|
||||
<polygon fill="black" stroke="black" points="838.6,-235.5 848.6,-232 838.6,-228.5 838.6,-235.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="805" y="-245.95" font-family="Helvetica,sans-Serif" font-size="9.00">Continuous</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="805" y="-234.7" font-family="Helvetica,sans-Serif" font-size="9.00">Aggregate</text>
|
||||
</g>
|
||||
<!-- lambda -->
|
||||
<g id="node12" class="node">
|
||||
<title>lambda</title>
|
||||
<path fill="#7986cb" stroke="black" stroke-dasharray="5,2" d="M910.38,-160C910.38,-160 864.38,-160 864.38,-160 858.38,-160 852.38,-154 852.38,-148 852.38,-148 852.38,-136 852.38,-136 852.38,-130 858.38,-124 864.38,-124 864.38,-124 910.38,-124 910.38,-124 916.38,-124 922.38,-130 922.38,-136 922.38,-136 922.38,-148 922.38,-148 922.38,-154 916.38,-160 910.38,-160"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="887.38" y="-145.25" font-family="Helvetica,sans-Serif" font-size="10.00">Lambda</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="887.38" y="-132.5" font-family="Helvetica,sans-Serif" font-size="10.00">Aggregator</text>
|
||||
</g>
|
||||
<!-- raw->lambda -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>raw->lambda</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M729.81,-215.18C742.43,-209.45 756.59,-202.98 769.5,-197 793.37,-185.95 819.91,-173.48 841.65,-163.21"/>
|
||||
<polygon fill="black" stroke="black" points="843,-166.44 850.54,-159.01 840,-160.12 843,-166.44"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="805" y="-205.05" font-family="Helvetica,sans-Serif" font-size="9.00">SQS</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="805" y="-193.8" font-family="Helvetica,sans-Serif" font-size="9.00">Trigger</text>
|
||||
<title>raw->agg_1m</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M729.98,-208C760.97,-208 805.22,-208 838.74,-208"/>
|
||||
<polygon fill="black" stroke="black" points="838.6,-211.5 848.6,-208 838.6,-204.5 838.6,-211.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="805" y="-221.95" font-family="Helvetica,sans-Serif" font-size="9.00">Continuous</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="805" y="-210.7" font-family="Helvetica,sans-Serif" font-size="9.00">Aggregate</text>
|
||||
</g>
|
||||
<!-- agg_1h -->
|
||||
<g id="node9" class="node">
|
||||
<title>agg_1h</title>
|
||||
<path fill="#ec407a" stroke="black" d="M1062.5,-250.84C1062.5,-253.15 1046.81,-255.03 1027.5,-255.03 1008.19,-255.03 992.5,-253.15 992.5,-250.84 992.5,-250.84 992.5,-213.16 992.5,-213.16 992.5,-210.85 1008.19,-208.97 1027.5,-208.97 1046.81,-208.97 1062.5,-210.85 1062.5,-213.16 1062.5,-213.16 1062.5,-250.84 1062.5,-250.84"/>
|
||||
<path fill="none" stroke="black" d="M1062.5,-250.84C1062.5,-248.53 1046.81,-246.66 1027.5,-246.66 1008.19,-246.66 992.5,-248.53 992.5,-250.84"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1027.5" y="-235.25" font-family="Helvetica,sans-Serif" font-size="10.00">metrics_1h</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1027.5" y="-222.5" font-family="Helvetica,sans-Serif" font-size="10.00">(1h, 90d)</text>
|
||||
<path fill="#ec407a" stroke="black" d="M1083.5,-226.84C1083.5,-229.15 1067.81,-231.03 1048.5,-231.03 1029.19,-231.03 1013.5,-229.15 1013.5,-226.84 1013.5,-226.84 1013.5,-189.16 1013.5,-189.16 1013.5,-186.85 1029.19,-184.97 1048.5,-184.97 1067.81,-184.97 1083.5,-186.85 1083.5,-189.16 1083.5,-189.16 1083.5,-226.84 1083.5,-226.84"/>
|
||||
<path fill="none" stroke="black" d="M1083.5,-226.84C1083.5,-224.53 1067.81,-222.66 1048.5,-222.66 1029.19,-222.66 1013.5,-224.53 1013.5,-226.84"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1048.5" y="-211.25" font-family="Helvetica,sans-Serif" font-size="10.00">metrics_1h</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1048.5" y="-198.5" font-family="Helvetica,sans-Serif" font-size="10.00">(1h, 90d)</text>
|
||||
</g>
|
||||
<!-- agg_1m->agg_1h -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>agg_1m->agg_1h</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M924.67,-232C941.93,-232 962.74,-232 981.04,-232"/>
|
||||
<polygon fill="black" stroke="black" points="980.84,-235.5 990.84,-232 980.84,-228.5 980.84,-235.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="959.88" y="-245.95" font-family="Helvetica,sans-Serif" font-size="9.00">Hourly</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="959.88" y="-234.7" font-family="Helvetica,sans-Serif" font-size="9.00">Job</text>
|
||||
</g>
|
||||
<!-- lambda->agg_1m -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>lambda->agg_1m</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M887.38,-160.21C887.38,-170.91 887.38,-184.78 887.38,-197.47"/>
|
||||
<polygon fill="black" stroke="black" points="883.88,-197.16 887.38,-207.16 890.88,-197.16 883.88,-197.16"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="873.12" y="-187.18" font-family="Helvetica,sans-Serif" font-size="9.00">Batch</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="873.12" y="-175.93" font-family="Helvetica,sans-Serif" font-size="9.00">Write</text>
|
||||
<title>agg_1m->agg_1h</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M924.48,-208C947.44,-208 977.36,-208 1001.94,-208"/>
|
||||
<polygon fill="black" stroke="black" points="1001.66,-211.5 1011.66,-208 1001.66,-204.5 1001.66,-211.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="970.38" y="-221.95" font-family="Helvetica,sans-Serif" font-size="9.00">Hourly</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="970.38" y="-210.7" font-family="Helvetica,sans-Serif" font-size="9.00">Job</text>
|
||||
</g>
|
||||
<!-- edge_relay -->
|
||||
<g id="node12" class="node">
|
||||
<title>edge_relay</title>
|
||||
<path fill="#e1bee7" stroke="black" d="M1071.5,-52C1071.5,-52 1025.5,-52 1025.5,-52 1019.5,-52 1013.5,-46 1013.5,-40 1013.5,-40 1013.5,-28 1013.5,-28 1013.5,-22 1019.5,-16 1025.5,-16 1025.5,-16 1071.5,-16 1071.5,-16 1077.5,-16 1083.5,-22 1083.5,-28 1083.5,-28 1083.5,-40 1083.5,-40 1083.5,-46 1077.5,-52 1071.5,-52"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1048.5" y="-37.25" font-family="Helvetica,sans-Serif" font-size="10.00">Edge</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1048.5" y="-24.5" font-family="Helvetica,sans-Serif" font-size="10.00">(WS Relay)</text>
|
||||
</g>
|
||||
<!-- gateway->edge_relay -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>gateway->edge_relay</title>
|
||||
<path fill="none" stroke="black" d="M926.09,-34C948.75,-34 977.76,-34 1001.73,-34"/>
|
||||
<polygon fill="black" stroke="black" points="1001.53,-37.5 1011.53,-34 1001.53,-30.5 1001.53,-37.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="970.38" y="-47.95" font-family="Helvetica,sans-Serif" font-size="9.00">WebSocket</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="970.38" y="-36.7" font-family="Helvetica,sans-Serif" font-size="9.00">Forward</text>
|
||||
</g>
|
||||
<!-- browser -->
|
||||
<g id="node13" class="node">
|
||||
<title>browser</title>
|
||||
<path fill="#ce93d8" stroke="black" d="M1233.75,-52C1233.75,-52 1181.75,-52 1181.75,-52 1175.75,-52 1169.75,-46 1169.75,-40 1169.75,-40 1169.75,-28 1169.75,-28 1169.75,-22 1175.75,-16 1181.75,-16 1181.75,-16 1233.75,-16 1233.75,-16 1239.75,-16 1245.75,-22 1245.75,-28 1245.75,-28 1245.75,-40 1245.75,-40 1245.75,-46 1239.75,-52 1233.75,-52"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1207.75" y="-37.25" font-family="Helvetica,sans-Serif" font-size="10.00">Browser</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1207.75" y="-24.5" font-family="Helvetica,sans-Serif" font-size="10.00">(Dashboard)</text>
|
||||
</g>
|
||||
<!-- edge_relay->browser -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>edge_relay->browser</title>
|
||||
<path fill="none" stroke="black" d="M1083.62,-34C1105.36,-34 1133.86,-34 1157.96,-34"/>
|
||||
<polygon fill="black" stroke="black" points="1157.88,-37.5 1167.88,-34 1157.88,-30.5 1157.88,-37.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1126.62" y="-36.7" font-family="Helvetica,sans-Serif" font-size="9.00">WebSocket</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 18 KiB |
@@ -11,60 +11,36 @@ digraph Deployment {
|
||||
|
||||
node [shape=box, style="rounded,filled"];
|
||||
|
||||
// Local Development
|
||||
// Local Stack
|
||||
subgraph cluster_local {
|
||||
label="Local Development";
|
||||
style=filled;
|
||||
fillcolor="#E3F2FD";
|
||||
|
||||
subgraph cluster_kind {
|
||||
label="Kind Cluster";
|
||||
style=filled;
|
||||
fillcolor="#BBDEFB";
|
||||
|
||||
tilt [label="Tilt\n(Live Reload)", shape=component, fillcolor="#90CAF9"];
|
||||
k8s_local [label="K8s Pods\n(via Kustomize)", fillcolor="#64B5F6"];
|
||||
}
|
||||
|
||||
compose [label="Docker Compose\n(Alternative)", fillcolor="#90CAF9", style="rounded,dashed"];
|
||||
}
|
||||
|
||||
// AWS Staging/Demo
|
||||
subgraph cluster_aws {
|
||||
label="AWS (sysmonstm.mcrn.ar)";
|
||||
label="Local Stack (Docker Compose)";
|
||||
style=filled;
|
||||
fillcolor="#E8F5E9";
|
||||
|
||||
subgraph cluster_ec2 {
|
||||
label="EC2 t2.small";
|
||||
style=filled;
|
||||
fillcolor="#C8E6C9";
|
||||
aggregator [label="Aggregator\n(gRPC Server)", fillcolor="#A5D6A7"];
|
||||
gateway [label="Gateway\n(FastAPI)", fillcolor="#A5D6A7"];
|
||||
alerts [label="Alerts\nService", fillcolor="#A5D6A7"];
|
||||
redis [label="Redis", shape=cylinder, fillcolor="#C8E6C9"];
|
||||
timescaledb [label="TimescaleDB", shape=cylinder, fillcolor="#C8E6C9"];
|
||||
}
|
||||
|
||||
compose_ec2 [label="Docker Compose\n(All Services)", fillcolor="#A5D6A7"];
|
||||
nginx [label="Nginx\n(SSL Termination)", fillcolor="#81C784"];
|
||||
}
|
||||
// AWS Edge
|
||||
subgraph cluster_aws {
|
||||
label="AWS (sysmonstm.mcrn.ar)";
|
||||
style=filled;
|
||||
fillcolor="#F3E5F5";
|
||||
|
||||
subgraph cluster_lambda {
|
||||
label="Lambda (Data Processing)";
|
||||
style=filled;
|
||||
fillcolor="#DCEDC8";
|
||||
|
||||
lambda_agg [label="Aggregator\nLambda", fillcolor="#AED581"];
|
||||
lambda_compact [label="Compactor\nLambda", fillcolor="#9CCC65"];
|
||||
}
|
||||
|
||||
sqs [label="SQS\n(Buffer)", shape=hexagon, fillcolor="#FFE082"];
|
||||
s3 [label="S3\n(Backup)", shape=cylinder, fillcolor="#FFE082"];
|
||||
edge_relay [label="Edge\n(WebSocket Relay)", fillcolor="#CE93D8"];
|
||||
}
|
||||
|
||||
// CI/CD
|
||||
subgraph cluster_cicd {
|
||||
label="CI/CD";
|
||||
style=filled;
|
||||
fillcolor="#F3E5F5";
|
||||
fillcolor="#E3F2FD";
|
||||
|
||||
woodpecker [label="Woodpecker CI", fillcolor="#CE93D8"];
|
||||
registry [label="Container\nRegistry", shape=cylinder, fillcolor="#BA68C8"];
|
||||
woodpecker [label="Woodpecker CI", fillcolor="#90CAF9"];
|
||||
registry [label="Container\nRegistry", shape=cylinder, fillcolor="#64B5F6"];
|
||||
}
|
||||
|
||||
// Collectors (External)
|
||||
@@ -78,18 +54,22 @@ digraph Deployment {
|
||||
coll3 [label="Collector\n(Machine N)", fillcolor="#FFCCBC"];
|
||||
}
|
||||
|
||||
// Browser
|
||||
browser [label="Browser\n(Dashboard)", fillcolor="#FFF3E0"];
|
||||
|
||||
// Connections
|
||||
tilt -> k8s_local [style=invis];
|
||||
coll1 -> aggregator [label="gRPC"];
|
||||
coll2 -> aggregator [label="gRPC"];
|
||||
coll3 -> aggregator [label="gRPC"];
|
||||
|
||||
aggregator -> redis [label="State"];
|
||||
aggregator -> timescaledb [label="Store"];
|
||||
gateway -> aggregator [label="gRPC"];
|
||||
gateway -> edge_relay [label="WebSocket\nForward"];
|
||||
|
||||
edge_relay -> browser [label="WebSocket", dir=both];
|
||||
|
||||
woodpecker -> registry [label="Push"];
|
||||
registry -> compose_ec2 [label="Pull"];
|
||||
registry -> k8s_local [label="Pull", style=dashed];
|
||||
|
||||
nginx -> compose_ec2 [label="Proxy"];
|
||||
compose_ec2 -> sqs [label="Events"];
|
||||
sqs -> lambda_agg [label="Trigger"];
|
||||
lambda_compact -> s3 [label="Archive"];
|
||||
|
||||
coll1 -> compose_ec2 [label="gRPC", lhead=cluster_ec2];
|
||||
coll2 -> compose_ec2 [label="gRPC", lhead=cluster_ec2];
|
||||
coll3 -> compose_ec2 [label="gRPC", lhead=cluster_ec2];
|
||||
registry -> edge_relay [label="Pull", style=dashed];
|
||||
registry -> aggregator [label="Pull", style=dashed, lhead=cluster_local];
|
||||
}
|
||||
|
||||
@@ -1,221 +1,197 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.1 (0)
|
||||
<!-- Generated by graphviz version 14.1.2 (0)
|
||||
-->
|
||||
<!-- Title: Deployment Pages: 1 -->
|
||||
<svg width="872pt" height="662pt"
|
||||
viewBox="0.00 0.00 872.00 662.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 658.3)">
|
||||
<svg width="743pt" height="439pt"
|
||||
viewBox="0.00 0.00 743.00 439.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 435.03)">
|
||||
<title>Deployment</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-658.3 868,-658.3 868,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="432" y="-637" font-family="Helvetica,sans-Serif" font-size="14.00">Deployment Architecture</text>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-435.03 739,-435.03 739,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="367.5" y="-413.73" font-family="Helvetica,sans-Serif" font-size="14.00">Deployment Architecture</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_local</title>
|
||||
<polygon fill="#e3f2fd" stroke="black" points="8,-307.77 8,-514.55 238,-514.55 238,-307.77 8,-307.77"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="123" y="-497.25" font-family="Helvetica,sans-Serif" font-size="14.00">Local Development</text>
|
||||
<polygon fill="#e8f5e9" stroke="black" points="292,-8 292,-291.28 518,-291.28 518,-8 292,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="405" y="-273.98" font-family="Helvetica,sans-Serif" font-size="14.00">Local Stack (Docker Compose)</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_kind</title>
|
||||
<polygon fill="#bbdefb" stroke="black" points="16,-315.77 16,-481.3 124,-481.3 124,-315.77 16,-315.77"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="70" y="-464" font-family="Helvetica,sans-Serif" font-size="14.00">Kind Cluster</text>
|
||||
<title>cluster_aws</title>
|
||||
<polygon fill="#f3e5f5" stroke="black" points="526,-91.25 526,-168.5 727,-168.5 727,-91.25 526,-91.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="626.5" y="-151.2" font-family="Helvetica,sans-Serif" font-size="14.00">AWS (sysmonstm.mcrn.ar)</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_aws</title>
|
||||
<polygon fill="#e8f5e9" stroke="black" points="642,-8 642,-514.55 856,-514.55 856,-8 642,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="749" y="-497.25" font-family="Helvetica,sans-Serif" font-size="14.00">AWS (sysmonstm.mcrn.ar)</text>
|
||||
<title>cluster_cicd</title>
|
||||
<polygon fill="#e3f2fd" stroke="black" points="531,-209 531,-397.78 635,-397.78 635,-209 531,-209"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="583" y="-380.48" font-family="Helvetica,sans-Serif" font-size="14.00">CI/CD</text>
|
||||
</g>
|
||||
<g id="clust4" class="cluster">
|
||||
<title>cluster_ec2</title>
|
||||
<polygon fill="#c8e6c9" stroke="black" points="650,-315.77 650,-481.3 768,-481.3 768,-315.77 650,-315.77"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="709" y="-464" font-family="Helvetica,sans-Serif" font-size="14.00">EC2 t2.small</text>
|
||||
</g>
|
||||
<g id="clust5" class="cluster">
|
||||
<title>cluster_lambda</title>
|
||||
<polygon fill="#dcedc8" stroke="black" points="650,-101.31 650,-178.56 848,-178.56 848,-101.31 650,-101.31"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="749" y="-161.26" font-family="Helvetica,sans-Serif" font-size="14.00">Lambda (Data Processing)</text>
|
||||
</g>
|
||||
<g id="clust6" class="cluster">
|
||||
<title>cluster_cicd</title>
|
||||
<polygon fill="#f3e5f5" stroke="black" points="246,-399.02 246,-621.05 350,-621.05 350,-399.02 246,-399.02"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="298" y="-603.75" font-family="Helvetica,sans-Serif" font-size="14.00">CI/CD</text>
|
||||
</g>
|
||||
<g id="clust7" class="cluster">
|
||||
<title>cluster_collectors</title>
|
||||
<polygon fill="none" stroke="gray" stroke-dasharray="5,2" points="358,-404.05 358,-481.3 634,-481.3 634,-404.05 358,-404.05"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="496" y="-464" font-family="Helvetica,sans-Serif" font-size="14.00">Monitored Machines</text>
|
||||
<polygon fill="none" stroke="gray" stroke-dasharray="5,2" points="8,-214.03 8,-291.28 284,-291.28 284,-214.03 8,-214.03"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="146" y="-273.98" font-family="Helvetica,sans-Serif" font-size="14.00">Monitored Machines</text>
|
||||
</g>
|
||||
<!-- tilt -->
|
||||
<!-- aggregator -->
|
||||
<g id="node1" class="node">
|
||||
<title>tilt</title>
|
||||
<polygon fill="#90caf9" stroke="black" points="110.25,-448.05 29.75,-448.05 29.75,-444.05 25.75,-444.05 25.75,-440.05 29.75,-440.05 29.75,-420.05 25.75,-420.05 25.75,-416.05 29.75,-416.05 29.75,-412.05 110.25,-412.05 110.25,-448.05"/>
|
||||
<polyline fill="none" stroke="black" points="29.75,-444.05 33.75,-444.05 33.75,-440.05 29.75,-440.05"/>
|
||||
<polyline fill="none" stroke="black" points="29.75,-420.05 33.75,-420.05 33.75,-416.05 29.75,-416.05"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="70" y="-433.3" font-family="Helvetica,sans-Serif" font-size="10.00">Tilt</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="70" y="-420.55" font-family="Helvetica,sans-Serif" font-size="10.00">(Live Reload)</text>
|
||||
<title>aggregator</title>
|
||||
<path fill="#a5d6a7" stroke="black" d="M371.75,-135.25C371.75,-135.25 312.25,-135.25 312.25,-135.25 306.25,-135.25 300.25,-129.25 300.25,-123.25 300.25,-123.25 300.25,-111.25 300.25,-111.25 300.25,-105.25 306.25,-99.25 312.25,-99.25 312.25,-99.25 371.75,-99.25 371.75,-99.25 377.75,-99.25 383.75,-105.25 383.75,-111.25 383.75,-111.25 383.75,-123.25 383.75,-123.25 383.75,-129.25 377.75,-135.25 371.75,-135.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="342" y="-120.5" font-family="Helvetica,sans-Serif" font-size="10.00">Aggregator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="342" y="-107.75" font-family="Helvetica,sans-Serif" font-size="10.00">(gRPC Server)</text>
|
||||
</g>
|
||||
<!-- k8s_local -->
|
||||
<g id="node2" class="node">
|
||||
<title>k8s_local</title>
|
||||
<path fill="#64b5f6" stroke="black" d="M104.25,-359.77C104.25,-359.77 35.75,-359.77 35.75,-359.77 29.75,-359.77 23.75,-353.77 23.75,-347.77 23.75,-347.77 23.75,-335.77 23.75,-335.77 23.75,-329.77 29.75,-323.77 35.75,-323.77 35.75,-323.77 104.25,-323.77 104.25,-323.77 110.25,-323.77 116.25,-329.77 116.25,-335.77 116.25,-335.77 116.25,-347.77 116.25,-347.77 116.25,-353.77 110.25,-359.77 104.25,-359.77"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="70" y="-345.02" font-family="Helvetica,sans-Serif" font-size="10.00">K8s Pods</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="70" y="-332.27" font-family="Helvetica,sans-Serif" font-size="10.00">(via Kustomize)</text>
|
||||
</g>
|
||||
<!-- tilt->k8s_local -->
|
||||
<!-- compose -->
|
||||
<g id="node3" class="node">
|
||||
<title>compose</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M218.25,-448.05C218.25,-448.05 143.75,-448.05 143.75,-448.05 137.75,-448.05 131.75,-442.05 131.75,-436.05 131.75,-436.05 131.75,-424.05 131.75,-424.05 131.75,-418.05 137.75,-412.05 143.75,-412.05 143.75,-412.05 218.25,-412.05 218.25,-412.05 224.25,-412.05 230.25,-418.05 230.25,-424.05 230.25,-424.05 230.25,-436.05 230.25,-436.05 230.25,-442.05 224.25,-448.05 218.25,-448.05"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="181" y="-433.3" font-family="Helvetica,sans-Serif" font-size="10.00">Docker Compose</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="181" y="-420.55" font-family="Helvetica,sans-Serif" font-size="10.00">(Alternative)</text>
|
||||
</g>
|
||||
<!-- compose_ec2 -->
|
||||
<!-- redis -->
|
||||
<g id="node4" class="node">
|
||||
<title>compose_ec2</title>
|
||||
<path fill="#a5d6a7" stroke="black" d="M744.25,-359.77C744.25,-359.77 669.75,-359.77 669.75,-359.77 663.75,-359.77 657.75,-353.77 657.75,-347.77 657.75,-347.77 657.75,-335.77 657.75,-335.77 657.75,-329.77 663.75,-323.77 669.75,-323.77 669.75,-323.77 744.25,-323.77 744.25,-323.77 750.25,-323.77 756.25,-329.77 756.25,-335.77 756.25,-335.77 756.25,-347.77 756.25,-347.77 756.25,-353.77 750.25,-359.77 744.25,-359.77"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="707" y="-345.02" font-family="Helvetica,sans-Serif" font-size="10.00">Docker Compose</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="707" y="-332.27" font-family="Helvetica,sans-Serif" font-size="10.00">(All Services)</text>
|
||||
<title>redis</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M361,-48.73C361,-50.53 348.9,-52 334,-52 319.1,-52 307,-50.53 307,-48.73 307,-48.73 307,-19.27 307,-19.27 307,-17.47 319.1,-16 334,-16 348.9,-16 361,-17.47 361,-19.27 361,-19.27 361,-48.73 361,-48.73"/>
|
||||
<path fill="none" stroke="black" d="M361,-48.73C361,-46.92 348.9,-45.45 334,-45.45 319.1,-45.45 307,-46.92 307,-48.73"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="334" y="-30.88" font-family="Helvetica,sans-Serif" font-size="10.00">Redis</text>
|
||||
</g>
|
||||
<!-- sqs -->
|
||||
<g id="node8" class="node">
|
||||
<title>sqs</title>
|
||||
<path fill="#ffe082" stroke="black" d="M742.89,-252.28C742.89,-252.28 735.71,-261.4 735.71,-261.4 732.12,-265.96 722.73,-270.52 716.93,-270.52 716.93,-270.52 697.07,-270.52 697.07,-270.52 691.27,-270.52 681.88,-265.96 678.29,-261.4 678.29,-261.4 671.11,-252.28 671.11,-252.28 667.52,-247.72 667.52,-238.61 671.11,-234.05 671.11,-234.05 678.29,-224.93 678.29,-224.93 681.88,-220.37 691.27,-215.81 697.07,-215.81 697.07,-215.81 716.93,-215.81 716.93,-215.81 722.73,-215.81 732.12,-220.37 735.71,-224.93 735.71,-224.93 742.89,-234.05 742.89,-234.05 746.48,-238.61 746.48,-247.72 742.89,-252.28"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="707" y="-246.42" font-family="Helvetica,sans-Serif" font-size="10.00">SQS</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="707" y="-233.67" font-family="Helvetica,sans-Serif" font-size="10.00">(Buffer)</text>
|
||||
<!-- aggregator->redis -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>aggregator->redis</title>
|
||||
<path fill="none" stroke="black" d="M340.3,-99.02C339.29,-88.75 337.98,-75.45 336.82,-63.64"/>
|
||||
<polygon fill="black" stroke="black" points="340.33,-63.6 335.87,-53.99 333.37,-64.29 340.33,-63.6"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="350.48" y="-72.7" font-family="Helvetica,sans-Serif" font-size="9.00">State</text>
|
||||
</g>
|
||||
<!-- compose_ec2->sqs -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>compose_ec2->sqs</title>
|
||||
<path fill="none" stroke="black" d="M707,-323.5C707,-311.94 707,-296.26 707,-281.89"/>
|
||||
<polygon fill="black" stroke="black" points="710.5,-282.27 707,-272.27 703.5,-282.27 710.5,-282.27"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="722.38" y="-291.22" font-family="Helvetica,sans-Serif" font-size="9.00">Events</text>
|
||||
</g>
|
||||
<!-- nginx -->
|
||||
<!-- timescaledb -->
|
||||
<g id="node5" class="node">
|
||||
<title>nginx</title>
|
||||
<path fill="#81c784" stroke="black" d="M747.75,-448.05C747.75,-448.05 670.25,-448.05 670.25,-448.05 664.25,-448.05 658.25,-442.05 658.25,-436.05 658.25,-436.05 658.25,-424.05 658.25,-424.05 658.25,-418.05 664.25,-412.05 670.25,-412.05 670.25,-412.05 747.75,-412.05 747.75,-412.05 753.75,-412.05 759.75,-418.05 759.75,-424.05 759.75,-424.05 759.75,-436.05 759.75,-436.05 759.75,-442.05 753.75,-448.05 747.75,-448.05"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="709" y="-433.3" font-family="Helvetica,sans-Serif" font-size="10.00">Nginx</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="709" y="-420.55" font-family="Helvetica,sans-Serif" font-size="10.00">(SSL Termination)</text>
|
||||
<title>timescaledb</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M459.25,-48.73C459.25,-50.53 441.21,-52 419,-52 396.79,-52 378.75,-50.53 378.75,-48.73 378.75,-48.73 378.75,-19.27 378.75,-19.27 378.75,-17.47 396.79,-16 419,-16 441.21,-16 459.25,-17.47 459.25,-19.27 459.25,-19.27 459.25,-48.73 459.25,-48.73"/>
|
||||
<path fill="none" stroke="black" d="M459.25,-48.73C459.25,-46.92 441.21,-45.45 419,-45.45 396.79,-45.45 378.75,-46.92 378.75,-48.73"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="419" y="-30.88" font-family="Helvetica,sans-Serif" font-size="10.00">TimescaleDB</text>
|
||||
</g>
|
||||
<!-- nginx->compose_ec2 -->
|
||||
<!-- aggregator->timescaledb -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>nginx->compose_ec2</title>
|
||||
<path fill="none" stroke="black" d="M708.6,-411.59C708.33,-400.13 707.98,-384.86 707.67,-371.63"/>
|
||||
<polygon fill="black" stroke="black" points="711.17,-371.63 707.44,-361.72 704.17,-371.79 711.17,-371.63"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="720.43" y="-380.47" font-family="Helvetica,sans-Serif" font-size="9.00">Proxy</text>
|
||||
<title>aggregator->timescaledb</title>
|
||||
<path fill="none" stroke="black" d="M358.33,-99.02C368.88,-87.89 382.79,-73.21 394.63,-60.72"/>
|
||||
<polygon fill="black" stroke="black" points="397.05,-63.25 401.39,-53.58 391.97,-58.44 397.05,-63.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="397.11" y="-72.7" font-family="Helvetica,sans-Serif" font-size="9.00">Store</text>
|
||||
</g>
|
||||
<!-- lambda_agg -->
|
||||
<!-- gateway -->
|
||||
<g id="node2" class="node">
|
||||
<title>gateway</title>
|
||||
<path fill="#a5d6a7" stroke="black" d="M383.75,-258.03C383.75,-258.03 348.25,-258.03 348.25,-258.03 342.25,-258.03 336.25,-252.03 336.25,-246.03 336.25,-246.03 336.25,-234.03 336.25,-234.03 336.25,-228.03 342.25,-222.03 348.25,-222.03 348.25,-222.03 383.75,-222.03 383.75,-222.03 389.75,-222.03 395.75,-228.03 395.75,-234.03 395.75,-234.03 395.75,-246.03 395.75,-246.03 395.75,-252.03 389.75,-258.03 383.75,-258.03"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="366" y="-243.28" font-family="Helvetica,sans-Serif" font-size="10.00">Gateway</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="366" y="-230.53" font-family="Helvetica,sans-Serif" font-size="10.00">(FastAPI)</text>
|
||||
</g>
|
||||
<!-- gateway->aggregator -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>gateway->aggregator</title>
|
||||
<path fill="none" stroke="black" d="M362.56,-221.73C358.68,-202.17 352.29,-170.05 347.67,-146.77"/>
|
||||
<polygon fill="black" stroke="black" points="351.11,-146.13 345.73,-137.01 344.24,-147.5 351.11,-146.13"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="369.18" y="-184.82" font-family="Helvetica,sans-Serif" font-size="9.00">gRPC</text>
|
||||
</g>
|
||||
<!-- edge_relay -->
|
||||
<g id="node6" class="node">
|
||||
<title>lambda_agg</title>
|
||||
<path fill="#aed581" stroke="black" d="M730,-145.31C730,-145.31 684,-145.31 684,-145.31 678,-145.31 672,-139.31 672,-133.31 672,-133.31 672,-121.31 672,-121.31 672,-115.31 678,-109.31 684,-109.31 684,-109.31 730,-109.31 730,-109.31 736,-109.31 742,-115.31 742,-121.31 742,-121.31 742,-133.31 742,-133.31 742,-139.31 736,-145.31 730,-145.31"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="707" y="-130.56" font-family="Helvetica,sans-Serif" font-size="10.00">Aggregator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="707" y="-117.81" font-family="Helvetica,sans-Serif" font-size="10.00">Lambda</text>
|
||||
<title>edge_relay</title>
|
||||
<path fill="#ce93d8" stroke="black" d="M629.75,-135.25C629.75,-135.25 546.25,-135.25 546.25,-135.25 540.25,-135.25 534.25,-129.25 534.25,-123.25 534.25,-123.25 534.25,-111.25 534.25,-111.25 534.25,-105.25 540.25,-99.25 546.25,-99.25 546.25,-99.25 629.75,-99.25 629.75,-99.25 635.75,-99.25 641.75,-105.25 641.75,-111.25 641.75,-111.25 641.75,-123.25 641.75,-123.25 641.75,-129.25 635.75,-135.25 629.75,-135.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="588" y="-120.5" font-family="Helvetica,sans-Serif" font-size="10.00">Edge</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="588" y="-107.75" font-family="Helvetica,sans-Serif" font-size="10.00">(WebSocket Relay)</text>
|
||||
</g>
|
||||
<!-- lambda_compact -->
|
||||
<g id="node7" class="node">
|
||||
<title>lambda_compact</title>
|
||||
<path fill="#9ccc65" stroke="black" d="M822.62,-145.31C822.62,-145.31 777.38,-145.31 777.38,-145.31 771.38,-145.31 765.38,-139.31 765.38,-133.31 765.38,-133.31 765.38,-121.31 765.38,-121.31 765.38,-115.31 771.38,-109.31 777.38,-109.31 777.38,-109.31 822.62,-109.31 822.62,-109.31 828.62,-109.31 834.62,-115.31 834.62,-121.31 834.62,-121.31 834.62,-133.31 834.62,-133.31 834.62,-139.31 828.62,-145.31 822.62,-145.31"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="800" y="-130.56" font-family="Helvetica,sans-Serif" font-size="10.00">Compactor</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="800" y="-117.81" font-family="Helvetica,sans-Serif" font-size="10.00">Lambda</text>
|
||||
</g>
|
||||
<!-- s3 -->
|
||||
<g id="node9" class="node">
|
||||
<title>s3</title>
|
||||
<path fill="#ffe082" stroke="black" d="M829.38,-57.88C829.38,-60.19 816.21,-62.06 800,-62.06 783.79,-62.06 770.62,-60.19 770.62,-57.88 770.62,-57.88 770.62,-20.19 770.62,-20.19 770.62,-17.88 783.79,-16 800,-16 816.21,-16 829.38,-17.88 829.38,-20.19 829.38,-20.19 829.38,-57.88 829.38,-57.88"/>
|
||||
<path fill="none" stroke="black" d="M829.38,-57.88C829.38,-55.56 816.21,-53.69 800,-53.69 783.79,-53.69 770.62,-55.56 770.62,-57.88"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="800" y="-42.28" font-family="Helvetica,sans-Serif" font-size="10.00">S3</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="800" y="-29.53" font-family="Helvetica,sans-Serif" font-size="10.00">(Backup)</text>
|
||||
</g>
|
||||
<!-- lambda_compact->s3 -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>lambda_compact->s3</title>
|
||||
<path fill="none" stroke="black" d="M800,-108.85C800,-98.81 800,-85.84 800,-73.88"/>
|
||||
<polygon fill="black" stroke="black" points="803.5,-73.9 800,-63.9 796.5,-73.9 803.5,-73.9"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="816.88" y="-82.76" font-family="Helvetica,sans-Serif" font-size="9.00">Archive</text>
|
||||
</g>
|
||||
<!-- sqs->lambda_agg -->
|
||||
<!-- gateway->edge_relay -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>sqs->lambda_agg</title>
|
||||
<path fill="none" stroke="black" d="M707,-215.47C707,-197.96 707,-175.06 707,-157.13"/>
|
||||
<polygon fill="black" stroke="black" points="710.5,-157.15 707,-147.15 703.5,-157.15 710.5,-157.15"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="722.75" y="-189.26" font-family="Helvetica,sans-Serif" font-size="9.00">Trigger</text>
|
||||
<title>gateway->edge_relay</title>
|
||||
<path fill="none" stroke="black" d="M384.8,-221.53C401.73,-206.88 428,-186.76 454.75,-176.5 482.85,-165.73 494.1,-179.79 522,-168.5 536.54,-162.62 550.65,-152.65 562.07,-143.13"/>
|
||||
<polygon fill="black" stroke="black" points="564.23,-145.89 569.46,-136.68 559.62,-140.62 564.23,-145.89"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="479.88" y="-190.45" font-family="Helvetica,sans-Serif" font-size="9.00">WebSocket</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="479.88" y="-179.2" font-family="Helvetica,sans-Serif" font-size="9.00">Forward</text>
|
||||
</g>
|
||||
<!-- alerts -->
|
||||
<g id="node3" class="node">
|
||||
<title>alerts</title>
|
||||
<path fill="#a5d6a7" stroke="black" d="M489,-258.03C489,-258.03 459,-258.03 459,-258.03 453,-258.03 447,-252.03 447,-246.03 447,-246.03 447,-234.03 447,-234.03 447,-228.03 453,-222.03 459,-222.03 459,-222.03 489,-222.03 489,-222.03 495,-222.03 501,-228.03 501,-234.03 501,-234.03 501,-246.03 501,-246.03 501,-252.03 495,-258.03 489,-258.03"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="474" y="-243.28" font-family="Helvetica,sans-Serif" font-size="10.00">Alerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="474" y="-230.53" font-family="Helvetica,sans-Serif" font-size="10.00">Service</text>
|
||||
</g>
|
||||
<!-- browser -->
|
||||
<g id="node12" class="node">
|
||||
<title>browser</title>
|
||||
<path fill="#fff3e0" stroke="black" d="M614,-52C614,-52 562,-52 562,-52 556,-52 550,-46 550,-40 550,-40 550,-28 550,-28 550,-22 556,-16 562,-16 562,-16 614,-16 614,-16 620,-16 626,-22 626,-28 626,-28 626,-40 626,-40 626,-46 620,-52 614,-52"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="588" y="-37.25" font-family="Helvetica,sans-Serif" font-size="10.00">Browser</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="588" y="-24.5" font-family="Helvetica,sans-Serif" font-size="10.00">(Dashboard)</text>
|
||||
</g>
|
||||
<!-- edge_relay->browser -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>edge_relay->browser</title>
|
||||
<path fill="none" stroke="black" d="M588,-87.54C588,-79.86 588,-71.56 588,-63.88"/>
|
||||
<polygon fill="black" stroke="black" points="584.5,-87.51 588,-97.51 591.5,-87.51 584.5,-87.51"/>
|
||||
<polygon fill="black" stroke="black" points="591.5,-64 588,-54 584.5,-64 591.5,-64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="613.12" y="-72.7" font-family="Helvetica,sans-Serif" font-size="9.00">WebSocket</text>
|
||||
</g>
|
||||
<!-- woodpecker -->
|
||||
<g id="node10" class="node">
|
||||
<g id="node7" class="node">
|
||||
<title>woodpecker</title>
|
||||
<path fill="#ce93d8" stroke="black" d="M330,-587.8C330,-587.8 266,-587.8 266,-587.8 260,-587.8 254,-581.8 254,-575.8 254,-575.8 254,-563.8 254,-563.8 254,-557.8 260,-551.8 266,-551.8 266,-551.8 330,-551.8 330,-551.8 336,-551.8 342,-557.8 342,-563.8 342,-563.8 342,-575.8 342,-575.8 342,-581.8 336,-587.8 330,-587.8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="298" y="-566.67" font-family="Helvetica,sans-Serif" font-size="10.00">Woodpecker CI</text>
|
||||
<path fill="#90caf9" stroke="black" d="M615,-364.53C615,-364.53 551,-364.53 551,-364.53 545,-364.53 539,-358.53 539,-352.53 539,-352.53 539,-340.53 539,-340.53 539,-334.53 545,-328.53 551,-328.53 551,-328.53 615,-328.53 615,-328.53 621,-328.53 627,-334.53 627,-340.53 627,-340.53 627,-352.53 627,-352.53 627,-358.53 621,-364.53 615,-364.53"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="583" y="-343.41" font-family="Helvetica,sans-Serif" font-size="10.00">Woodpecker CI</text>
|
||||
</g>
|
||||
<!-- registry -->
|
||||
<g id="node11" class="node">
|
||||
<g id="node8" class="node">
|
||||
<title>registry</title>
|
||||
<path fill="#ba68c8" stroke="black" d="M329.62,-448.89C329.62,-451.2 315.45,-453.08 298,-453.08 280.55,-453.08 266.38,-451.2 266.38,-448.89 266.38,-448.89 266.38,-411.21 266.38,-411.21 266.38,-408.89 280.55,-407.02 298,-407.02 315.45,-407.02 329.62,-408.89 329.62,-411.21 329.62,-411.21 329.62,-448.89 329.62,-448.89"/>
|
||||
<path fill="none" stroke="black" d="M329.62,-448.89C329.62,-446.58 315.45,-444.71 298,-444.71 280.55,-444.71 266.38,-446.58 266.38,-448.89"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="298" y="-433.3" font-family="Helvetica,sans-Serif" font-size="10.00">Container</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="298" y="-420.55" font-family="Helvetica,sans-Serif" font-size="10.00">Registry</text>
|
||||
<path fill="#64b5f6" stroke="black" d="M614.62,-258.88C614.62,-261.19 600.45,-263.06 583,-263.06 565.55,-263.06 551.38,-261.19 551.38,-258.88 551.38,-258.88 551.38,-221.19 551.38,-221.19 551.38,-218.88 565.55,-217 583,-217 600.45,-217 614.62,-218.88 614.62,-221.19 614.62,-221.19 614.62,-258.88 614.62,-258.88"/>
|
||||
<path fill="none" stroke="black" d="M614.62,-258.88C614.62,-256.56 600.45,-254.69 583,-254.69 565.55,-254.69 551.38,-256.56 551.38,-258.88"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="583" y="-243.28" font-family="Helvetica,sans-Serif" font-size="10.00">Container</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="583" y="-230.53" font-family="Helvetica,sans-Serif" font-size="10.00">Registry</text>
|
||||
</g>
|
||||
<!-- woodpecker->registry -->
|
||||
<g id="edge2" class="edge">
|
||||
<g id="edge9" class="edge">
|
||||
<title>woodpecker->registry</title>
|
||||
<path fill="none" stroke="black" d="M298,-551.35C298,-529.66 298,-492.15 298,-464.77"/>
|
||||
<polygon fill="black" stroke="black" points="301.5,-464.88 298,-454.88 294.5,-464.88 301.5,-464.88"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="308.88" y="-525.25" font-family="Helvetica,sans-Serif" font-size="9.00">Push</text>
|
||||
<path fill="none" stroke="black" d="M583,-328.28C583,-313.79 583,-292.67 583,-274.84"/>
|
||||
<polygon fill="black" stroke="black" points="586.5,-274.93 583,-264.93 579.5,-274.93 586.5,-274.93"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="593.88" y="-301.98" font-family="Helvetica,sans-Serif" font-size="9.00">Push</text>
|
||||
</g>
|
||||
<!-- registry->k8s_local -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>registry->k8s_local</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M265.9,-410.59C258.2,-406.51 249.91,-402.4 242,-399.02 204.6,-383.02 161.03,-368.81 127.1,-358.68"/>
|
||||
<polygon fill="black" stroke="black" points="128.47,-355.44 117.89,-355.97 126.49,-362.15 128.47,-355.44"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="222.42" y="-380.47" font-family="Helvetica,sans-Serif" font-size="9.00">Pull</text>
|
||||
<!-- registry->aggregator -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>registry->aggregator</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M560.24,-217.39C550.98,-209.15 539.58,-199.63 527.42,-190.91"/>
|
||||
<polygon fill="black" stroke="black" points="529.47,-188.06 519.24,-185.28 525.5,-193.83 529.47,-188.06"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="544.69" y="-184.82" font-family="Helvetica,sans-Serif" font-size="9.00">Pull</text>
|
||||
</g>
|
||||
<!-- registry->compose_ec2 -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>registry->compose_ec2</title>
|
||||
<path fill="none" stroke="black" d="M329.84,-409.93C337.55,-405.88 345.91,-401.95 354,-399.02 452.44,-363.35 574.46,-350.26 646.22,-345.49"/>
|
||||
<polygon fill="black" stroke="black" points="646.02,-349.01 655.78,-344.88 645.58,-342.02 646.02,-349.01"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="427.09" y="-380.47" font-family="Helvetica,sans-Serif" font-size="9.00">Pull</text>
|
||||
<!-- registry->edge_relay -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>registry->edge_relay</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M583.93,-216.6C584.74,-196.89 585.94,-168.11 586.82,-146.77"/>
|
||||
<polygon fill="black" stroke="black" points="590.31,-147.14 587.22,-137 583.31,-146.85 590.31,-147.14"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="593.38" y="-184.82" font-family="Helvetica,sans-Serif" font-size="9.00">Pull</text>
|
||||
</g>
|
||||
<!-- coll1 -->
|
||||
<g id="node12" class="node">
|
||||
<g id="node9" class="node">
|
||||
<title>coll1</title>
|
||||
<path fill="#ffccbc" stroke="black" d="M521.88,-448.05C521.88,-448.05 472.12,-448.05 472.12,-448.05 466.12,-448.05 460.12,-442.05 460.12,-436.05 460.12,-436.05 460.12,-424.05 460.12,-424.05 460.12,-418.05 466.12,-412.05 472.12,-412.05 472.12,-412.05 521.88,-412.05 521.88,-412.05 527.88,-412.05 533.88,-418.05 533.88,-424.05 533.88,-424.05 533.88,-436.05 533.88,-436.05 533.88,-442.05 527.88,-448.05 521.88,-448.05"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="497" y="-433.3" font-family="Helvetica,sans-Serif" font-size="10.00">Collector</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="497" y="-420.55" font-family="Helvetica,sans-Serif" font-size="10.00">(Machine 1)</text>
|
||||
<path fill="#ffccbc" stroke="black" d="M263.88,-258.03C263.88,-258.03 214.12,-258.03 214.12,-258.03 208.12,-258.03 202.12,-252.03 202.12,-246.03 202.12,-246.03 202.12,-234.03 202.12,-234.03 202.12,-228.03 208.12,-222.03 214.12,-222.03 214.12,-222.03 263.88,-222.03 263.88,-222.03 269.88,-222.03 275.88,-228.03 275.88,-234.03 275.88,-234.03 275.88,-246.03 275.88,-246.03 275.88,-252.03 269.88,-258.03 263.88,-258.03"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="239" y="-243.28" font-family="Helvetica,sans-Serif" font-size="10.00">Collector</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="239" y="-230.53" font-family="Helvetica,sans-Serif" font-size="10.00">(Machine 1)</text>
|
||||
</g>
|
||||
<!-- coll1->compose_ec2 -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>coll1->compose_ec2</title>
|
||||
<path fill="none" stroke="black" d="M521.16,-411.67C528.02,-407.19 535.63,-402.62 543,-399.02 576.02,-382.89 614.85,-369.35 646.44,-359.6"/>
|
||||
<polygon fill="black" stroke="black" points="640.37,-365.52 648.58,-358.82 637.98,-358.94 640.37,-365.52"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="602.75" y="-380.47" font-family="Helvetica,sans-Serif" font-size="9.00">gRPC</text>
|
||||
<!-- coll1->aggregator -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>coll1->aggregator</title>
|
||||
<path fill="none" stroke="black" d="M253.76,-221.73C271.04,-201.46 299.85,-167.67 319.83,-144.25"/>
|
||||
<polygon fill="black" stroke="black" points="322.46,-146.55 326.29,-136.67 317.14,-142.01 322.46,-146.55"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="302.12" y="-184.82" font-family="Helvetica,sans-Serif" font-size="9.00">gRPC</text>
|
||||
</g>
|
||||
<!-- coll2 -->
|
||||
<g id="node13" class="node">
|
||||
<g id="node10" class="node">
|
||||
<title>coll2</title>
|
||||
<path fill="#ffccbc" stroke="black" d="M613.88,-448.05C613.88,-448.05 564.12,-448.05 564.12,-448.05 558.12,-448.05 552.12,-442.05 552.12,-436.05 552.12,-436.05 552.12,-424.05 552.12,-424.05 552.12,-418.05 558.12,-412.05 564.12,-412.05 564.12,-412.05 613.88,-412.05 613.88,-412.05 619.88,-412.05 625.88,-418.05 625.88,-424.05 625.88,-424.05 625.88,-436.05 625.88,-436.05 625.88,-442.05 619.88,-448.05 613.88,-448.05"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="589" y="-433.3" font-family="Helvetica,sans-Serif" font-size="10.00">Collector</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="589" y="-420.55" font-family="Helvetica,sans-Serif" font-size="10.00">(Machine 2)</text>
|
||||
<path fill="#ffccbc" stroke="black" d="M77.88,-258.03C77.88,-258.03 28.12,-258.03 28.12,-258.03 22.12,-258.03 16.12,-252.03 16.12,-246.03 16.12,-246.03 16.12,-234.03 16.12,-234.03 16.12,-228.03 22.12,-222.03 28.12,-222.03 28.12,-222.03 77.88,-222.03 77.88,-222.03 83.88,-222.03 89.88,-228.03 89.88,-234.03 89.88,-234.03 89.88,-246.03 89.88,-246.03 89.88,-252.03 83.88,-258.03 77.88,-258.03"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="53" y="-243.28" font-family="Helvetica,sans-Serif" font-size="10.00">Collector</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="53" y="-230.53" font-family="Helvetica,sans-Serif" font-size="10.00">(Machine 2)</text>
|
||||
</g>
|
||||
<!-- coll2->compose_ec2 -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>coll2->compose_ec2</title>
|
||||
<path fill="none" stroke="black" d="M612.88,-411.59C621.13,-405.55 630.83,-398.47 640.8,-391.17"/>
|
||||
<polygon fill="black" stroke="black" points="642.77,-394.07 648.78,-385.34 638.64,-388.41 642.77,-394.07"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="670.19" y="-380.47" font-family="Helvetica,sans-Serif" font-size="9.00">gRPC</text>
|
||||
<!-- coll2->aggregator -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>coll2->aggregator</title>
|
||||
<path fill="none" stroke="black" d="M77.23,-221.79C84.09,-217.31 91.68,-212.7 99,-209 161.95,-177.15 238.85,-150.3 289.05,-134.25"/>
|
||||
<polygon fill="black" stroke="black" points="290.05,-137.61 298.53,-131.26 287.94,-130.94 290.05,-137.61"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="182.04" y="-184.82" font-family="Helvetica,sans-Serif" font-size="9.00">gRPC</text>
|
||||
</g>
|
||||
<!-- coll3 -->
|
||||
<g id="node14" class="node">
|
||||
<g id="node11" class="node">
|
||||
<title>coll3</title>
|
||||
<path fill="#ffccbc" stroke="black" d="M429.62,-448.05C429.62,-448.05 378.38,-448.05 378.38,-448.05 372.38,-448.05 366.38,-442.05 366.38,-436.05 366.38,-436.05 366.38,-424.05 366.38,-424.05 366.38,-418.05 372.38,-412.05 378.38,-412.05 378.38,-412.05 429.62,-412.05 429.62,-412.05 435.62,-412.05 441.62,-418.05 441.62,-424.05 441.62,-424.05 441.62,-436.05 441.62,-436.05 441.62,-442.05 435.62,-448.05 429.62,-448.05"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="404" y="-433.3" font-family="Helvetica,sans-Serif" font-size="10.00">Collector</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="404" y="-420.55" font-family="Helvetica,sans-Serif" font-size="10.00">(Machine N)</text>
|
||||
<path fill="#ffccbc" stroke="black" d="M171.62,-258.03C171.62,-258.03 120.38,-258.03 120.38,-258.03 114.38,-258.03 108.38,-252.03 108.38,-246.03 108.38,-246.03 108.38,-234.03 108.38,-234.03 108.38,-228.03 114.38,-222.03 120.38,-222.03 120.38,-222.03 171.62,-222.03 171.62,-222.03 177.62,-222.03 183.62,-228.03 183.62,-234.03 183.62,-234.03 183.62,-246.03 183.62,-246.03 183.62,-252.03 177.62,-258.03 171.62,-258.03"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="146" y="-243.28" font-family="Helvetica,sans-Serif" font-size="10.00">Collector</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="146" y="-230.53" font-family="Helvetica,sans-Serif" font-size="10.00">(Machine N)</text>
|
||||
</g>
|
||||
<!-- coll3->compose_ec2 -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>coll3->compose_ec2</title>
|
||||
<path fill="none" stroke="black" d="M427.53,-411.82C434.78,-407.12 442.97,-402.41 451,-399.02 514.86,-372.07 593.36,-357.28 646.47,-349.71"/>
|
||||
<polygon fill="black" stroke="black" points="639.16,-354.39 648.5,-349.4 638.08,-347.48 639.16,-354.39"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="516.54" y="-380.47" font-family="Helvetica,sans-Serif" font-size="9.00">gRPC</text>
|
||||
<!-- coll3->aggregator -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>coll3->aggregator</title>
|
||||
<path fill="none" stroke="black" d="M172.78,-221.78C179.37,-217.57 186.43,-213.1 193,-209 230.29,-185.74 273.17,-159.69 303.33,-141.49"/>
|
||||
<polygon fill="black" stroke="black" points="304.99,-144.58 311.75,-136.42 301.38,-138.58 304.99,-144.58"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="253.61" y="-184.82" font-family="Helvetica,sans-Serif" font-size="9.00">gRPC</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 15 KiB |
@@ -86,8 +86,7 @@ main {
|
||||
border-radius: 4px;
|
||||
padding: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
max-height: 400px;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.graph-preview img {
|
||||
|
||||
@@ -231,6 +231,31 @@ machine_metrics_cache[machine_id].update(incoming_metrics)
|
||||
|
||||
New metrics merge with existing. The broadcast includes the full merged state.
|
||||
|
||||
### Edge Relay - Public Dashboard Without the Cost
|
||||
|
||||
The full stack (aggregator, Redis, TimescaleDB) runs on local hardware. But the dashboard needs to be publicly accessible at `sysmonstm.mcrn.ar`. Running the full stack on AWS would be expensive and unnecessary.
|
||||
|
||||
The solution is an edge relay (`ctrl/edge/edge.py`). It's a minimal FastAPI app that does one thing: relay WebSocket messages. The gateway forwards metrics to the edge via WebSocket, and the edge broadcasts them to connected browsers:
|
||||
|
||||
```python
|
||||
# Gateway forwards to edge when EDGE_URL is configured
|
||||
async def forward_to_edge(data: dict):
|
||||
if edge_ws:
|
||||
await edge_ws.send(json.dumps(data))
|
||||
```
|
||||
|
||||
The edge receives these and broadcasts to all dashboard viewers:
|
||||
|
||||
```python
|
||||
@app.websocket("/ws")
|
||||
async def dashboard_ws(websocket: WebSocket):
|
||||
await websocket.accept()
|
||||
clients.add(websocket)
|
||||
# ... broadcasts incoming metrics to all clients
|
||||
```
|
||||
|
||||
This keeps heavy processing (gRPC, storage, event evaluation) on local hardware and puts only a lightweight relay in the cloud. The AWS instance has no databases, no gRPC, no storage — just WebSocket in, WebSocket out.
|
||||
|
||||
## Phase 3: Alerts - Adding Intelligence
|
||||
|
||||
The alerts service subscribes to metric events and evaluates them against rules.
|
||||
@@ -402,7 +427,8 @@ Set `COLLECTOR_AGGREGATOR_URL=192.168.1.100:50051` and it overrides the default.
|
||||
| Redis events | `shared/events/redis_pubsub.py` | Redis Pub/Sub implementation |
|
||||
| Configuration | `shared/config.py` | Pydantic settings for all services |
|
||||
| DB initialization | `scripts/init-db.sql` | TimescaleDB schema, hypertables |
|
||||
| Docker setup | `docker-compose.yml` | Full stack orchestration |
|
||||
| Edge relay | `ctrl/edge/edge.py` | WebSocket relay for AWS dashboard |
|
||||
| Docker setup | `ctrl/dev/docker-compose.yml` | Full stack orchestration |
|
||||
|
||||
## Running It
|
||||
|
||||
|
||||
@@ -80,39 +80,6 @@
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<!-- Explainer Articles -->
|
||||
<section class="nav-section">
|
||||
<h2>Explainer Articles</h2>
|
||||
<div class="doc-links">
|
||||
<a
|
||||
href="explainer/viewer.html?file=sysmonstm-from-start-to-finish.md"
|
||||
class="doc-link"
|
||||
>
|
||||
<h3>sysmonstm: From Start to Finish</h3>
|
||||
<p>
|
||||
The complete story of building this monitoring
|
||||
platform. Architecture decisions, trade-offs, and
|
||||
code walkthrough from MVP to production patterns.
|
||||
</p>
|
||||
<span class="tag">Article</span>
|
||||
</a>
|
||||
<a
|
||||
href="explainer/viewer.html?file=other-applications.md"
|
||||
class="doc-link"
|
||||
>
|
||||
<h3>Same Patterns, Different Domains</h3>
|
||||
<p>
|
||||
How the same architecture applies to payment
|
||||
processing systems and the Deskmeter workspace
|
||||
timer. Domain mapping and implementation paths.
|
||||
</p>
|
||||
<span class="tag">Article</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<hr class="section-divider" />
|
||||
|
||||
<!-- Architecture Diagrams -->
|
||||
<section class="graph-section" id="overview">
|
||||
<div class="graph-header-row">
|
||||
@@ -155,6 +122,11 @@
|
||||
<strong>Alerts</strong>: Subscribes to events,
|
||||
evaluates thresholds, triggers actions
|
||||
</li>
|
||||
<li>
|
||||
<strong>Edge</strong>: Lightweight WebSocket
|
||||
relay on AWS, serves public dashboard at
|
||||
sysmonstm.mcrn.ar
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
@@ -245,16 +217,17 @@
|
||||
<h4>Environments</h4>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Local Dev</strong>: Kind + Tilt for K8s, or
|
||||
Docker Compose
|
||||
<strong>Local</strong>: Docker Compose with
|
||||
aggregator, gateway, Redis, TimescaleDB, alerts
|
||||
</li>
|
||||
<li>
|
||||
<strong>Demo (EC2)</strong>: Docker Compose on
|
||||
t2.small at sysmonstm.mcrn.ar
|
||||
<strong>Edge (AWS)</strong>: Lightweight
|
||||
WebSocket relay at sysmonstm.mcrn.ar, receives
|
||||
forwarded metrics from local gateway
|
||||
</li>
|
||||
<li>
|
||||
<strong>Lambda Pipeline</strong>: SQS-triggered
|
||||
aggregation for data processing experience
|
||||
<strong>Collectors</strong>: Run on remote
|
||||
machines, stream to local aggregator via gRPC
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -301,7 +274,7 @@
|
||||
<hr class="section-divider" />
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>Interview Talking Points</h2>
|
||||
<h2>Key Design Decisions</h2>
|
||||
<div class="findings-grid">
|
||||
<article class="finding-card">
|
||||
<h3>Domain Mapping</h3>
|
||||
@@ -366,16 +339,13 @@
|
||||
<h3>Infrastructure</h3>
|
||||
<ul>
|
||||
<li>Docker</li>
|
||||
<li>Kubernetes</li>
|
||||
<li>Kind + Tilt</li>
|
||||
<li>Terraform</li>
|
||||
<li>Docker Compose</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tech-column">
|
||||
<h3>CI/CD</h3>
|
||||
<ul>
|
||||
<li>Woodpecker CI</li>
|
||||
<li>Kustomize</li>
|
||||
<li>Container Registry</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -386,7 +356,7 @@
|
||||
<footer>
|
||||
<p>System Monitoring Platform - Documentation</p>
|
||||
<p class="date">
|
||||
Generated: <time datetime="2025-12-31">December 2025</time>
|
||||
Generated: <time datetime="2026-03-16">March 2026</time>
|
||||
</p>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user