Sign inSign up

weasts/servermon-weast

By weasts

•Updated over 1 year ago

A real-time, web-based dashboard to monitor your server's vital statistics.

Image
Web servers
Monitoring & observability
0

1.1K

weasts/servermon-weast repository overview

⁠Live Server Monitor Dashboard šŸ“ŠšŸ’»

source code⁠

A real-time, web-based dashboard to monitor your server's vital statistics. Built with Python, Flask, Socket.IO, psutil, and Docker for easy deployment. The frontend uses HTML, Tailwind CSS, and Chart.js for a modern, responsive, and themeable interface.

Dashboard Screenchot goes here

⁠✨ Features

  • šŸ–„ļø Live CPU Usage: Overall and per-core CPU utilization percentages, updated in real-time.
  • 🧠 Live RAM Usage: Total, used, and available memory (GB), along with usage percentage.
  • šŸ’¾ Live Storage Usage: Disk space utilization (total, used, free in GB, and percentage) for configurable mount points.
  • 🌐 Live Network Traffic:
    • Total bytes sent/received per network interface (MB).
    • Live send/receive rates per interface (Kbps).
    • Packet counts and error/drop statistics.
  • ā±ļø System Uptime & Load Average: Displays current server uptime and 1, 5, and 15-minute load averages.
  • šŸ“œ Live System Log Tailing: Tails and displays the latest lines from configured log files (defaults to dummy logs if none are specified).
  • šŸŽ® AMD GPU Monitoring (Basic): Placeholder for radeontop integration. Shows status message; can be extended to parse output from radeontop.
  • 🌐 Web-Based UI: Accessible from any modern web browser.
  • ⚔ Real-time Updates: Uses WebSockets (Socket.IO) for instant data updates without page reloads.
  • šŸŽØ Themeable Interface:
    • Defaults to a sleek Dark Mode.
    • Toggleable Light Mode available.
    • Theme preference is saved in browser localStorage.
  • šŸ“± Responsive Design: Adapts to different screen sizes (desktop, tablet, mobile).
  • āš™ļø Configurable Polling Interval: Adjust data refresh rate via an environment variable (POLLING_INTERVAL_MS). Default is 2000ms.
  • 🐳 Dockerized: Easy to build and deploy as a Docker container.

ā šŸ› ļø Tech Stack

  • Backend:
    • Python 3.10+
    • Flask (Web framework)
    • Flask-SocketIO (WebSocket communication)
    • psutil (System information gathering)
    • eventlet (Asynchronous server for Socket.IO)
  • Frontend:
    • HTML5
    • Tailwind CSS (Utility-first CSS framework)
    • Chart.js (JavaScript charting library)
    • Socket.IO Client (JavaScript library for WebSockets)
  • Deployment:
    • Docker

ā šŸ“‚ Project Structure

server-monitor-docker/
ā”œā”€ā”€ Dockerfile                # Defines the Docker image
ā”œā”€ā”€ requirements.txt          # Python dependencies
ā”œā”€ā”€ run.py                    # Entrypoint script for Docker to start the Flask-SocketIO app
ā”œā”€ā”€ backend/
│   ā”œā”€ā”€ app.py                # Flask application, Socket.IO handling, routes
│   └── collectors.py         # Data collection logic using psutil
└── frontend/
    └── index.html            # Main HTML page with CSS and JavaScript

ā šŸš€ Getting Started

⁠Prerequisites
  • Docker: Ensure Docker is installed and running on your system. Get Docker⁠
  • Git (Optional): For cloning if this project is in a Git repository.
⁠Installation & Setup
  1. Create Project Directory: If you haven't cloned a repository, create the project directory structure as shown above.

    mkdir -p server-monitor-docker/backend
    mkdir -p server-monitor-docker/frontend
    cd server-monitor-docker
    
  2. Populate Files: Place the code files (Dockerfile, requirements.txt, run.py, backend/app.py, backend/collectors.py, frontend/index.html) into their respective directories as outlined in the "Project Structure" section.

    (Ensure you have the correct versions of these files.)


⁠🐳 Docker Instructions

⁠Building the Docker Image

Navigate to the root of the project directory (server-monitor-docker/) in your terminal and run:

docker build -t server-monitor-app .

