Skip to content

Commit 9a47e88

Browse files
Merge pull request #32 from codeperfectplus/features/prometheus_support
Features/prometheus support
2 parents cf0d7a0 + e1a8c91 commit 9a47e88

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2675
-862
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

+8-12
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,27 @@ assignees: ''
88
---
99

1010
**Describe the bug**
11+
1112
A clear and concise description of what the bug is.
1213

1314
**To Reproduce**
15+
1416
Steps to reproduce the behavior:
15-
1. Go to '...'
16-
2. Click on '....'
17-
3. Scroll down to '....'
18-
4. See error
1917

2018
**Expected behavior**
19+
2120
A clear and concise description of what you expected to happen.
2221

2322
**Screenshots**
23+
2424
If applicable, add screenshots to help explain your problem.
2525

26-
**Desktop (please complete the following information):**
26+
**(please complete the following information):**
27+
2728
- OS: [e.g. iOS]
2829
- Browser [e.g. chrome, safari]
29-
- Version [e.g. 22]
30-
31-
**Smartphone (please complete the following information):**
32-
- Device: [e.g. iPhone6]
33-
- OS: [e.g. iOS8.1]
34-
- Browser [e.g. stock browser, safari]
35-
- Version [e.g. 22]
30+
- Systemguard version [e.g. 22]
3631

3732
**Additional context**
33+
3834
Add any other context about the problem here.

.github/ISSUE_TEMPLATE/feature_request.md

+4
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@ assignees: ''
88
---
99

1010
**Is your feature request related to a problem? Please describe.**
11+
1112
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
1213

1314
**Describe the solution you'd like**
15+
1416
A clear and concise description of what you want to happen.
1517

1618
**Describe alternatives you've considered**
19+
1720
A clear and concise description of any alternative solutions or features you've considered.
1821

1922
**Additional context**
23+
2024
Add any other context or screenshots about the feature request here.

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,8 @@ cython_debug/
164164

165165
predefine_user.json
166166
src/assets/predefine_user.json
167+
168+
influxdb_data
169+
prometheus_config
170+
*.yml
171+
prometheus_config/prometheus.yml

README.md

+10-16
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
System Guard is a Flask app designed to monitor server stats such as CPU, Memory, Disk, and Network. It also provides real-time monitoring capabilities which can be useful for system administrators, developers, and DevOps engineers to keep track of their server's performance and troubleshoot issues. The app uses the `psutil` library to retrieve system stats and the `speedtest-cli` library to perform a network speed test.
44

5+
56
## Features 🚀
67

78
- Lightweight, open-source, and free to use with a straightforward installation process, out-of-the-box monitoring solution.
@@ -18,22 +19,15 @@ System Guard is a Flask app designed to monitor server stats such as CPU, Memory
1819
- Role-based dashboards tailored for Developer, Admin, IT Manager, and Manager roles (upcoming feature).
1920
- Update security updates with a single click or automatically update to the latest version to simplify maintenance.
2021

21-
## Old Features 🚀
22-
23-
- Administrators can manage user accounts by creating, updating, or deleting users.
24-
- Admin-level access is required for configuring settings, managing users, and adjusting security and notification - preferences.
25-
- Historical performance data can be viewed as charts, aiding in trend analysis.
26-
- Supports network speed testing directly from the server.
27-
- Provides the ability to terminate resource-heavy processes with a single command.
28-
- Real-time server metric monitoring keeps data consistently updated.
29-
- The interface is responsive and optimized for various devices including mobile, tablets, and desktops.
30-
- The system can automatically update to the latest version to simplify maintenance.
31-
- Installation can be done quickly via a bash script for easy setup.
32-
- Notifications are sent to users and admins when a process is manually terminated.
33-
- Offers website monitoring tasks that trigger email alerts when a website becomes unavailable.
34-
- Configurable email alerts for various actions across the server.
35-
- Option to download historical data in CSV format for detailed analysis (upcoming feature).
36-
- Server status monitoring with alerts for server downtime or recovery (upcoming feature).
22+
## Architecture 🏗️
23+
24+
![SystemGuard-Architecture](/src/docs/images/SystemGuard-Architecture.jpg)
25+
26+
## Tech Stack 🛠️
27+
28+
- **Frontend**: JavaScript, Bootstrap, Chart.js, Grafana
29+
- **Backend**: Python, Flask, SQLAlchemy, SQLite, Prometheus, InfluxDB
30+
- **Monitoring**: psutil, speedtest-cli, nmap, netstat
3731

3832
## Get started 🛠️
3933

app.py

+4-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
from src.config import app
22
from src import routes
3-
from src.background_task import start_website_monitoring, monitor_settings
4-
import os
3+
from src.background_task import start_background_tasks
4+
5+
# Start the background tasks
6+
start_background_tasks()
57

6-
# background thread to monitor system settings changes
7-
print("FLASK_ENV: ", os.getenv('FLASK_ENV'))
8-
if os.getenv('FLASK_ENV') == 'production':
9-
monitor_settings() # Starts monitoring for system logging changes
10-
start_website_monitoring() # Starts pinging active websites
118

