-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
257 lines (232 loc) · 8.7 KB
/
app.py
File metadata and controls
257 lines (232 loc) · 8.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
from flask import Flask, render_template, Response
from influx_metrics import influx_metrics
import time
import logging
import traceback
import json
import psutil
import threading
import queue
import platform
import subprocess
# Configure logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
app = Flask(__name__)
# Create a thread-safe queue for metrics
metrics_queue = queue.Queue(maxsize=50)
def get_network_io():
"""Get network I/O statistics"""
try:
# Get the primary network interface
net_io = psutil.net_io_counters()
return {
'bytes_sent': net_io.bytes_sent / (1024 * 1024), # Convert to MB
'bytes_recv': net_io.bytes_recv / (1024 * 1024), # Convert to MB
'packets_sent': net_io.packets_sent,
'packets_recv': net_io.packets_recv
}
except Exception as e:
logger.error(f"Network metrics error: {e}")
return {
'bytes_sent': 0,
'bytes_recv': 0,
'packets_sent': 0,
'packets_recv': 0
}
def get_disk_io():
"""Get disk I/O statistics"""
try:
disk_io = psutil.disk_io_counters()
return {
'read_bytes': disk_io.read_bytes / (1024 * 1024), # Convert to MB
'write_bytes': disk_io.write_bytes / (1024 * 1024), # Convert to MB
'read_count': disk_io.read_count,
'write_count': disk_io.write_count
}
except Exception as e:
logger.error(f"Disk metrics error: {e}")
return {
'read_bytes': 0,
'write_bytes': 0,
'read_count': 0,
'write_count': 0
}
def collect_metrics_thread():
"""Background thread to collect system metrics"""
while True:
try:
# Collect system metrics
cpu_percent = psutil.cpu_percent()
memory = psutil.virtual_memory()
network_io = get_network_io()
disk_io = get_disk_io()
# Create metrics payload
metrics = {
'timestamp': time.time(),
'cpu_usage': cpu_percent,
'memory_usage': memory.percent,
'memory_total': memory.total / (1024 * 1024 * 1024), # Convert to GB
'memory_available': memory.available / (1024 * 1024 * 1024), # Convert to GB
'memory_used': memory.used / (1024 * 1024 * 1024), # Convert to GB
'network_bytes_sent': network_io['bytes_sent'],
'network_bytes_recv': network_io['bytes_recv'],
'disk_read_bytes': disk_io['read_bytes'],
'disk_write_bytes': disk_io['write_bytes']
}
# Write to InfluxDB
influx_metrics.collect_system_metrics()
# Add to queue, remove oldest if full
if metrics_queue.full():
metrics_queue.get()
metrics_queue.put(metrics)
# Wait before next collection
time.sleep(1)
except Exception as e:
logger.error(f"Metrics collection error: {e}")
time.sleep(5)
@app.route('/')
def index():
return render_template('realtime_metrics.html')
@app.route('/metrics-stream')
def metrics_stream():
def event_stream():
while True:
try:
# Wait for new metrics
metrics = metrics_queue.get(timeout=1)
yield f"data: {json.dumps(metrics)}\n\n"
except queue.Empty:
# No new metrics, send a comment to keep connection alive
yield ":heartbeat\n\n"
except Exception as e:
logger.error(f"Stream error: {e}")
break
return Response(event_stream(), mimetype='text/event-stream')
@app.route('/system-info')
def system_info():
"""Provide detailed system information"""
try:
return jsonify({
'platform': platform.system(),
'platform_release': platform.release(),
'platform_version': platform.version(),
'architecture': platform.machine(),
'processor': platform.processor(),
'cpu_count': psutil.cpu_count(logical=False), # Physical CPUs
'cpu_count_logical': psutil.cpu_count(logical=True), # Logical CPUs
'total_memory': psutil.virtual_memory().total / (1024 * 1024 * 1024), # GB
})
except Exception as e:
logger.error(f"System info error: {e}")
return jsonify({'error': str(e)}), 500
@app.route('/process-metrics')
def process_metrics():
"""Get top resource-consuming processes"""
try:
# Get process information
processes = []
for proc in sorted(psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']),
key=lambda x: x.info['cpu_percent'],
reverse=True)[:10]:
try:
processes.append({
'pid': proc.info['pid'],
'name': proc.info['name'],
'cpu_percent': proc.info['cpu_percent'],
'memory_percent': proc.info['memory_percent']
})
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return jsonify(processes)
except Exception as e:
logger.error(f"Process metrics error: {e}")
return jsonify({'error': str(e)}), 500
@app.route('/disk-usage')
def disk_usage():
"""Get disk usage information"""
try:
disk_partitions = psutil.disk_partitions()
disk_info = []
for partition in disk_partitions:
try:
usage = psutil.disk_usage(partition.mountpoint)
disk_info.append({
'device': partition.device,
'mountpoint': partition.mountpoint,
'fstype': partition.fstype,
'total_size': usage.total / (1024 * 1024 * 1024), # GB
'used': usage.used / (1024 * 1024 * 1024), # GB
'free': usage.free / (1024 * 1024 * 1024), # GB
'percent': usage.percent
})
except Exception as e:
logger.error(f"Disk usage error for {partition.mountpoint}: {e}")
return jsonify(disk_info)
except Exception as e:
logger.error(f"Disk usage overall error: {e}")
return jsonify({'error': str(e)}), 500
@app.route('/network-connections')
def network_connections():
"""Get active network connections"""
try:
connections = []
for conn in psutil.net_connections():
try:
connections.append({
'fd': conn.fd,
'family': str(conn.family),
'type': str(conn.type),
'laddr': str(conn.laddr),
'raddr': str(conn.raddr),
'status': conn.status
})
except Exception as e:
logger.error(f"Network connection error: {e}")
return jsonify(connections)
except Exception as e:
logger.error(f"Network connections error: {e}")
return jsonify({'error': str(e)}), 500
# Query endpoints for InfluxDB metrics
@app.route('/query/system-metrics')
def query_system_metrics():
"""Query system metrics from InfluxDB"""
try:
# Example query for system metrics
table = influx_metrics.client.query(
query="SELECT * FROM system_metrics ORDER BY time DESC LIMIT 100",
language="sql"
)
return jsonify({
'schema': str(table.schema),
'data': table.to_pydict()
})
except Exception as e:
logger.error(f"System metrics query error: {e}")
return jsonify({'error': str(e)}), 500
@app.route('/metrics-overview')
def metrics_overview():
"""Provide an overview of available metrics and endpoints"""
return jsonify({
'available_endpoints': [
'/system-info',
'/process-metrics',
'/disk-usage',
'/network-connections',
'/query/system-metrics',
'/metrics-stream'
],
'dashboard': '/realtime-metrics'
})
if __name__ == '__main__':
# Start metrics collection thread
metrics_thread = threading.Thread(target=collect_metrics_thread, daemon=True)
metrics_thread.start()
try:
app.run(debug=True, threaded=True)
except Exception as e:
logger.error(f"Application startup error: {e}")
logger.error(traceback.format_exc())
finally:
# Ensure InfluxDB client is closed
influx_metrics.close()