This command builds a Docker image tagged as server-monitor-app using the Dockerfile in the current directory.

⁠Running the Docker Container
⁠Basic Run

To run the container with default settings (2-second polling, monitoring container's root filesystem, and dummy logs generated by the application):

docker run -d -p 5000:5000 --name live-server-monitor --init server-monitor-app
  • -d: Run in detached mode (background).
  • -p 5000:5000: Map port 5000 of the host to port 5000 of the container (Flask app default port).
  • --name live-server-monitor: Assign a name to the container for easier management.
  • --init: Runs an init process as PID 1 in the container, which helps manage signals and zombie processes. Recommended for applications like this.
⁠Running with Custom Configurations

You can customize the monitor's behavior using environment variables and Docker volume mounts:

Environment Variables:

  • POLLING_INTERVAL_MS: Data refresh interval in milliseconds (e.g., 1000 for 1 second, 5000 for 5 seconds). Default: 2000. Minimum effective interval is around 500ms.
  • STORAGE_PATHS: Comma-separated list of absolute paths inside the container to monitor for storage usage. Example: STORAGE_PATHS="/,/mnt/data,/mnt/backups". If not set, defaults to /host_root if it exists, otherwise /.
  • LOG_CONFIG: Comma-separated list of Name:Path pairs for log files to monitor. Name is the display name in the UI, Path is the absolute path inside the container. Example: LOG_CONFIG="Syslog:/var/log/syslog_host,App Log:/app/my_app_host.log". If not set, defaults to dummy logs created by the application.
  • FLASK_DEBUG: Set to 1 for Flask debug mode, 0 for production. Default is 0 as set in the Dockerfile. run.py uses this to toggle debug mode for socketio.run.
  • FLASK_RUN_HOST: Host for the Flask app. Default is 0.0.0.0 as set in Dockerfile.
  • FLASK_RUN_PORT: Port for the Flask app. Default is 5000 as set in Dockerfile.

Volume Mounts (for monitoring host system resources):

  • To monitor host storage, mount host directories into the container and specify the container paths in STORAGE_PATHS.
  • To monitor host log files, mount them into the container and specify the container paths in LOG_CONFIG.

Example: Advanced Run Command

This example runs the monitor with:

  • 3-second polling.
  • Monitors the host's root (/) and /mnt/important_data directories for storage.
  • Tails the host's /var/log/syslog and /var/log/auth.log.
docker run -d \
    -p 5000:5000 \
    --name live-server-monitor \
    --init \
    -e POLLING_INTERVAL_MS=3000 \
    -e STORAGE_PATHS="/host_root,/host_data" \
    -e LOG_CONFIG="Host Syslog:/mnt/logs/syslog,Host Auth Log:/mnt/logs/auth.log" \
    -v /:/host_root:ro \
    -v /mnt/important_data:/host_data:ro \
    -v /var/log/syslog:/mnt/logs/syslog:ro \
    -v /var/log/auth.log:/mnt/logs/auth.log:ro \
    server-monitor-app
  • :ro makes the mounted volumes read-only from the container's perspective, which is recommended for monitoring to prevent accidental changes to host files.
⁠Accessing the Monitor

Once the container is running, open your web browser and navigate to:

http://localhost:5000

(If running Docker on a remote machine or VM, replace localhost with the machine's IP address).


ā šŸ”§ Customization & Modification

⁠Polling Interval

Set the POLLING_INTERVAL_MS environment variable during docker run. Example: -e POLLING_INTERVAL_MS=1000 for 1-second updates. The minimum effective interval is around 500ms due to backend and frontend constraints.

⁠Monitored Storage
  1. Modify the -v /host/path:/container/path:ro Docker run option to mount the desired host storage directories.
  2. Set the STORAGE_PATHS environment variable to a comma-separated list of the container paths you've mapped. Example: -v /data/drive1:/mnt/drive1_data:ro -e STORAGE_PATHS="/,/mnt/drive1_data"
⁠Monitored Logs
  1. Modify the -v /host/logfile.log:/container/logfile.log:ro Docker run option to mount the desired host log files.
  2. Set the LOG_CONFIG environment variable. Example: -v /var/log/my_app.log:/applogs/app.log:ro -e LOG_CONFIG="My Application Log:/applogs/app.log"
⁠Frontend Styling & Appearance
  • Tailwind CSS: Styles are primarily managed using Tailwind CSS classes directly in frontend/index.html. You can modify these classes to change the appearance.
  • Theme Colors: Dark and light mode colors are defined using CSS custom properties (variables) in the <style> section of frontend/index.html. Adjust these variables (e.g., --bg-color-primary, --text-color-accent) to change the theme.
  • Charts: Chart appearance (colors, types) can be modified in the JavaScript section of frontend/index.html, specifically in the createTimeSeriesChart function and where charts are initialized.
⁠Backend Logic
  • Data Collection (backend/collectors.py): If you need to add new metrics or change how existing ones are collected, this is the primary file to modify. It uses the psutil library extensively.
  • Application & WebSocket Handling (backend/app.py): This file handles the Flask routes, Socket.IO events, and manages the background thread for emitting stats. Modifications here would be for changing API behavior or WebSocket communication. The eventlet.monkey_patch() is crucial and is called in run.py.

ā šŸŽ® GPU Monitoring

⁠AMD GPU (Radeontop) Integration

The current radeontop integration is a basic placeholder that attempts to run radeontop -l 1 -d - and parse its text output.

To enable or improve it:

  1. Install radeontop in Docker: Ensure radeontop is included in the apt-get install command in your Dockerfile.
  2. Device Access: You'll likely need to pass AMD GPU devices to the container using --device flags during docker run (e.g., --device=/dev/dri/card0 --device=/dev/kfd). This can be hardware-specific.
  3. Permissions: The container might require elevated privileges or specific user group memberships to access GPU devices and radeontop.
  4. Modify backend/collectors.py:
    • Update the get_radeontop_data() function.
    • The current implementation uses subprocess.run to execute radeontop and includes a basic parser parse_radeontop_single_line_output for a specific output format. You might need to adjust the radeontop command options or the parsing logic (parse_radeontop_single_line_output) depending on your radeontop version and the desired metrics.
    • This is an advanced task and may require significant effort depending on the desired level of detail and compatibility with different radeontop versions.
⁠NVIDIA GPU Monitoring (Possibility)

Monitoring NVIDIA GPUs typically requires using NVIDIA's own tools, primarily nvidia-smi (NVIDIA System Management Interface).

Conceptual Steps to Add NVIDIA GPU Monitoring:

  1. NVIDIA Container Toolkit: The host system and Docker need to be configured with the NVIDIA Container Toolkit⁠. This allows Docker containers to access NVIDIA GPU resources.
  2. Modify Dockerfile:
    • It's generally better to use an NVIDIA-provided base image (e.g., nvidia/cuda:tag-base) as these come with necessary drivers and libraries.
    • If not using an NVIDIA base image, you would need to ensure nvidia-smi is accessible within the container, which might involve installing NVIDIA drivers and utilities. This is complex and error-prone; the NVIDIA Container Toolkit on the host is the preferred way as it makes GPUs available to standard containers.
  3. Update backend/collectors.py:
    • Create a new function, e.g., get_nvidia_gpu_data().
    • Inside this function, use subprocess.run to execute nvidia-smi commands.
      • Example: nvidia-smi --query-gpu=timestamp,name,temperature.gpu,utilization.gpu,utilization.memory,memory.total,memory.used,memory.free --format=csv,noheader,nounits
    • Parse the CSV output from nvidia-smi.
    • Structure the parsed data into a dictionary similar to other collectors.
  4. Update backend/app.py:
    • Call get_nvidia_gpu_data() within get_all_stats() and add its output to the current_stats dictionary.
  5. Update frontend/index.html:
    • Add new sections and/or charts to display NVIDIA GPU metrics.
    • Update the JavaScript to handle and render the new GPU data.
  6. Docker Run Command:
    • When running the Docker container, you'll need to include the --gpus all flag (or specify particular GPUs) if using the NVIDIA Container Toolkit.
    docker run -d -p 5000:5000 --name live-server-monitor --init --gpus all server-monitor-app
    

Challenges:

  • NVIDIA Drivers & Toolkit: Correct setup on the host is crucial.
  • Parsing nvidia-smi: While nvidia-smi offers CSV output, robust parsing is still needed.
  • Container Privileges: Ensuring the container has the right access if not using the NVIDIA Container Toolkit approach.

⁠🩺 Troubleshooting

  • Container not starting/exiting immediately:

    • Check Docker logs: docker logs live-server-monitor (or your container name). Look for Python errors, issues with environment variables, or problems in run.py or backend/app.py during startup.
    • Ensure the CMD in your Dockerfile is correct (e.g., CMD ["python", "run.py"]).
    • Verify that eventlet.monkey_patch() is called at the very beginning of run.py.
  • No data on webpage / "Connection Error" / "Disconnected":

    • Verify container is running: docker ps. If not listed, check docker ps -a and then docker logs <container_id_or_name>.
    • Check Docker logs for backend errors: docker logs live-server-monitor. Pay attention to errors from collectors.py or app.py.
    • Open browser's developer console (usually F12):
      • Look for JavaScript errors in the "Console" tab.
      • Check the "Network" tab for WebSocket connection issues (often shown as pending or failing socket.io requests).
    • Firewall: Ensure no firewall is blocking port 5000 (or the port you've mapped) on the host or between your client machine and the Docker host.
    • CORS Issues: The backend app.py is configured with cors_allowed_origins="*", which should generally prevent CORS issues. If you've modified this, ensure your frontend's origin is allowed.
    • POLLING_INTERVAL_MS too low: If set extremely low (e.g., below 100ms), it might overload the server or client. The application enforces a minimum of 500ms.
  • Incorrect storage/log paths:

    • Double-check volume mounts (-v): Ensure the host path exists and the container path matches what's used in STORAGE_PATHS or LOG_CONFIG. Paths are case-sensitive.
    • Check environment variables (-e): Verify STORAGE_PATHS and LOG_CONFIG are correctly formatted (comma-separated, Name:Path for logs).
    • Permissions: Ensure the user inside the Docker container (usually root, unless specified otherwise in Dockerfile) has read access to the mounted volumes. The :ro flag helps prevent writes but read access is still needed.
    • Default Paths: If environment variables are not set or invalid, the application defaults to /host_root or / for storage, and dummy logs for log files. Check backend/app.py logs for warnings about invalid configurations.
  • Data not updating or updating erratically:

    • Check docker logs live-server-monitor for errors in the background_thread in backend/app.py or within get_all_stats in collectors.py.
    • Ensure socketio.sleep() is used in the background_thread rather than time.sleep() for proper cooperative multitasking with eventlet. (This is correctly implemented in the provided app.py).
  • CPU usage seems off or slow to update:

    • psutil.cpu_percent(interval=0.1) is used. A very short interval can sometimes be less accurate or slightly delayed. The polling interval of the app itself (POLLING_INTERVAL_MS) is the main driver for UI updates.
  • Network rates are zero or incorrect:

    • The network rate calculation in get_network_traffic depends on the difference between two consecutive calls. The first data point will show 0 rates. Ensure the polling interval is not too short for meaningful deltas to be calculated.
  • AMD GPU (Radeontop) section shows "Radeontop data not available" or error:

    • radeontop not installed: Add radeontop to apt-get install in Dockerfile.
    • Device not passed to container: Use --device=/dev/dri/cardX and potentially --device=/dev/kfd with docker run.
    • Permissions: The container might need specific privileges.
    • radeontop command or parsing error: Check the status message and raw output sample in the UI. The get_radeontop_data function in backend/collectors.py captures errors. You might need to adjust the command or the parse_radeontop_single_line_output function if your radeontop version has different output.
  • "Error creating dummy log" or "Error writing to or trimming dummy log":

    • This usually indicates a permissions issue within the container for the path /app/dummy_logX.log or that the filesystem is read-only where it's trying to write. The default Dockerfile should allow this, but custom base images or security settings might interfere.

ā šŸ¤ Contributing

Contributions, issues, and feature requests are welcome!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

ā šŸ“œ License

Distributed under the GNU General Public License Version 3, 29 June 2007. You can find the full license text here⁠.


Tag summary

Content type

Image

Digest

sha256:6538b93d2…

Size

55.2 MB

Last updated

over 1 year ago

docker pull weasts/servermon-weast