Skip to content

Commit 2e7d529

Browse files
chore: refactor
1 parent 7f09d11 commit 2e7d529

2 files changed

Lines changed: 48 additions & 54 deletions

File tree

README.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,21 @@ python app.py
2828
http://localhost:5000
2929
```
3030

31+
## Features
32+
33+
- Monitor the server stats like CPU, Memory, Disk, Network etc.
34+
- Check the network speed of the server. (Speed test)
35+
- Rate limit the speed test to avoid the abuse.
3136

3237
## Why not the docker image?
3338

3439
I have not created the docker image for this project because it requires the access to the host machine to get the server stats. So, it is not possible to get the server stats from the docker container.
3540

3641

3742
## Acknowledgments
38-
39-
- This project uses `speedtest-cli` for performing speed tests. `speedtest-cli` is licensed under the Apache License 2.0. For more details, please refer to its [GitHub repository](https://github.com/sivel/speedtest-cli).
40-
41-
- This project uses `psutil` for getting the system stats. `psutil` is licensed under the BSD 3-Clause "New" or "Revised" License. For more details, please refer to its [GitHub repository](https://github.com/giampaolo/psutil)
42-
43-
- This project uses `flask` for creating the web app. `flask` is licensed under the BSD 3-Clause "New" or "Revised" License. For more details, please refer to its [GitHub repository](https://github.com/pallets/flask)
44-
45-
- This project uses `chart.js` for creating the charts. `chart.js` is licensed under the MIT License. For more details, please refer to its [GitHub repository](https://github.com/chartjs/Chart.js)
43+
| Project | License | Repository |
44+
|---------|---------|------------|
45+
| `speedtest-cli` | Apache License 2.0 | [GitHub repository](https://github.com/sivel/speedtest-cli) |
46+
| `psutil` | BSD 3-Clause License | [GitHub repository](https://github.com/giampaolo/psutil) |
47+
| `flask` | BSD 3-Clause License | [GitHub repository](https://github.com/pallets/flask) |
48+
| `chart.js` | MIT License | [GitHub repository](https://github.com/chartjs/Chart.js) |

app.py

Lines changed: 37 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,6 @@ class SpeedTestResult(db.Model):
2525
def __repr__(self):
2626
return f'<SpeedTestResult {self.download_speed}, {self.upload_speed}, {self.ping}>'
2727

28-
def get_established_connections():
29-
connections = psutil.net_connections()
30-
ipv4_dict = set()
31-
ipv6_dict = set()
32-
33-
for conn in connections:
34-
if conn.status == 'ESTABLISHED':
35-
if '.' in conn.laddr.ip:
36-
ipv4_dict.add(conn.laddr.ip)
37-
elif ':' in conn.laddr.ip:
38-
ipv6_dict.add(conn.laddr.ip)
39-
40-
ipv4_dict = [ip for ip in ipv4_dict if ip.startswith('192.168')][0]
41-
42-
return ipv4_dict, ipv6_dict
43-
4428
def change_up_time_format(uptime):
4529
uptime_seconds = uptime.total_seconds()
4630
days = int(uptime_seconds // (24 * 3600))
@@ -50,35 +34,11 @@ def change_up_time_format(uptime):
5034
minutes = int(uptime_seconds // 60)
5135
return f"{days} days, {hours} hours, {minutes} minutes"
5236

53-
def get_system_info():
54-
info = {
55-
'username': os.getlogin(),
56-
'cpu_percent': round(psutil.cpu_percent(interval=1), 2),
57-
'memory_percent': round(psutil.virtual_memory().percent, 2),
58-
'disk_usage': round(psutil.disk_usage('/').percent, 2),
59-
'battery_percent': round(psutil.sensors_battery().percent) if psutil.sensors_battery() else "N/A",
60-
'cpu_core': psutil.cpu_count(),
61-
'boot_time': datetime.datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H:%M:%S"),
62-
'network_sent': round(psutil.net_io_counters().bytes_sent / (1024 ** 2), 2), # In MB
63-
'network_received': round(psutil.net_io_counters().bytes_recv / (1024 ** 2), 2), # In MB
64-
'process_count': len(psutil.pids()),
65-
'swap_memory': psutil.swap_memory().percent,
66-
'uptime': change_up_time_format(datetime.datetime.now() - datetime.datetime.fromtimestamp(psutil.boot_time())),
67-
'ipv4_connections': get_established_connections()[0],
68-
'ipv6_connections': get_established_connections()[1]
69-
}
70-
return info
71-
7237
def run_speedtest():
7338
try:
74-
# Run the speedtest and capture the output
7539
result = subprocess.run(['speedtest-cli'], capture_output=True, text=True, check=True)
76-
77-
# Extract relevant information from the output
7840
output_lines = result.stdout.splitlines()
79-
download_speed = None
80-
upload_speed = None
81-
ping = None
41+
download_speed, upload_speed, ping = None, None, None
8242

8343
for line in output_lines:
8444
if "Download:" in line:
@@ -100,12 +60,10 @@ def run_speedtest():
10060

10161
@app.route('/speedtest')
10262
def speedtest():
103-
# Check if the database has three or more entries in the last hour
10463
one_hour_ago = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
10564
recent_results = SpeedTestResult.query.filter(SpeedTestResult.timestamp > one_hour_ago).all()
10665

10766
if len(recent_results) < 3:
108-
# Run a new speed test and store the result
10967
speedtest_result = run_speedtest()
11068
if speedtest_result:
11169
new_result = SpeedTestResult(
@@ -117,14 +75,48 @@ def speedtest():
11775
db.session.commit()
11876
return render_template('speedtest_result.html', speedtest_result=speedtest_result, source="Actual Test")
11977
else:
120-
# Retrieve the latest result from the database
12178
latest_result = recent_results[-1]
122-
next_test_time = one_hour_ago + datetime.timedelta(hours=1)
79+
next_test_time = latest_result.timestamp + datetime.timedelta(hours=1)
12380
return render_template('speedtest_result.html',
12481
speedtest_result=latest_result,
12582
source="Database",
12683
next_test_time=next_test_time)
12784

85+
def get_system_info():
86+
ipv4_dict, ipv6_dict = get_established_connections()
87+
info = {
88+
'username': os.getlogin(),
89+
'cpu_percent': round(psutil.cpu_percent(interval=1), 2),
90+
'memory_percent': round(psutil.virtual_memory().percent, 2),
91+
'disk_usage': round(psutil.disk_usage('/').percent, 2),
92+
'battery_percent': round(psutil.sensors_battery().percent) if psutil.sensors_battery() else "N/A",
93+
'cpu_core': psutil.cpu_count(),
94+
'boot_time': datetime.datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H:%M:%S"),
95+
'network_sent': round(psutil.net_io_counters().bytes_sent / (1024 ** 2), 2), # In MB
96+
'network_received': round(psutil.net_io_counters().bytes_recv / (1024 ** 2), 2), # In MB
97+
'process_count': len(psutil.pids()),
98+
'swap_memory': psutil.swap_memory().percent,
99+
'uptime': change_up_time_format(datetime.datetime.now() - datetime.datetime.fromtimestamp(psutil.boot_time())),
100+
'ipv4_connections': ipv4_dict,
101+
'ipv6_connections': ipv6_dict
102+
}
103+
return info
104+
105+
def get_established_connections():
106+
connections = psutil.net_connections()
107+
ipv4_dict = set()
108+
ipv6_dict = set()
109+
110+
for conn in connections:
111+
if conn.status == 'ESTABLISHED':
112+
if '.' in conn.laddr.ip:
113+
ipv4_dict.add(conn.laddr.ip)
114+
elif ':' in conn.laddr.ip:
115+
ipv6_dict.add(conn.laddr.ip)
116+
117+
ipv4_dict = [ip for ip in ipv4_dict if ip.startswith('192.168')]
118+
return ipv4_dict[0] if ipv4_dict else "N/A", ipv6_dict
119+
128120
@app.route('/')
129121
def dashboard():
130122
system_info = get_system_info()
@@ -169,7 +161,6 @@ def system_health():
169161
return render_template('system_health.html', system_info=system_info)
170162

171163
if __name__ == '__main__':
172-
# Create the database tables if they don't exist
173164
with app.app_context():
174165
db.create_all()
175166
app.run(host='0.0.0.0', port=5000, debug=True)

0 commit comments

Comments
 (0)