129
if __name__ == "__main__":
1310
app.run(host="0.0.0.0", port=5000, debug=True)

requirements.txt

+10-1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,13 @@ watchdog==5.0.2
2323
requests==2.32.3
2424

2525
# Speedtest CLI for testing internet speed
26-
speedtest-cli==2.1.3
26+
speedtest-cli==2.1.3
27+
28+
# prometheus client for monitoring
29+
prometheus_client==0.20.0
30+
31+
# influxdb-client, optional for writing metrics to InfluxDB
32+
# influxdb-client==1.46.0
33+
34+
# pyyaml for parsing YAML configuration files
35+
pyyaml==6.0.2

setup.sh

+9-2
Original file line numberDiff line numberDiff line change
@@ -853,10 +853,12 @@ start_server() {
853853

854854
# Install function
855855
install() {
856+
create_dir "$EXTRACT_DIR"
857+
# PROMETHEUS_INSTALL_SCRIPT
856858
message_box "$APP_NAME Installer $INSATLLER_VERSION" 0
857-
message_box "Welcome on board: $(echo "$USER_NAME" | sed 's/.*/\u&/')" 3
859+
message_box "Welcome on board: $(echo "$USER_NAME" | sed 's/.*/\u&/')" 0
858860
check_dependencies
859-
create_dir "$EXTRACT_DIR"
861+
860862
message_box "Choose the installation method\nNote: Release is recommended for production use." 0
861863
message_box "1. Release (More Stable Version)\n2. Git Repository (Pre-Release Version)\n3. Source Code (Current Directory)" 0
862864

@@ -878,6 +880,11 @@ install() {
878880
exit 1
879881
;;
880882
esac
883+
PROMETHEUS_INSTALL_SCRIPT=$(find "$EXTRACT_DIR" -name prometheus.sh) || {
884+
log "ERROR" "Prometheus installation script not found."
885+
exit 1
886+
}
887+
sudo -u "$USER_NAME" bash "$PROMETHEUS_INSTALL_SCRIPT"
881888
start_server
882889
message_box "The $APP_NAME server is running at $HOST_URL" 0
883890
# open_browser

src/background_task/__init__.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,19 @@
1+
import os
12
from src.background_task.monitor_website import start_website_monitoring
23
from src.background_task.log_system_info import monitor_settings
4+
from src.background_task.external_monitoring import fetch_file_metrics_task
5+
from src.logger import logger
36

4-
__all__ = ["start_website_monitoring", "monitor_settings"]
7+
8+
9+
def start_background_tasks():
10+
"""
11+
Starts the background tasks for the application.
12+
"""
13+
if os.getenv('FLASK_ENV') == 'production':
14+
logger.info("Starting background tasks for production environment.")
15+
start_website_monitoring()
16+
fetch_file_metrics_task()
17+
monitor_settings()
18+
else:
19+
logger.info("Background tasks are not started in development environment.")
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from flask import Flask, Response
2+
from prometheus_client import Gauge, generate_latest
3+
import os
4+
import time
5+
from src.models import ExternalMonitornig
6+
from src.config import app
7+
import threading
8+
from src.logger import logger
9+
10+
# Define a Gauge metric with a label 'key' to store multiple values from the file
11+
file_metric = Gauge('external_metrics', 'Value read from file for each key', ['key'])
12+
13+
def read_file_and_update_metric(file_path: str) -> None:
14+
"""Reads a file and updates metrics based on its content."""
15+
if os.path.exists(file_path):
16+
with open(file_path, 'r') as file:
17+
for line in file:
18+
try:
19+
key, value = line.strip().split(':')
20+
file_metric.labels(key.strip()).set(float(value.strip()))
21+
except ValueError as ve:
22+
logger.error(f"Value error processing line '{line}': {ve}")
23+
except Exception as e:
24+
logger.error(f"Error processing line '{line}': {e}")
25+
else:
26+
logger.warning(f"File {file_path} does not exist")
27+
28+
def fetch_file_metrics(sleep_duration: int = 5) -> None:
29+
"""Background task to read file paths from the database and update metrics."""
30+
while True:
31+
with app.app_context():
32+
file_paths = ExternalMonitornig.query.all()
33+
current_keys = {sample.labels['key'] for sample in file_metric.collect()[0].samples}
34+
new_keys = set()
35+
36+
for file_path in file_paths:
37+
logger.info(f"Reading file: {file_path.file_path}")
38+
read_file_and_update_metric(file_path.file_path)
39+
new_keys.update({key.strip() for line in open(file_path.file_path) for key in line.split(':')[0].strip()})
40+
41+
# Remove metrics for keys that are no longer in the database
42+
for key in current_keys:
43+
if key not in new_keys:
44+
file_metric.remove(key)
45+
46+
time.sleep(sleep_duration)
47+
48+
def fetch_file_metrics_task() -> None:
49+
"""Starts the background task in a separate thread."""
50+
thread = threading.Thread(target=fetch_file_metrics)
51+
thread.daemon = True
52+
thread.start()

0 commit comments

Comments
 (0)