This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
from datetime import datetime, timezone
|
||||
|
||||
import requests
|
||||
@@ -53,6 +55,64 @@ def human_relative(iso_ts):
|
||||
return f"{days} gün önce"
|
||||
|
||||
|
||||
def _cpu_times():
|
||||
with open("/proc/stat") as f:
|
||||
parts = f.readline().split()[1:]
|
||||
nums = [int(x) for x in parts]
|
||||
idle = nums[3] + nums[4]
|
||||
total = sum(nums)
|
||||
return idle, total
|
||||
|
||||
|
||||
def server_stats():
|
||||
stats = {}
|
||||
|
||||
# CPU: kisa bir ornekleme araligiyla kullanim yuzdesi
|
||||
idle1, total1 = _cpu_times()
|
||||
time.sleep(0.3)
|
||||
idle2, total2 = _cpu_times()
|
||||
d_idle = idle2 - idle1
|
||||
d_total = total2 - total1
|
||||
cpu_percent = round((1 - d_idle / d_total) * 100, 1) if d_total > 0 else 0.0
|
||||
stats["cpu_percent"] = cpu_percent
|
||||
stats["cpu_cores"] = os.cpu_count()
|
||||
|
||||
with open("/proc/loadavg") as f:
|
||||
stats["load"] = " / ".join(f.read().split()[:3])
|
||||
|
||||
meminfo = {}
|
||||
with open("/proc/meminfo") as f:
|
||||
for line in f:
|
||||
key, _, rest = line.partition(":")
|
||||
meminfo[key] = int(rest.strip().split()[0]) # kB
|
||||
mem_total = meminfo.get("MemTotal", 0)
|
||||
mem_available = meminfo.get("MemAvailable", 0)
|
||||
mem_used = mem_total - mem_available
|
||||
stats["mem_used_gb"] = round(mem_used / 1024 / 1024, 1)
|
||||
stats["mem_total_gb"] = round(mem_total / 1024 / 1024, 1)
|
||||
stats["mem_percent"] = round(mem_used / mem_total * 100, 1) if mem_total else 0.0
|
||||
|
||||
disk = shutil.disk_usage("/")
|
||||
stats["disk_used_gb"] = round(disk.used / 1024**3, 1)
|
||||
stats["disk_total_gb"] = round(disk.total / 1024**3, 1)
|
||||
stats["disk_percent"] = round(disk.used / disk.total * 100, 1) if disk.total else 0.0
|
||||
|
||||
with open("/proc/uptime") as f:
|
||||
up_secs = int(float(f.read().split()[0]))
|
||||
days, rem = divmod(up_secs, 86400)
|
||||
hours, _ = divmod(rem, 3600)
|
||||
stats["uptime"] = f"{days} gün {hours} saat" if days else f"{hours} saat"
|
||||
|
||||
all_containers = subprocess.run(
|
||||
["docker", "ps", "-a", "--format", "{{.State}}"],
|
||||
capture_output=True, text=True,
|
||||
).stdout.split()
|
||||
stats["containers_running"] = sum(1 for s in all_containers if s == "running")
|
||||
stats["containers_total"] = len(all_containers)
|
||||
|
||||
return stats
|
||||
|
||||
|
||||
def inspect_all(cid):
|
||||
return json.loads(subprocess.run(
|
||||
["docker", "inspect", cid], capture_output=True, text=True, check=True
|
||||
@@ -161,11 +221,53 @@ TEMPLATE = """
|
||||
.btn-delete:hover { background: #991b1b; }
|
||||
.empty { opacity: 0.6; margin-top: 1.5rem; }
|
||||
form { display: inline; }
|
||||
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
gap: 1rem; margin-bottom: 2rem; }
|
||||
.stat-card { background: #1e293b; border-radius: 10px; padding: 1rem 1.2rem; }
|
||||
.stat-label { font-size: 0.75rem; opacity: 0.6; text-transform: uppercase; letter-spacing: .03em; }
|
||||
.stat-value { font-size: 1.5rem; font-weight: 700; margin: 0.15rem 0 0.5rem; }
|
||||
.stat-sub { font-size: 0.78rem; opacity: 0.55; }
|
||||
.bar { height: 6px; border-radius: 999px; background: #334155; overflow: hidden; margin-top: 0.5rem; }
|
||||
.bar-fill { height: 100%; background: #38bdf8; }
|
||||
.bar-fill.warn { background: #f59e0b; }
|
||||
.bar-fill.crit { background: #ef4444; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Deploy Panel</h1>
|
||||
<div class="sub">{{ projects|length }} proje · 20 saniyede bir otomatik yenilenir · <a href="/">şimdi yenile</a></div>
|
||||
|
||||
<div class="stats">
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">CPU ({{ s.cpu_cores }} çekirdek)</div>
|
||||
<div class="stat-value">%{{ s.cpu_percent }}</div>
|
||||
<div class="bar"><div class="bar-fill {{ 'crit' if s.cpu_percent > 85 else ('warn' if s.cpu_percent > 60 else '') }}" style="width: {{ s.cpu_percent }}%"></div></div>
|
||||
<div class="stat-sub">yük: {{ s.load }}</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Bellek</div>
|
||||
<div class="stat-value">%{{ s.mem_percent }}</div>
|
||||
<div class="bar"><div class="bar-fill {{ 'crit' if s.mem_percent > 85 else ('warn' if s.mem_percent > 60 else '') }}" style="width: {{ s.mem_percent }}%"></div></div>
|
||||
<div class="stat-sub">{{ s.mem_used_gb }} / {{ s.mem_total_gb }} GB</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Disk</div>
|
||||
<div class="stat-value">%{{ s.disk_percent }}</div>
|
||||
<div class="bar"><div class="bar-fill {{ 'crit' if s.disk_percent > 85 else ('warn' if s.disk_percent > 60 else '') }}" style="width: {{ s.disk_percent }}%"></div></div>
|
||||
<div class="stat-sub">{{ s.disk_used_gb }} / {{ s.disk_total_gb }} GB</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Sunucu</div>
|
||||
<div class="stat-value" style="font-size:1.1rem;">{{ s.uptime }}</div>
|
||||
<div class="stat-sub">çalışma süresi</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Container</div>
|
||||
<div class="stat-value" style="font-size:1.1rem;">{{ s.containers_running }} / {{ s.containers_total }}</div>
|
||||
<div class="stat-sub">çalışan / toplam</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if projects %}
|
||||
<table>
|
||||
<tr><th>Proje</th><th>Adres</th><th>Durum</th><th>İmaj</th><th></th></tr>
|
||||
@@ -225,7 +327,7 @@ LOGS_TEMPLATE = """
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
return render_template_string(TEMPLATE, projects=list_projects())
|
||||
return render_template_string(TEMPLATE, projects=list_projects(), s=server_stats())
|
||||
|
||||
|
||||
@app.route("/logs/<name>")
|
||||
|
||||
Reference in New Issue
Block a user