A simple system and network monitoring solution with a built-in server for remote monitoring capabilities.
View an example web client dashboard here
- Asynchronous Data Collection: Efficient, non-blocking data collection.
- Real-Time Monitoring: Transmits live system and network statistics.
- System Statistics: Provides CPU, memory, and disk usage, uptime, and top processes.
- Network Statistics: Monitors data sent and received on network interfaces.
- Websocket Server: Includes a tornado server for remote monitoring (built-in and standalone).
The desktop application is built with Tkinter, Python's binding to the Tk GUI toolkit, it consists of:
- Core logic: The collection of modules, scripts and binaries that are used to provide the functionality.
- The server: Used by the app to receive data to display, but can also be run as its own standalone service.
The server manages the execution of the monitoring scripts, using multiple threads managed through an executor to retrieve data asynchronously and mitigate blocking operations from calls to read system data.
The server is built with tornado, a scalable, non-blocking web server designed to handle a large number of concurrent connections. It's non-blocking nature makes it ideal for building real-time services.
While the server is included in the desktop application, a standalone version is provided for people who want to build their own clients, or for people who want to port-forward and setup remote monitoring.
Three standard HTTP endpoints are provided:
Retrieves system monitoring information
- CPU: Temperature, Frequency, Usage
- Disk: Used, Free, Total, Usage
- Mem: Used, Free, Total, Usage
- User: Logged in user
- Platform: Distribution, Kernel, Uptime
- Processes Top 10 processes by memory usage
A small note on CPU temperature monitoring on Windows: reading temperature sensors requires elevated privileges, in order to display your CPU temperature on Windows, you'll need to run PSMonitor as an administrator.
PSMonitor uses a tiny binary executable called libwincputemp, which is part of this project.
Retrieves network monitoring information:
- Interfaces: Visible network interfaces
- Wireless: Name, Quality, Channel, Encryption, Address, Signal
- Statistics: For each interface: MB sent, MB received, packets sent, packets received, errors receiving packets, error sending packets, dropout rate.
Renders a simple dashboard to check or test the server.
Creates a worker to manage the execution of monitoring scripts. Responds with a worker ID which is then used in the websocket connection endpoint URL (below).
A single websocket endpoint is provided.
- Creates the websocket connection, data immediately begins being sent through the connection.
If you would like to run the standalone server as a managed process, you can use the systemd service file provided.
-
Copy the service file and make any necessary changes:
sudo cp ./psmonitor.service /etc/systemd/system/
-
Reload the daemon to recognize the new service:
sudo systemctl daemon-reload
-
Start the service:
sudo systemctl start psmonitor
Alternatively, you could use supervisor or something similar.
To connect to the WebSocket server, you can use any WebSocket client. Here is an example of how to connect using JavaScript:
-
Retrieve the assigned worker:
const client = await fetch(`http://<server-address>`, { method: 'POST', body: { connection: 'monitor' } }); const worker = await client.json()
-
Open the WebSocket connection and retrieve data:
const url = `ws://<server-address>:<port>/ws?id=${worker.id}`; connection = new WebSocket(url); connection.onopen = () => { log.write('event', 'websocket is connected'); } connection.onmessage = (response) => { const data = JSON.parse(response.data); }
You can also use WebSocket clients in other programming languages, such as Python:
-
Retrieve an assigned worker:
import requests response = requests.post('http://<server-address>', json={'connection': 'monitor'}) worker = response.json()
-
Open the WebSocket connection and retrieve data:
import asyncio import websockets async def connect(): uri = f"ws://<server-address>:<port>/ws?id={worker['id']}" async with websockets.connect(uri) as websocket: async for message in websocket: print(message) asyncio.run(connect())
You can use the quick dashboard located at public/web.html
for further testing and exploration.
I hope you like it!
This software is open-sourced software licensed under the MIT license.
This software uses LibreHardwareMonitorLib.dll in order to provide CPU temperature readings on Windows. The DLL forms part of the libwincputemp program which is part of this project. LibreOpenHardwareMonitor is licensed under MPL 2.0, a copy of the license can be found in the third-party licenses file.