This commit is contained in:
devdatt 2026-02-18 17:49:52 +05:30
parent a6009a1085
commit d21816c93e
2 changed files with 157 additions and 94 deletions

View File

@ -246,124 +246,181 @@ WantedBy=multi-user.target
EOL EOL
cat > /usr/local/bin/nginx_system_monitor_sampler.py<< 'EOL' cat > /usr/local/bin/nginx_system_monitor_sampler.py<< 'EOL'
#!/usr/bin/env python3 #!/usr/bin/env python3 -u
import time, json, os, subprocess import time
from collections import deque import json
from datetime import datetime import os
import subprocess
import threading
import re
import psutil import psutil
import shutil
from collections import deque
from datetime import datetime, timezone
OUT_FILE="/var/www/encoder/metrics.json" # ---------------- CONFIGURATION ----------------
TMP_FILE=OUT_FILE+".tmp" OUT_FILE = "/var/www/encoder/metrics.json"
SAMPLE_INTERVAL=10.0 TMP_FILE = OUT_FILE + ".tmp"
HISTORY_SECONDS=15*60 SAMPLE_INTERVAL = 10.0
MAX_SAMPLES=int(HISTORY_SECONDS/SAMPLE_INTERVAL) HISTORY_SECONDS = 15 * 60
MAX_SAMPLES = int(HISTORY_SECONDS / SAMPLE_INTERVAL)
timestamps=deque(maxlen=MAX_SAMPLES) # ---------------- DEPENDENCY CHECK ----------------
cpu_hist=deque(maxlen=MAX_SAMPLES) if not shutil.which("intel_gpu_top"):
ram_hist=deque(maxlen=MAX_SAMPLES) raise RuntimeError("intel_gpu_top not installed or not in PATH")
gpu_hist=deque(maxlen=MAX_SAMPLES)
net_in_hist=deque(maxlen=MAX_SAMPLES)
net_out_hist=deque(maxlen=MAX_SAMPLES)
disk_read_hist=deque(maxlen=MAX_SAMPLES)
disk_write_hist=deque(maxlen=MAX_SAMPLES)
disk_percent_hist=deque(maxlen=MAX_SAMPLES)
_prev_net=psutil.net_io_counters() # ---------------- HISTORY BUFFERS ----------------
_prev_disk=psutil.disk_io_counters() keys = [
_prev_time=time.time() "timestamps", "cpu_percent", "ram_percent", "gpu_total", "gpu_render",
"gpu_video", "gpu_blitter", "gpu_videoenhance", "net_in_Bps",
"net_out_Bps", "disk_read_Bps", "disk_write_Bps", "disk_percent"
]
hist = {k: deque(maxlen=MAX_SAMPLES) for k in keys}
def igpu_percent(): _prev_net = psutil.net_io_counters()
_prev_disk = psutil.disk_io_counters()
_prev_time = time.time()
# Prime CPU measurement
psutil.cpu_percent(None)
gpu_data = {"total": 0.0, "render": 0.0, "video": 0.0, "blitter": 0.0, "ve": 0.0}
gpu_lock = threading.Lock()
# ---------------- GPU MONITOR THREAD ----------------
def gpu_monitor():
global gpu_data
cmd = ["intel_gpu_top", "-J", "-s", "1000"]
while True:
try: try:
out = subprocess.check_output( p = subprocess.Popen(
["intel_gpu_top","-J","-s","200","-o","-"], cmd,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
timeout=2 text=True,
bufsize=1
) )
line = out.decode().splitlines()[0]
data = json.loads(line)
engines = data.get("engines",{})
if not engines:
return 0.0
return round(max(v.get("busy",0) for v in engines.values()),2)
except Exception:
return 0.0
def sample_once(): buf = ""
global _prev_net,_prev_disk,_prev_time brace = 0
now=time.time()
iso=datetime.fromtimestamp(now).isoformat(timespec='seconds')
cpu=psutil.cpu_percent(interval=None) for chunk in iter(lambda: p.stdout.read(1), ""):
ram=psutil.virtual_memory().percent if chunk == "{":
gpu=igpu_percent() brace += 1
net=psutil.net_io_counters() if brace > 0:
disk=psutil.disk_io_counters() buf += chunk
if chunk == "}":
brace -= 1
if brace == 0 and buf.strip():
try: try:
disk_percent=psutil.disk_usage("/").percent obj = json.loads(buf)
except: engines = obj.get("engines", {})
disk_percent=0.0
elapsed=now-_prev_time if _prev_time else SAMPLE_INTERVAL r = v = b = e = 0.0
if elapsed<=0: elapsed=SAMPLE_INTERVAL
in_rate=int(((net.bytes_recv-_prev_net.bytes_recv)/elapsed)) for name, data in engines.items():
out_rate=int(((net.bytes_sent-_prev_net.bytes_sent)/elapsed)) busy = float(data.get("busy", 0.0))
n = name.lower()
read_rate=(disk.read_bytes-_prev_disk.read_bytes)/elapsed if "render" in n or "rcs" in n:
write_rate=(disk.write_bytes-_prev_disk.write_bytes)/elapsed r = max(r, busy)
elif "video" in n or "vcs" in n:
v = max(v, busy)
elif "blitter" in n or "bcs" in n:
b = max(b, busy)
elif "enhance" in n or "vecs" in n:
e = max(e, busy)
timestamps.append(iso) with gpu_lock:
cpu_hist.append(round(cpu,2)) gpu_data["render"] = r
ram_hist.append(round(ram,2)) gpu_data["video"] = v
gpu_hist.append(round(gpu,2)) gpu_data["blitter"] = b
net_in_hist.append(int(in_rate)) gpu_data["ve"] = e
net_out_hist.append(int(out_rate)) gpu_data["total"] = max(r, v, b, e)
disk_read_hist.append(int(read_rate))
disk_write_hist.append(int(write_rate))
disk_percent_hist.append(round(disk_percent,2))
_prev_net=net except Exception:
_prev_disk=disk pass
_prev_time=now
def write_json_atomic(): buf = ""
payload={
"timestamps":list(timestamps),
"cpu_percent":list(cpu_hist),
"ram_percent":list(ram_hist),
"igpu_percent":list(gpu_hist),
"net_in_Bps":list(net_in_hist),
"net_out_Bps":list(net_out_hist),
"disk_read_Bps":list(disk_read_hist),
"disk_write_Bps":list(disk_write_hist),
"disk_percent":list(disk_percent_hist),
"sample_interval":SAMPLE_INTERVAL,
"generated_at":datetime.utcnow().isoformat(timespec='seconds')+"Z"
}
with open(TMP_FILE,"w") as f: json.dump(payload,f)
os.replace(TMP_FILE,OUT_FILE)
p.wait()
except Exception:
time.sleep(2)
# ---------------- SAMPLING ----------------
def sample_once():
global _prev_net, _prev_disk, _prev_time
now = time.time()
elapsed = max(now - _prev_time, 0.1)
cpu = psutil.cpu_percent()
ram = psutil.virtual_memory().percent
net = psutil.net_io_counters()
disk = psutil.disk_io_counters()
in_r = (net.bytes_recv - _prev_net.bytes_recv) / elapsed
out_r = (net.bytes_sent - _prev_net.bytes_sent) / elapsed
read_r = (disk.read_bytes - _prev_disk.read_bytes) / elapsed
write_r = (disk.write_bytes - _prev_disk.write_bytes) / elapsed
with gpu_lock:
g = gpu_data.copy()
# stale GPU protection
if time.time() - _prev_time > SAMPLE_INTERVAL * 2:
g = {"total": 0, "render": 0, "video": 0, "blitter": 0, "ve": 0}
hist["timestamps"].append(datetime.now().isoformat(timespec='seconds'))
hist["cpu_percent"].append(round(cpu, 1))
hist["ram_percent"].append(round(ram, 1))
hist["net_in_Bps"].append(int(max(0, in_r)))
hist["net_out_Bps"].append(int(max(0, out_r)))
hist["disk_read_Bps"].append(int(max(0, read_r)))
hist["disk_write_Bps"].append(int(max(0, write_r)))
hist["disk_percent"].append(round(psutil.disk_usage('/').percent, 1))
hist["gpu_total"].append(round(g["total"], 1))
hist["gpu_render"].append(round(g["render"], 1))
hist["gpu_video"].append(round(g["video"], 1))
hist["gpu_blitter"].append(round(g["blitter"], 1))
hist["gpu_videoenhance"].append(round(g["ve"], 1))
_prev_net, _prev_disk, _prev_time = net, disk, now
# ---------------- MAIN LOOP ----------------
def main(): def main():
global _prev_net,_prev_disk,_prev_time threading.Thread(target=gpu_monitor, daemon=True).start()
_prev_net=psutil.net_io_counters()
_prev_disk=psutil.disk_io_counters()
_prev_time=time.time()
time.sleep(0.2)
while True: while True:
try: try:
sample_once() sample_once()
write_json_atomic()
except Exception as e: payload = {k: list(v) for k, v in hist.items()}
print("Sampler error:",e) payload.update({
"sample_interval": SAMPLE_INTERVAL,
"generated_at": datetime.now(timezone.utc).isoformat()
})
with open(TMP_FILE, "w") as f:
json.dump(payload, f)
os.replace(TMP_FILE, OUT_FILE)
except Exception:
pass
time.sleep(SAMPLE_INTERVAL) time.sleep(SAMPLE_INTERVAL)
if __name__=="__main__": # ---------------- ENTRY ----------------
if __name__ == "__main__":
main() main()
EOL
EOL
sudo mkdir -p /etc/srt/; sudo mkdir -p /etc/srt/;
cat > /etc/srt/srt.sh<< 'EOL' cat > /etc/srt/srt.sh<< 'EOL'

View File

@ -1,3 +1,9 @@
sudo apt update
sudo apt upgrade -y
sudo apt install -y apache2 php libapache2-mod-php vainfo ufw intel-media-va-driver-non-free libavcodec-extra mesa-utils i965-va-driver libmfx1 certbot intel-gpu-tools python3-certbot-nginx ffmpeg nginx v4l-utils python3-pip mpv libnginx-mod-rtmp alsa-utils vlan git zlib1g-dev php-zip php-curl
sudo pip3 install psutil --break-system-packages
sudo cp -r encoder/* /var/www/encoder/ sudo cp -r encoder/* /var/www/encoder/
sudo cp -r html/* /var/www/html/ sudo cp -r html/* /var/www/html/
sudo cp attempts.json /var/www/attempts.json sudo cp attempts.json /var/www/attempts.json