The duplicate functions at lines 455-486 were redefining cacheElements and bindEvents with wrong element IDs (kebab-case vs camelCase in HTML). This caused 'Cannot read properties of null' error on slides app init.
1381 lines
44 KiB
HTML
1381 lines
44 KiB
HTML
<link rel="stylesheet" href="monitoring/monitoring.css" />
|
|
|
|
<div class="monitoring-container" id="monitoring-app">
|
|
<header class="monitoring-header">
|
|
<h2>
|
|
<svg
|
|
width="24"
|
|
height="24"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
class="header-icon"
|
|
>
|
|
<circle
|
|
cx="12"
|
|
cy="12"
|
|
r="10"
|
|
stroke="currentColor"
|
|
stroke-width="1.</h2>5"
|
|
fill="none"
|
|
opacity="0.3"
|
|
/>
|
|
<circle
|
|
cx="12"
|
|
cy="12"
|
|
r="6.5"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
fill="none"
|
|
opacity="0.6"
|
|
/>
|
|
<circle cx="12" cy="12" r="2" fill="currentColor" />
|
|
<line
|
|
x1="12"
|
|
y1="2"
|
|
x2="12"
|
|
y2="5"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
/>
|
|
<line
|
|
x1="12"
|
|
y1="19"
|
|
x2="12"
|
|
y2="22"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
/>
|
|
<line
|
|
x1="2"
|
|
y1="12"
|
|
x2="5"
|
|
y2="12"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
/>
|
|
<line
|
|
x1="19"
|
|
y1="12"
|
|
x2="22"
|
|
y2="12"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
/>
|
|
</svg>
|
|
Monitoring Dashboard
|
|
</h2>
|
|
<div class="header-actions">
|
|
<button class="view-toggle" id="view-toggle" title="Toggle View">
|
|
<svg
|
|
width="18"
|
|
height="18"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
>
|
|
<rect x="3" y="3" width="7" height="7" />
|
|
<rect x="14" y="3" width="7" height="7" />
|
|
<rect x="3" y="14" width="7" height="7" />
|
|
<rect x="14" y="14" width="7" height="7" />
|
|
</svg>
|
|
</button>
|
|
<span
|
|
class="last-updated"
|
|
hx-get="/api/ui/monitoring/timestamp"
|
|
hx-trigger="load, every 5s"
|
|
hx-swap="innerHTML"
|
|
>--</span
|
|
>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Live System Visualization -->
|
|
<div class="live-visualization" id="live-view">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 1200 650"
|
|
class="live-svg"
|
|
>
|
|
<defs>
|
|
<!-- Gradients -->
|
|
<linearGradient
|
|
id="bgGradient"
|
|
x1="0%"
|
|
y1="0%"
|
|
x2="100%"
|
|
y2="100%"
|
|
>
|
|
<stop
|
|
offset="0%"
|
|
style="stop-color: var(--bg-dark, #0f172a)"
|
|
/>
|
|
<stop
|
|
offset="50%"
|
|
style="stop-color: var(--bg-surface, #1e293b)"
|
|
/>
|
|
<stop
|
|
offset="100%"
|
|
style="stop-color: var(--bg-dark, #0f172a)"
|
|
/>
|
|
</linearGradient>
|
|
|
|
<linearGradient
|
|
id="coreGlow"
|
|
x1="0%"
|
|
y1="0%"
|
|
x2="100%"
|
|
y2="100%"
|
|
>
|
|
<stop offset="0%" style="stop-color: #3b82f6" />
|
|
<stop offset="50%" style="stop-color: #6366f1" />
|
|
<stop offset="100%" style="stop-color: #8b5cf6" />
|
|
</linearGradient>
|
|
|
|
<linearGradient
|
|
id="greenGlow"
|
|
x1="0%"
|
|
y1="0%"
|
|
x2="100%"
|
|
y2="100%"
|
|
>
|
|
<stop offset="0%" style="stop-color: #10b981" />
|
|
<stop offset="100%" style="stop-color: #22c55e" />
|
|
</linearGradient>
|
|
|
|
<linearGradient
|
|
id="dbGradient"
|
|
x1="0%"
|
|
y1="0%"
|
|
x2="100%"
|
|
y2="100%"
|
|
>
|
|
<stop offset="0%" style="stop-color: #3b82f6" />
|
|
<stop offset="100%" style="stop-color: #1d4ed8" />
|
|
</linearGradient>
|
|
|
|
<linearGradient
|
|
id="vectorGradient"
|
|
x1="0%"
|
|
y1="0%"
|
|
x2="100%"
|
|
y2="100%"
|
|
>
|
|
<stop offset="0%" style="stop-color: #8b5cf6" />
|
|
<stop offset="100%" style="stop-color: #6d28d9" />
|
|
</linearGradient>
|
|
|
|
<linearGradient
|
|
id="storageGradient"
|
|
x1="0%"
|
|
y1="0%"
|
|
x2="100%"
|
|
y2="100%"
|
|
>
|
|
<stop offset="0%" style="stop-color: #f59e0b" />
|
|
<stop offset="100%" style="stop-color: #d97706" />
|
|
</linearGradient>
|
|
|
|
<linearGradient
|
|
id="aiGradient"
|
|
x1="0%"
|
|
y1="0%"
|
|
x2="100%"
|
|
y2="100%"
|
|
>
|
|
<stop offset="0%" style="stop-color: #ec4899" />
|
|
<stop offset="100%" style="stop-color: #db2777" />
|
|
</linearGradient>
|
|
|
|
<linearGradient
|
|
id="cacheGradient"
|
|
x1="0%"
|
|
y1="0%"
|
|
x2="100%"
|
|
y2="100%"
|
|
>
|
|
<stop offset="0%" style="stop-color: #06b6d4" />
|
|
<stop offset="100%" style="stop-color: #0891b2" />
|
|
</linearGradient>
|
|
|
|
<!-- Glow filter -->
|
|
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
|
|
<feGaussianBlur stdDeviation="3" result="coloredBlur" />
|
|
<feMerge>
|
|
<feMergeNode in="coloredBlur" />
|
|
<feMergeNode in="SourceGraphic" />
|
|
</feMerge>
|
|
</filter>
|
|
</defs>
|
|
|
|
<!-- Background -->
|
|
<rect width="100%" height="100%" fill="url(#bgGradient)" />
|
|
|
|
<!-- Subtle grid -->
|
|
<g opacity="0.06" stroke="#64748b" stroke-width="0.5">
|
|
<line x1="0" y1="162" x2="1200" y2="162" />
|
|
<line x1="0" y1="325" x2="1200" y2="325" />
|
|
<line x1="0" y1="487" x2="1200" y2="487" />
|
|
<line x1="300" y1="0" x2="300" y2="650" />
|
|
<line x1="600" y1="0" x2="600" y2="650" />
|
|
<line x1="900" y1="0" x2="900" y2="650" />
|
|
</g>
|
|
|
|
<!-- ==================== CENTRAL CORE: BotServer ==================== -->
|
|
<g transform="translate(600, 325)" class="core-node">
|
|
<!-- Outer rotating ring -->
|
|
<circle
|
|
r="85"
|
|
fill="none"
|
|
stroke="url(#coreGlow)"
|
|
stroke-width="2"
|
|
stroke-dasharray="10 5"
|
|
opacity="0.4"
|
|
class="rotate-slow"
|
|
/>
|
|
|
|
<!-- Middle pulsing ring -->
|
|
<circle
|
|
r="65"
|
|
fill="none"
|
|
stroke="url(#coreGlow)"
|
|
stroke-width="3"
|
|
opacity="0.6"
|
|
class="pulse-ring"
|
|
/>
|
|
|
|
<!-- Core background -->
|
|
<circle
|
|
r="50"
|
|
fill="#1e293b"
|
|
stroke="url(#coreGlow)"
|
|
stroke-width="3"
|
|
filter="url(#glow)"
|
|
/>
|
|
|
|
<!-- Bot icon -->
|
|
<g fill="#f8fafc">
|
|
<rect
|
|
x="-22"
|
|
y="-18"
|
|
width="44"
|
|
height="32"
|
|
rx="7"
|
|
fill="url(#coreGlow)"
|
|
opacity="0.9"
|
|
/>
|
|
<circle cx="-9" cy="-4" r="4.5" fill="#f8fafc" />
|
|
<circle cx="9" cy="-4" r="4.5" fill="#f8fafc" />
|
|
<path
|
|
d="M-10 9 Q0 16 10 9"
|
|
stroke="#f8fafc"
|
|
stroke-width="2.5"
|
|
fill="none"
|
|
/>
|
|
<rect
|
|
x="-2.5"
|
|
y="-32"
|
|
width="5"
|
|
height="11"
|
|
rx="2.5"
|
|
fill="url(#coreGlow)"
|
|
/>
|
|
<circle
|
|
cx="0"
|
|
cy="-35"
|
|
r="4.5"
|
|
fill="url(#coreGlow)"
|
|
class="antenna-pulse"
|
|
/>
|
|
</g>
|
|
|
|
<text
|
|
y="72"
|
|
text-anchor="middle"
|
|
fill="#f8fafc"
|
|
font-family="system-ui"
|
|
font-size="13"
|
|
font-weight="600"
|
|
>
|
|
BotServer
|
|
</text>
|
|
<text
|
|
y="88"
|
|
text-anchor="middle"
|
|
fill="#10b981"
|
|
font-family="system-ui"
|
|
font-size="10"
|
|
class="status-text"
|
|
>
|
|
● Running
|
|
</text>
|
|
</g>
|
|
|
|
<!-- ==================== LEFT: Data Layer ==================== -->
|
|
|
|
<!-- PostgreSQL -->
|
|
<g
|
|
transform="translate(150, 185)"
|
|
class="service-node"
|
|
data-service="postgresql"
|
|
>
|
|
<circle
|
|
r="42"
|
|
fill="#1e293b"
|
|
stroke="url(#dbGradient)"
|
|
stroke-width="2"
|
|
filter="url(#glow)"
|
|
/>
|
|
<g transform="translate(-14, -16)">
|
|
<ellipse
|
|
cx="14"
|
|
cy="0"
|
|
rx="16"
|
|
ry="5.5"
|
|
fill="url(#dbGradient)"
|
|
/>
|
|
<path
|
|
d="M-2 0 L-2 18 Q14 27 30 18 L30 0"
|
|
fill="url(#dbGradient)"
|
|
opacity="0.8"
|
|
/>
|
|
<ellipse
|
|
cx="14"
|
|
cy="18"
|
|
rx="16"
|
|
ry="5.5"
|
|
fill="url(#dbGradient)"
|
|
/>
|
|
<line
|
|
x1="-2"
|
|
y1="6"
|
|
x2="30"
|
|
y2="6"
|
|
stroke="#1e40af"
|
|
stroke-width="1"
|
|
/>
|
|
<line
|
|
x1="-2"
|
|
y1="12"
|
|
x2="30"
|
|
y2="12"
|
|
stroke="#1e40af"
|
|
stroke-width="1"
|
|
/>
|
|
</g>
|
|
<text
|
|
y="58"
|
|
text-anchor="middle"
|
|
fill="#f8fafc"
|
|
font-family="system-ui"
|
|
font-size="11"
|
|
font-weight="500"
|
|
>
|
|
PostgreSQL
|
|
</text>
|
|
<circle
|
|
cx="32"
|
|
cy="-32"
|
|
r="5"
|
|
class="status-dot running"
|
|
data-status="postgresql"
|
|
/>
|
|
</g>
|
|
|
|
<!-- Qdrant -->
|
|
<g
|
|
transform="translate(150, 325)"
|
|
class="service-node"
|
|
data-service="qdrant"
|
|
>
|
|
<circle
|
|
r="42"
|
|
fill="#1e293b"
|
|
stroke="url(#vectorGradient)"
|
|
stroke-width="2"
|
|
filter="url(#glow)"
|
|
/>
|
|
<g fill="url(#vectorGradient)">
|
|
<polygon points="0,-20 17,10 -17,10" opacity="0.9" />
|
|
<polygon points="0,-11 11,6 -11,6" fill="#1e293b" />
|
|
<circle cx="0" cy="-20" r="3.5" />
|
|
<circle cx="17" cy="10" r="3.5" />
|
|
<circle cx="-17" cy="10" r="3.5" />
|
|
</g>
|
|
<text
|
|
y="58"
|
|
text-anchor="middle"
|
|
fill="#f8fafc"
|
|
font-family="system-ui"
|
|
font-size="11"
|
|
font-weight="500"
|
|
>
|
|
Qdrant
|
|
</text>
|
|
<circle
|
|
cx="32"
|
|
cy="-32"
|
|
r="5"
|
|
class="status-dot running"
|
|
data-status="qdrant"
|
|
/>
|
|
</g>
|
|
|
|
<!-- MinIO -->
|
|
<g
|
|
transform="translate(150, 465)"
|
|
class="service-node"
|
|
data-service="drive"
|
|
>
|
|
<circle
|
|
r="42"
|
|
fill="#1e293b"
|
|
stroke="url(#storageGradient)"
|
|
stroke-width="2"
|
|
filter="url(#glow)"
|
|
/>
|
|
<g fill="url(#storageGradient)">
|
|
<rect x="-20" y="-16" width="40" height="32" rx="4" />
|
|
<rect
|
|
x="-16"
|
|
y="-12"
|
|
width="32"
|
|
height="24"
|
|
rx="2"
|
|
fill="#1e293b"
|
|
/>
|
|
<rect
|
|
x="-12"
|
|
y="-8"
|
|
width="24"
|
|
height="7"
|
|
rx="1"
|
|
fill="#fcd34d"
|
|
opacity="0.4"
|
|
/>
|
|
<rect
|
|
x="-12"
|
|
y="2"
|
|
width="24"
|
|
height="7"
|
|
rx="1"
|
|
fill="#fcd34d"
|
|
opacity="0.4"
|
|
/>
|
|
<circle cx="8" cy="-4.5" r="1.8" fill="#fbbf24" />
|
|
<circle cx="8" cy="5.5" r="1.8" fill="#fbbf24" />
|
|
</g>
|
|
<text
|
|
y="58"
|
|
text-anchor="middle"
|
|
fill="#f8fafc"
|
|
font-family="system-ui"
|
|
font-size="11"
|
|
font-weight="500"
|
|
>
|
|
MinIO
|
|
</text>
|
|
<circle
|
|
cx="32"
|
|
cy="-32"
|
|
r="5"
|
|
class="status-dot running"
|
|
data-status="drive"
|
|
/>
|
|
</g>
|
|
|
|
<!-- ==================== RIGHT: Services ==================== -->
|
|
|
|
<!-- BotModels -->
|
|
<g
|
|
transform="translate(1050, 185)"
|
|
class="service-node"
|
|
data-service="botmodels"
|
|
>
|
|
<circle
|
|
r="42"
|
|
fill="#1e293b"
|
|
stroke="url(#aiGradient)"
|
|
stroke-width="2"
|
|
filter="url(#glow)"
|
|
/>
|
|
<g>
|
|
<circle
|
|
cx="0"
|
|
cy="-7"
|
|
r="12"
|
|
fill="none"
|
|
stroke="url(#aiGradient)"
|
|
stroke-width="2"
|
|
/>
|
|
<circle
|
|
cx="0"
|
|
cy="-7"
|
|
r="5"
|
|
fill="url(#aiGradient)"
|
|
class="ai-pulse"
|
|
/>
|
|
<path
|
|
d="M-16 10 L0 -2 L16 10"
|
|
stroke="url(#aiGradient)"
|
|
stroke-width="2"
|
|
fill="none"
|
|
/>
|
|
<path
|
|
d="M-10 16 L0 7 L10 16"
|
|
stroke="url(#aiGradient)"
|
|
stroke-width="2"
|
|
fill="none"
|
|
/>
|
|
</g>
|
|
<text
|
|
y="58"
|
|
text-anchor="middle"
|
|
fill="#f8fafc"
|
|
font-family="system-ui"
|
|
font-size="11"
|
|
font-weight="500"
|
|
>
|
|
BotModels
|
|
</text>
|
|
<circle
|
|
cx="32"
|
|
cy="-32"
|
|
r="5"
|
|
class="status-dot running"
|
|
data-status="botmodels"
|
|
/>
|
|
</g>
|
|
|
|
<!-- Cache -->
|
|
<g
|
|
transform="translate(1050, 325)"
|
|
class="service-node"
|
|
data-service="cache"
|
|
>
|
|
<circle
|
|
r="42"
|
|
fill="#1e293b"
|
|
stroke="url(#cacheGradient)"
|
|
stroke-width="2"
|
|
filter="url(#glow)"
|
|
/>
|
|
<g fill="url(#cacheGradient)">
|
|
<rect x="-18" y="-16" width="36" height="32" rx="3" />
|
|
<rect
|
|
x="-14"
|
|
y="-12"
|
|
width="28"
|
|
height="24"
|
|
rx="2"
|
|
fill="#1e293b"
|
|
/>
|
|
<text
|
|
x="0"
|
|
y="5"
|
|
text-anchor="middle"
|
|
font-family="system-ui"
|
|
font-size="16"
|
|
fill="#22d3ee"
|
|
>
|
|
⚡
|
|
</text>
|
|
</g>
|
|
<text
|
|
y="58"
|
|
text-anchor="middle"
|
|
fill="#f8fafc"
|
|
font-family="system-ui"
|
|
font-size="11"
|
|
font-weight="500"
|
|
>
|
|
Cache
|
|
</text>
|
|
<circle
|
|
cx="32"
|
|
cy="-32"
|
|
r="5"
|
|
class="status-dot running"
|
|
data-status="cache"
|
|
/>
|
|
</g>
|
|
|
|
<!-- Vault -->
|
|
<g
|
|
transform="translate(1050, 465)"
|
|
class="service-node"
|
|
data-service="vault"
|
|
>
|
|
<circle
|
|
r="42"
|
|
fill="#1e293b"
|
|
stroke="url(#greenGlow)"
|
|
stroke-width="2"
|
|
filter="url(#glow)"
|
|
/>
|
|
<g fill="url(#greenGlow)">
|
|
<rect x="-16" y="-9" width="32" height="25" rx="4" />
|
|
<rect
|
|
x="-12"
|
|
y="-5"
|
|
width="24"
|
|
height="17"
|
|
rx="2"
|
|
fill="#1e293b"
|
|
/>
|
|
<circle cx="0" cy="3.5" r="5" fill="url(#greenGlow)" />
|
|
<rect
|
|
x="-1.5"
|
|
y="3.5"
|
|
width="3"
|
|
height="7"
|
|
fill="url(#greenGlow)"
|
|
/>
|
|
<path
|
|
d="M-9 -16 L0 -23 L9 -16"
|
|
stroke="url(#greenGlow)"
|
|
stroke-width="2.5"
|
|
fill="none"
|
|
/>
|
|
</g>
|
|
<text
|
|
y="58"
|
|
text-anchor="middle"
|
|
fill="#f8fafc"
|
|
font-family="system-ui"
|
|
font-size="11"
|
|
font-weight="500"
|
|
>
|
|
Vault
|
|
</text>
|
|
<circle
|
|
cx="32"
|
|
cy="-32"
|
|
r="5"
|
|
class="status-dot running"
|
|
data-status="vault"
|
|
/>
|
|
</g>
|
|
|
|
<!-- ==================== ANIMATED CONNECTION LINES ==================== -->
|
|
|
|
<!-- Left connections -->
|
|
<g class="connection-lines" stroke-width="2" fill="none">
|
|
<path
|
|
d="M192 185 Q400 185 510 300"
|
|
stroke="#3b82f6"
|
|
opacity="0.25"
|
|
class="connection-path"
|
|
/>
|
|
<circle r="3.5" fill="#60a5fa" class="data-packet">
|
|
<animateMotion
|
|
dur="3s"
|
|
repeatCount="indefinite"
|
|
path="M192 185 Q400 185 510 300"
|
|
/>
|
|
</circle>
|
|
|
|
<path
|
|
d="M192 325 L510 325"
|
|
stroke="#8b5cf6"
|
|
opacity="0.25"
|
|
class="connection-path"
|
|
/>
|
|
<circle r="3.5" fill="#a78bfa" class="data-packet">
|
|
<animateMotion
|
|
dur="2.5s"
|
|
repeatCount="indefinite"
|
|
path="M192 325 L510 325"
|
|
/>
|
|
</circle>
|
|
|
|
<path
|
|
d="M192 465 Q400 465 510 350"
|
|
stroke="#f59e0b"
|
|
opacity="0.25"
|
|
class="connection-path"
|
|
/>
|
|
<circle r="3.5" fill="#fcd34d" class="data-packet">
|
|
<animateMotion
|
|
dur="3.5s"
|
|
repeatCount="indefinite"
|
|
path="M192 465 Q400 465 510 350"
|
|
/>
|
|
</circle>
|
|
</g>
|
|
|
|
<!-- Right connections -->
|
|
<g class="connection-lines" stroke-width="2" fill="none">
|
|
<path
|
|
d="M690 300 Q800 185 1008 185"
|
|
stroke="#ec4899"
|
|
opacity="0.25"
|
|
class="connection-path"
|
|
/>
|
|
<circle r="3.5" fill="#f472b6" class="data-packet">
|
|
<animateMotion
|
|
dur="2s"
|
|
repeatCount="indefinite"
|
|
path="M690 300 Q800 185 1008 185"
|
|
/>
|
|
</circle>
|
|
|
|
<path
|
|
d="M690 325 L1008 325"
|
|
stroke="#06b6d4"
|
|
opacity="0.25"
|
|
class="connection-path"
|
|
/>
|
|
<circle r="3.5" fill="#22d3ee" class="data-packet">
|
|
<animateMotion
|
|
dur="1.5s"
|
|
repeatCount="indefinite"
|
|
path="M690 325 L1008 325"
|
|
/>
|
|
</circle>
|
|
|
|
<path
|
|
d="M690 350 Q800 465 1008 465"
|
|
stroke="#10b981"
|
|
opacity="0.25"
|
|
class="connection-path"
|
|
/>
|
|
<circle r="3.5" fill="#34d399" class="data-packet">
|
|
<animateMotion
|
|
dur="4s"
|
|
repeatCount="indefinite"
|
|
path="M690 350 Q800 465 1008 465"
|
|
/>
|
|
</circle>
|
|
</g>
|
|
|
|
<!-- ==================== METRICS PANELS ==================== -->
|
|
|
|
<!-- Sessions -->
|
|
<g transform="translate(330, 50)">
|
|
<rect
|
|
x="0"
|
|
y="0"
|
|
width="150"
|
|
height="75"
|
|
rx="10"
|
|
fill="#1e293b"
|
|
stroke="#334155"
|
|
stroke-width="1"
|
|
/>
|
|
<text
|
|
x="12"
|
|
y="22"
|
|
fill="#64748b"
|
|
font-family="system-ui"
|
|
font-size="9"
|
|
font-weight="500"
|
|
>
|
|
ACTIVE SESSIONS
|
|
</text>
|
|
<text
|
|
x="12"
|
|
y="52"
|
|
fill="#f8fafc"
|
|
font-family="system-ui"
|
|
font-size="28"
|
|
font-weight="700"
|
|
hx-get="/api/ui/monitoring/metric/sessions"
|
|
hx-trigger="load, every 5s"
|
|
hx-swap="innerHTML"
|
|
>
|
|
--
|
|
</text>
|
|
<text
|
|
x="138"
|
|
y="62"
|
|
fill="#10b981"
|
|
font-family="system-ui"
|
|
font-size="10"
|
|
text-anchor="end"
|
|
hx-get="/api/ui/monitoring/trend/sessions"
|
|
hx-trigger="load, every 5s"
|
|
hx-swap="innerHTML"
|
|
>
|
|
↑ 0%
|
|
</text>
|
|
</g>
|
|
|
|
<!-- Messages -->
|
|
<g transform="translate(500, 50)">
|
|
<rect
|
|
x="0"
|
|
y="0"
|
|
width="150"
|
|
height="75"
|
|
rx="10"
|
|
fill="#1e293b"
|
|
stroke="#334155"
|
|
stroke-width="1"
|
|
/>
|
|
<text
|
|
x="12"
|
|
y="22"
|
|
fill="#64748b"
|
|
font-family="system-ui"
|
|
font-size="9"
|
|
font-weight="500"
|
|
>
|
|
MESSAGES TODAY
|
|
</text>
|
|
<text
|
|
x="12"
|
|
y="52"
|
|
fill="#f8fafc"
|
|
font-family="system-ui"
|
|
font-size="28"
|
|
font-weight="700"
|
|
hx-get="/api/ui/monitoring/metric/messages"
|
|
hx-trigger="load, every 10s"
|
|
hx-swap="innerHTML"
|
|
>
|
|
--
|
|
</text>
|
|
<text
|
|
x="138"
|
|
y="62"
|
|
fill="#94a3b8"
|
|
font-family="system-ui"
|
|
font-size="10"
|
|
text-anchor="end"
|
|
hx-get="/api/ui/monitoring/rate/messages"
|
|
hx-trigger="load, every 10s"
|
|
hx-swap="innerHTML"
|
|
>
|
|
0/hr
|
|
</text>
|
|
</g>
|
|
|
|
<!-- Response Time -->
|
|
<g transform="translate(670, 50)">
|
|
<rect
|
|
x="0"
|
|
y="0"
|
|
width="150"
|
|
height="75"
|
|
rx="10"
|
|
fill="#1e293b"
|
|
stroke="#334155"
|
|
stroke-width="1"
|
|
/>
|
|
<text
|
|
x="12"
|
|
y="22"
|
|
fill="#64748b"
|
|
font-family="system-ui"
|
|
font-size="9"
|
|
font-weight="500"
|
|
>
|
|
AVG RESPONSE
|
|
</text>
|
|
<text
|
|
x="12"
|
|
y="52"
|
|
fill="#f8fafc"
|
|
font-family="system-ui"
|
|
font-size="28"
|
|
font-weight="700"
|
|
hx-get="/api/ui/monitoring/metric/response_time"
|
|
hx-trigger="load, every 10s"
|
|
hx-swap="innerHTML"
|
|
>
|
|
--
|
|
</text>
|
|
<text
|
|
x="138"
|
|
y="62"
|
|
fill="#94a3b8"
|
|
font-family="system-ui"
|
|
font-size="10"
|
|
text-anchor="end"
|
|
>
|
|
ms
|
|
</text>
|
|
</g>
|
|
|
|
<!-- ==================== RESOURCE BARS ==================== -->
|
|
|
|
<g
|
|
transform="translate(330, 545)"
|
|
hx-get="/api/ui/monitoring/resources/bars"
|
|
hx-trigger="load, every 15s"
|
|
hx-swap="innerHTML"
|
|
>
|
|
<!-- CPU -->
|
|
<g transform="translate(0, 0)">
|
|
<text
|
|
x="0"
|
|
y="11"
|
|
fill="#94a3b8"
|
|
font-family="system-ui"
|
|
font-size="9"
|
|
font-weight="500"
|
|
>
|
|
CPU
|
|
</text>
|
|
<rect
|
|
x="35"
|
|
y="2"
|
|
width="90"
|
|
height="12"
|
|
rx="4"
|
|
fill="#334155"
|
|
/>
|
|
<rect
|
|
x="35"
|
|
y="2"
|
|
width="58"
|
|
height="12"
|
|
rx="4"
|
|
fill="url(#coreGlow)"
|
|
class="resource-fill"
|
|
/>
|
|
<text
|
|
x="132"
|
|
y="12"
|
|
fill="#f8fafc"
|
|
font-family="system-ui"
|
|
font-size="10"
|
|
font-weight="500"
|
|
>
|
|
65%
|
|
</text>
|
|
</g>
|
|
|
|
<!-- Memory -->
|
|
<g transform="translate(160, 0)">
|
|
<text
|
|
x="0"
|
|
y="11"
|
|
fill="#94a3b8"
|
|
font-family="system-ui"
|
|
font-size="9"
|
|
font-weight="500"
|
|
>
|
|
MEM
|
|
</text>
|
|
<rect
|
|
x="35"
|
|
y="2"
|
|
width="90"
|
|
height="12"
|
|
rx="4"
|
|
fill="#334155"
|
|
/>
|
|
<rect
|
|
x="35"
|
|
y="2"
|
|
width="65"
|
|
height="12"
|
|
rx="4"
|
|
fill="url(#greenGlow)"
|
|
class="resource-fill"
|
|
/>
|
|
<text
|
|
x="132"
|
|
y="12"
|
|
fill="#f8fafc"
|
|
font-family="system-ui"
|
|
font-size="10"
|
|
font-weight="500"
|
|
>
|
|
72%
|
|
</text>
|
|
</g>
|
|
|
|
<!-- GPU -->
|
|
<g transform="translate(320, 0)">
|
|
<text
|
|
x="0"
|
|
y="11"
|
|
fill="#94a3b8"
|
|
font-family="system-ui"
|
|
font-size="9"
|
|
font-weight="500"
|
|
>
|
|
GPU
|
|
</text>
|
|
<rect
|
|
x="35"
|
|
y="2"
|
|
width="90"
|
|
height="12"
|
|
rx="4"
|
|
fill="#334155"
|
|
/>
|
|
<rect
|
|
x="35"
|
|
y="2"
|
|
width="40"
|
|
height="12"
|
|
rx="4"
|
|
fill="url(#vectorGradient)"
|
|
class="resource-fill"
|
|
/>
|
|
<text
|
|
x="132"
|
|
y="12"
|
|
fill="#f8fafc"
|
|
font-family="system-ui"
|
|
font-size="10"
|
|
font-weight="500"
|
|
>
|
|
45%
|
|
</text>
|
|
</g>
|
|
|
|
<!-- Disk -->
|
|
<g transform="translate(480, 0)">
|
|
<text
|
|
x="0"
|
|
y="11"
|
|
fill="#94a3b8"
|
|
font-family="system-ui"
|
|
font-size="9"
|
|
font-weight="500"
|
|
>
|
|
DISK
|
|
</text>
|
|
<rect
|
|
x="35"
|
|
y="2"
|
|
width="90"
|
|
height="12"
|
|
rx="4"
|
|
fill="#334155"
|
|
/>
|
|
<rect
|
|
x="35"
|
|
y="2"
|
|
width="25"
|
|
height="12"
|
|
rx="4"
|
|
fill="url(#storageGradient)"
|
|
class="resource-fill"
|
|
/>
|
|
<text
|
|
x="132"
|
|
y="12"
|
|
fill="#f8fafc"
|
|
font-family="system-ui"
|
|
font-size="10"
|
|
font-weight="500"
|
|
>
|
|
28%
|
|
</text>
|
|
</g>
|
|
</g>
|
|
|
|
<!-- ==================== ACTIVITY TICKER ==================== -->
|
|
|
|
<g transform="translate(330, 590)">
|
|
<rect
|
|
x="0"
|
|
y="0"
|
|
width="490"
|
|
height="36"
|
|
rx="8"
|
|
fill="#1e293b"
|
|
stroke="#334155"
|
|
stroke-width="1"
|
|
/>
|
|
<circle
|
|
cx="16"
|
|
cy="18"
|
|
r="4"
|
|
fill="#10b981"
|
|
class="pulse-dot"
|
|
/>
|
|
<text
|
|
x="30"
|
|
y="22"
|
|
fill="#94a3b8"
|
|
font-family="system-ui"
|
|
font-size="11"
|
|
hx-get="/api/ui/monitoring/activity/latest"
|
|
hx-trigger="load, every 5s"
|
|
hx-swap="innerHTML"
|
|
>
|
|
System monitoring active...
|
|
</text>
|
|
</g>
|
|
|
|
<!-- ==================== LEGEND ==================== -->
|
|
|
|
<g transform="translate(50, 600)">
|
|
<g transform="translate(0, 0)">
|
|
<circle r="4" fill="#10b981" />
|
|
<text
|
|
x="10"
|
|
y="4"
|
|
fill="#94a3b8"
|
|
font-family="system-ui"
|
|
font-size="9"
|
|
>
|
|
Running
|
|
</text>
|
|
</g>
|
|
<g transform="translate(70, 0)">
|
|
<circle r="4" fill="#f59e0b" />
|
|
<text
|
|
x="10"
|
|
y="4"
|
|
fill="#94a3b8"
|
|
font-family="system-ui"
|
|
font-size="9"
|
|
>
|
|
Warning
|
|
</text>
|
|
</g>
|
|
<g transform="translate(140, 0)">
|
|
<circle r="4" fill="#ef4444" />
|
|
<text
|
|
x="10"
|
|
y="4"
|
|
fill="#94a3b8"
|
|
font-family="system-ui"
|
|
font-size="9"
|
|
>
|
|
Stopped
|
|
</text>
|
|
</g>
|
|
</g>
|
|
</svg>
|
|
</div>
|
|
|
|
<!-- Grid View (hidden by default) -->
|
|
<div class="monitoring-grid" id="grid-view" style="display: none">
|
|
<!-- Sessions Panel -->
|
|
<div
|
|
class="monitor-panel"
|
|
hx-get="/api/ui/monitoring/sessions"
|
|
hx-trigger="load, every 5s"
|
|
hx-swap="innerHTML"
|
|
>
|
|
<div class="panel-header">
|
|
<svg
|
|
width="20"
|
|
height="20"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
class="panel-icon"
|
|
>
|
|
<circle
|
|
cx="12"
|
|
cy="8"
|
|
r="4"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
/>
|
|
<path
|
|
d="M4 20c0-4 4-6 8-6s8 2 8 6"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
/>
|
|
</svg>
|
|
<span>Sessions</span>
|
|
</div>
|
|
<div class="tree-view">
|
|
<div class="tree-node">
|
|
<span class="tree-branch"></span>
|
|
<span class="tree-label">Loading...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Messages Panel -->
|
|
<div
|
|
class="monitor-panel"
|
|
hx-get="/api/ui/monitoring/messages"
|
|
hx-trigger="load, every 10s"
|
|
hx-swap="innerHTML"
|
|
>
|
|
<div class="panel-header">
|
|
<svg
|
|
width="20"
|
|
height="20"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
class="panel-icon"
|
|
>
|
|
<path
|
|
d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
/>
|
|
</svg>
|
|
<span>Messages</span>
|
|
</div>
|
|
<div class="tree-view">
|
|
<div class="tree-node">
|
|
<span class="tree-branch"></span>
|
|
<span class="tree-label">Loading...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Resources Panel -->
|
|
<div
|
|
class="monitor-panel resources-panel"
|
|
hx-get="/api/ui/monitoring/resources"
|
|
hx-trigger="load, every 15s"
|
|
hx-swap="innerHTML"
|
|
>
|
|
<div class="panel-header">
|
|
<svg
|
|
width="20"
|
|
height="20"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
class="panel-icon"
|
|
>
|
|
<rect
|
|
x="4"
|
|
y="4"
|
|
width="16"
|
|
height="16"
|
|
rx="2"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
/>
|
|
<line
|
|
x1="4"
|
|
y1="12"
|
|
x2="20"
|
|
y2="12"
|
|
stroke="currentColor"
|
|
stroke-width="1"
|
|
/>
|
|
<line
|
|
x1="12"
|
|
y1="4"
|
|
x2="12"
|
|
y2="20"
|
|
stroke="currentColor"
|
|
stroke-width="1"
|
|
/>
|
|
</svg>
|
|
<span>Resources</span>
|
|
</div>
|
|
<div class="tree-view">
|
|
<div class="tree-node">
|
|
<span class="tree-branch"></span>
|
|
<span class="tree-label">Loading...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Services Panel -->
|
|
<div
|
|
class="monitor-panel services-panel"
|
|
hx-get="/api/ui/monitoring/services"
|
|
hx-trigger="load, every 30s"
|
|
hx-swap="innerHTML"
|
|
>
|
|
<div class="panel-header">
|
|
<svg
|
|
width="20"
|
|
height="20"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
class="panel-icon"
|
|
>
|
|
<rect
|
|
x="2"
|
|
y="3"
|
|
width="20"
|
|
height="4"
|
|
rx="1"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
/>
|
|
<rect
|
|
x="2"
|
|
y="10"
|
|
width="20"
|
|
height="4"
|
|
rx="1"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
/>
|
|
<rect
|
|
x="2"
|
|
y="17"
|
|
width="20"
|
|
height="4"
|
|
rx="1"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
/>
|
|
</svg>
|
|
<span>Services</span>
|
|
</div>
|
|
<div class="tree-view">
|
|
<div class="tree-node">
|
|
<span class="tree-branch"></span>
|
|
<span class="tree-label">Loading...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bots Panel -->
|
|
<div
|
|
class="monitor-panel bots-panel"
|
|
hx-get="/api/ui/monitoring/bots"
|
|
hx-trigger="load, every 30s"
|
|
hx-swap="innerHTML"
|
|
>
|
|
<div class="panel-header">
|
|
<svg
|
|
width="20"
|
|
height="20"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
class="panel-icon"
|
|
>
|
|
<rect
|
|
x="4"
|
|
y="4"
|
|
width="16"
|
|
height="14"
|
|
rx="3"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
/>
|
|
<circle cx="9" cy="10" r="1.5" fill="currentColor" />
|
|
<circle cx="15" cy="10" r="1.5" fill="currentColor" />
|
|
<path
|
|
d="M9 14 Q12 16 15 14"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
fill="none"
|
|
/>
|
|
</svg>
|
|
<span>Active Bots</span>
|
|
</div>
|
|
<div class="tree-view">
|
|
<div class="tree-node">
|
|
<span class="tree-branch"></span>
|
|
<span class="tree-label">Loading...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Hidden service status updater -->
|
|
<div
|
|
id="service-status-container"
|
|
style="display: none"
|
|
hx-get="/api/ui/monitoring/services/status"
|
|
hx-trigger="load, every 30s"
|
|
hx-swap="innerHTML"
|
|
></div>
|
|
|
|
<link rel="stylesheet" href="monitoring/monitoring.css" />
|
|
<script src="monitoring/monitoring.js"></script>
|
|
</div>
|