Server stats for a remote server #398
Replies: 5 comments 5 replies
-
I have been able to solve this by writing a simple flask app: import platform
import psutil
import time
from flask import Flask, jsonify, request, abort
app = Flask(__name__)
VALID_TOKEN = "your-secret-token"
def get_system_info():
info = {
"host_info_is_available": True,
"boot_time": int(psutil.boot_time()),
"hostname": platform.node(),
"platform": platform.system(),
"cpu": {
"load_is_available": True,
"load1_percent": int(psutil.getloadavg()[0] * 100),
"load15_percent": int(psutil.getloadavg()[2] * 100),
"temperature_is_available": True,
"temperature_c": get_cpu_temperature()
},
"memory": {
"memory_is_available": True,
"total_mb": psutil.virtual_memory().total // (1024 * 1024),
"used_mb": psutil.virtual_memory().used // (1024 * 1024),
"used_percent": int(psutil.virtual_memory().percent),
"swap_is_available": True,
"swap_total_mb": psutil.swap_memory().total // (1024 * 1024),
"swap_used_mb": psutil.swap_memory().used // (1024 * 1024),
"swap_used_percent": int(psutil.swap_memory().percent)
},
"mountpoints": [
{
"path": partition.mountpoint,
"name": partition.mountpoint,
"total_mb": psutil.disk_usage(partition.mountpoint).total // (1024 * 1024),
"used_mb": psutil.disk_usage(partition.mountpoint).used // (1024 * 1024),
"used_percent": int(psutil.disk_usage(partition.mountpoint).percent)
}
for partition in psutil.disk_partitions()
if not partition.mountpoint.startswith(("/snap", "/boot/efi"))
]
}
return info
def get_cpu_temperature():
try:
with open("/sys/class/thermal/thermal_zone0/temp", "r") as f:
temp = int(f.read().strip()) / 1000.0
return int(temp)
except FileNotFoundError:
return 0
@app.route('/api/sysinfo/all', methods=['GET'])
def sysinfo():
token = request.headers.get('Authorization')
if token != f"Bearer {VALID_TOKEN}":
abort(401, description="Unauthorized: Invalid token")
info = get_system_info()
return jsonify(info)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080) You can then run it by [Unit]
Description=Glance server status
After=network.target
[Service]
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/glance-serverstatus
ExecStart=/bin/python3 /home/ubuntu/glance-serverstatus/app.py
Restart=always
[Install]
WantedBy=multi-user.target Then, you can use the serverstatus widget like normal: - type: server-stats
servers:
- type: local
name: Local
- type: remote
name: Remote
url: http://remote.server.com:8080
token: your-secret-token I can package it inside of a Docker container for easier setup if need arises. |
Beta Was this translation helpful? Give feedback.
-
I packaged it inside a Docker container, you can set it up as: git clone https://github.com/kubakubakuba/glance-serverstatus-agent.git
cd glance-serverstatus-agent
nano .env
docker compose build
docker compose up -d |
Beta Was this translation helpful? Give feedback.
-
Thanks for creating this. This is working on the remote machine and I can pull stats manually using the /api/sysinfo/all endpoint. However, on the host running Glance, trying to use the Server Stats widget I'm getting this error trying to connect: 2025/03/10 17:12:51 WARN Getting remote system info: json: cannot unmarshal number 556 into Go struct field .cpu.load15_percent of type uint8 Any ideas how to resolve this? EDIT: I figured out the issue. The raw values returned by psutil.getloadavg() are not percentages. They represent the actual number of processes contending for CPU time. To get a percentage, you need to divide the load average by the number of CPU cores. For example, on a 4-core system, a load average of 4.0 means 100% utilization, while a value of 8.0 indicates that the system is oversubscribed, with twice as many processes ready to run as there are cores. To resolve this I changed the code as follows:
Now it works great! |
Beta Was this translation helpful? Give feedback.
-
This also has some issues dealing with volumes/mount points when Dockerized - it doesn't seem to show the correct data on Glance's dashboard unless I specifically point to the mount point "/app" like this
I also tried simply setting psutil.disk_partitions(all=True), which does send information about the mounted volumes but isn't correctly parsed by Glance. Only hard coding the mount point seems to work even though that is very janky. Someone else should be able to come up with a more robust solution that can properly account for volume mount points set in the docker-compose. |
Beta Was this translation helpful? Give feedback.
-
Hi, I had to make a change to the memory section for "used_mem", it seemed to be showing me the incorrect ram used. Inside or out of the docker. I changed the below for me - from, to: "used_mb": psutil.virtual_memory().used // (1024 * 1024), to "used_mb": psutil.virtual_memory().total // (1024 * 1024) - psutil.virtual_memory().available // (1024 * 1024), That gave me the correct ram used. The psutil.virtual_memory().used did not show the correct ram used due to cache/buffers or so.. The "available" shows the true used value. I ran this in a docker and via systemd too. Cheers! |
Beta Was this translation helpful? Give feedback.
-
Hello, is the server-stats widget available for remote servers? The
https://github.com/glanceapp/agent
link seems dead.Beta Was this translation helpful? Give feedback.
All reactions