feat: 系统资源实时监控和网速显示
This commit is contained in:
319
app.py
319
app.py
@@ -20,6 +20,16 @@ from flask import Flask, render_template_string, jsonify, request, g
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
# 系统资源监控
|
||||
try:
|
||||
import psutil
|
||||
import time
|
||||
HAS_PSUTIL = True
|
||||
# 网速计算用的上次数据
|
||||
_last_net_stats = {'bytes_sent': 0, 'bytes_recv': 0, 'time': 0}
|
||||
except ImportError:
|
||||
HAS_PSUTIL = False
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
@@ -694,6 +704,101 @@ def api_cron_sync():
|
||||
return jsonify({'message': f'同步完成,新增 {synced_count} 个任务'})
|
||||
|
||||
|
||||
# ==================== 系统资源监控 API ====================
|
||||
|
||||
@app.route('/api/system/stats')
|
||||
def api_system_stats():
|
||||
"""获取系统资源信息"""
|
||||
if not HAS_PSUTIL:
|
||||
return jsonify({'error': 'psutil未安装', 'available': False})
|
||||
|
||||
try:
|
||||
# CPU
|
||||
cpu_percent = psutil.cpu_percent(interval=0.5)
|
||||
cpu_count = psutil.cpu_count(logical=False) or psutil.cpu_count()
|
||||
cpu_count_logical = psutil.cpu_count(logical=True)
|
||||
|
||||
# 内存
|
||||
mem = psutil.virtual_memory()
|
||||
mem_total_gb = round(mem.total / (1024**3), 2)
|
||||
mem_used_gb = round(mem.used / (1024**3), 2)
|
||||
mem_available_gb = round(mem.available / (1024**3), 2)
|
||||
mem_percent = mem.percent
|
||||
|
||||
# 磁盘
|
||||
disk = psutil.disk_usage('/')
|
||||
disk_total_gb = round(disk.total / (1024**3), 2)
|
||||
disk_used_gb = round(disk.used / (1024**3), 2)
|
||||
disk_free_gb = round(disk.free / (1024**3), 2)
|
||||
disk_percent = disk.percent
|
||||
|
||||
# 网络流量和网速计算
|
||||
net = psutil.net_io_counters()
|
||||
current_time = time.time()
|
||||
|
||||
# 计算网速 (bytes/s)
|
||||
time_diff = current_time - _last_net_stats['time'] if _last_net_stats['time'] > 0 else 1
|
||||
sent_speed = (net.bytes_sent - _last_net_stats['bytes_sent']) / time_diff if time_diff > 0 else 0
|
||||
recv_speed = (net.bytes_recv - _last_net_stats['bytes_recv']) / time_diff if time_diff > 0 else 0
|
||||
|
||||
# 保存当前数据用于下次计算
|
||||
_last_net_stats['bytes_sent'] = net.bytes_sent
|
||||
_last_net_stats['bytes_recv'] = net.bytes_recv
|
||||
_last_net_stats['time'] = current_time
|
||||
|
||||
# 转换为 KB/s 或 MB/s
|
||||
sent_speed_kb = sent_speed / 1024
|
||||
recv_speed_kb = recv_speed / 1024
|
||||
sent_speed_display = f"{sent_speed_kb:.1f} KB/s" if sent_speed_kb < 1024 else f"{sent_speed_kb/1024:.2f} MB/s"
|
||||
recv_speed_display = f"{recv_speed_kb:.1f} KB/s" if recv_speed_kb < 1024 else f"{recv_speed_kb/1024:.2f} MB/s"
|
||||
|
||||
net_sent_mb = round(net.bytes_sent / (1024**2), 2)
|
||||
net_recv_mb = round(net.bytes_recv / (1024**2), 2)
|
||||
|
||||
# 系统启动时间
|
||||
boot_time = datetime.fromtimestamp(psutil.boot_time()).strftime('%Y-%m-%d %H:%M:%S')
|
||||
uptime_seconds = int(datetime.now().timestamp() - psutil.boot_time())
|
||||
uptime_hours = uptime_seconds // 3600
|
||||
uptime_minutes = (uptime_seconds % 3600) // 60
|
||||
|
||||
# 进程数
|
||||
process_count = len(psutil.pids())
|
||||
|
||||
return jsonify({
|
||||
'available': True,
|
||||
'cpu': {
|
||||
'percent': cpu_percent,
|
||||
'count': cpu_count,
|
||||
'logical': cpu_count_logical
|
||||
},
|
||||
'memory': {
|
||||
'total_gb': mem_total_gb,
|
||||
'used_gb': mem_used_gb,
|
||||
'available_gb': mem_available_gb,
|
||||
'percent': mem_percent
|
||||
},
|
||||
'disk': {
|
||||
'total_gb': disk_total_gb,
|
||||
'used_gb': disk_used_gb,
|
||||
'free_gb': disk_free_gb,
|
||||
'percent': disk_percent
|
||||
},
|
||||
'network': {
|
||||
'sent_mb': net_sent_mb,
|
||||
'recv_mb': net_recv_mb,
|
||||
'sent_speed': sent_speed_display,
|
||||
'recv_speed': recv_speed_display
|
||||
},
|
||||
'system': {
|
||||
'boot_time': boot_time,
|
||||
'uptime': f'{uptime_hours}小时{uptime_minutes}分钟',
|
||||
'process_count': process_count
|
||||
}
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e), 'available': False})
|
||||
|
||||
|
||||
def guess_cron_name(command):
|
||||
"""从命令推断任务名称"""
|
||||
keywords = {
|
||||
@@ -935,7 +1040,7 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>项目服务管理面板 v2.4</title>
|
||||
<title>项目服务管理面板 v2.6</title>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📊</text></svg>">
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link href="https://cdn.jsdelivr.net/npm/remixicon@3.5.0/fonts/remixicon.css" rel="stylesheet">
|
||||
@@ -965,6 +1070,11 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
||||
.filter-bar-btn.active { background: #3b82f6; border-color: #3b82f6; color: #fff; }
|
||||
.filter-bar-btn.add-btn { background: #22c55e; border-color: #22c55e; color: #fff; }
|
||||
.filter-bar-btn.add-btn:hover { background: #16a34a; }
|
||||
.realtime-toggle { display: flex; align-items: center; gap: 8px; padding: 8px 16px; border-radius: 8px; background: #1e293b; border: 1px solid #334155; }
|
||||
.realtime-toggle.active { background: #22c55e/20; border-color: #22c55e; }
|
||||
.speed-badge { display: inline-flex; align-items: center; gap: 4px; padding: 4px 12px; border-radius: 6px; background: #334155; font-size: 13px; }
|
||||
.speed-badge.upload { color: #f97316; }
|
||||
.speed-badge.download { color: #3b82f6; }
|
||||
.tab-btn { border-bottom: 2px solid transparent; }
|
||||
.tab-btn.active { border-bottom-color: #3b82f6; }
|
||||
.cron-card { transition: all 0.2s; }
|
||||
@@ -1016,6 +1126,9 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
||||
<button onclick="switchTab('projects')" class="tab-btn active px-4 py-2 text-gray-300 hover:text-white" data-tab="projects">
|
||||
<i class="ri-apps-line"></i> 项目服务
|
||||
</button>
|
||||
<button onclick="switchTab('system')" class="tab-btn px-4 py-2 text-gray-300 hover:text-white" data-tab="system">
|
||||
<i class="ri-dashboard-2-line"></i> 系统资源
|
||||
</button>
|
||||
<button onclick="switchTab('cron')" class="tab-btn px-4 py-2 text-gray-300 hover:text-white" data-tab="cron">
|
||||
<i class="ri-timer-line"></i> Cron 管理
|
||||
</button>
|
||||
@@ -1079,6 +1192,121 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 系统资源 Tab -->
|
||||
<div id="systemTab" class="hidden">
|
||||
<!-- 系统概览 -->
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
|
||||
<div class="card rounded-xl p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-gray-400 text-sm">系统运行时间</p>
|
||||
<p id="sysUptime" class="text-lg font-bold text-green-400">-</p>
|
||||
</div>
|
||||
<i class="ri-time-line text-3xl text-green-400 opacity-50"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card rounded-xl p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-gray-400 text-sm">启动时间</p>
|
||||
<p id="sysBootTime" class="text-lg font-bold text-blue-400">-</p>
|
||||
</div>
|
||||
<i class="ri-calendar-line text-3xl text-blue-400 opacity-50"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card rounded-xl p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-gray-400 text-sm">进程数</p>
|
||||
<p id="sysProcessCount" class="text-lg font-bold text-yellow-400">-</p>
|
||||
</div>
|
||||
<i class="ri-terminal-line text-3xl text-yellow-400 opacity-50"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card rounded-xl p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-gray-400 text-sm">CPU核心</p>
|
||||
<p id="sysCpuCount" class="text-lg font-bold text-purple-400">-</p>
|
||||
</div>
|
||||
<i class="ri-cpu-line text-3xl text-purple-400 opacity-50"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CPU & 内存 -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
|
||||
<div class="card rounded-xl p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="font-bold text-lg flex items-center gap-2"><i class="ri-cpu-line text-blue-400"></i> CPU 使用率</h3>
|
||||
<span id="cpuPercent" class="text-2xl font-bold text-blue-400">-</span>
|
||||
</div>
|
||||
<div class="w-full bg-gray-700 rounded-full h-4 mb-2">
|
||||
<div id="cpuBar" class="bg-blue-500 h-4 rounded-full transition-all duration-300" style="width: 0%"></div>
|
||||
</div>
|
||||
<p class="text-gray-400 text-sm">物理核心: <span id="cpuPhysical">-</span> | 逻辑核心: <span id="cpuLogical">-</span></p>
|
||||
</div>
|
||||
<div class="card rounded-xl p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="font-bold text-lg flex items-center gap-2"><i class="ri-memory-card-line text-green-400"></i> 内存使用</h3>
|
||||
<span id="memPercent" class="text-2xl font-bold text-green-400">-</span>
|
||||
</div>
|
||||
<div class="w-full bg-gray-700 rounded-full h-4 mb-2">
|
||||
<div id="memBar" class="bg-green-500 h-4 rounded-full transition-all duration-300" style="width: 0%"></div>
|
||||
</div>
|
||||
<p class="text-gray-400 text-sm">已用: <span id="memUsed">-</span> GB / 总量: <span id="memTotal">-</span> GB | 可用: <span id="memAvailable">-</span> GB</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 磁盘 & 网络 -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
|
||||
<div class="card rounded-xl p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="font-bold text-lg flex items-center gap-2"><i class="ri-hard-drive-2-line text-orange-400"></i> 磁盘使用</h3>
|
||||
<span id="diskPercent" class="text-2xl font-bold text-orange-400">-</span>
|
||||
</div>
|
||||
<div class="w-full bg-gray-700 rounded-full h-4 mb-2">
|
||||
<div id="diskBar" class="bg-orange-500 h-4 rounded-full transition-all duration-300" style="width: 0%"></div>
|
||||
</div>
|
||||
<p class="text-gray-400 text-sm">已用: <span id="diskUsed">-</span> GB / 总量: <span id="diskTotal">-</span> GB | 剩余: <span id="diskFree">-</span> GB</p>
|
||||
</div>
|
||||
<div class="card rounded-xl p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="font-bold text-lg flex items-center gap-2"><i class="ri-wifi-line text-cyan-400"></i> 网络流量</h3>
|
||||
</div>
|
||||
<!-- 实时网速 -->
|
||||
<div class="flex gap-3 mb-4">
|
||||
<span class="speed-badge upload"><i class="ri-upload-line"></i> ↑ <span id="netSentSpeed">-</span></span>
|
||||
<span class="speed-badge download"><i class="ri-download-line"></i> ↓ <span id="netRecvSpeed">-</span></span>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<p class="text-gray-400 text-sm mb-1">累计发送</p>
|
||||
<p id="netSent" class="text-xl font-bold text-cyan-400">-</p>
|
||||
<p class="text-gray-500 text-xs">MB</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-gray-400 text-sm mb-1">累计接收</p>
|
||||
<p id="netRecv" class="text-xl font-bold text-purple-400">-</p>
|
||||
<p class="text-gray-500 text-xs">MB</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 控制按钮 -->
|
||||
<div class="flex gap-3 mb-4 items-center">
|
||||
<button onclick="loadSystemStats()" class="btn bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded-lg flex items-center gap-2">
|
||||
<i class="ri-refresh-line"></i> 刷新数据
|
||||
</button>
|
||||
<div class="realtime-toggle" id="realtimeToggle">
|
||||
<input type="checkbox" id="realtimeCheck" onchange="toggleRealtime()" class="w-4 h-4 cursor-pointer">
|
||||
<label for="realtimeCheck" class="text-gray-300 text-sm cursor-pointer">实时监控</label>
|
||||
<span id="realtimeIndicator" class="text-xs text-gray-500 ml-1"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Cron 管理 Tab -->
|
||||
<div id="cronTab" class="hidden">
|
||||
<!-- Cron 统计 -->
|
||||
@@ -1341,11 +1569,100 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
||||
btn.classList.toggle('active', btn.dataset.tab === tab);
|
||||
});
|
||||
document.getElementById('projectsTab').classList.toggle('hidden', tab !== 'projects');
|
||||
document.getElementById('systemTab').classList.toggle('hidden', tab !== 'system');
|
||||
document.getElementById('cronTab').classList.toggle('hidden', tab !== 'cron');
|
||||
|
||||
// 切换Tab时关闭实时监控
|
||||
if (tab !== 'system' && realtimeTimer) {
|
||||
clearInterval(realtimeTimer);
|
||||
realtimeTimer = null;
|
||||
document.getElementById('realtimeCheck').checked = false;
|
||||
document.getElementById('realtimeToggle').classList.remove('active');
|
||||
document.getElementById('realtimeIndicator').textContent = '';
|
||||
}
|
||||
|
||||
if (tab === 'cron') {
|
||||
loadCronTasks();
|
||||
}
|
||||
if (tab === 'system') {
|
||||
loadSystemStats();
|
||||
}
|
||||
}
|
||||
|
||||
// 系统资源加载
|
||||
let realtimeTimer = null;
|
||||
let realtimeInterval = 2; // 秒
|
||||
|
||||
async function loadSystemStats() {
|
||||
try {
|
||||
const res = await fetch('/api/system/stats');
|
||||
const data = await res.json();
|
||||
|
||||
if (!data.available) {
|
||||
document.getElementById('sysUptime').textContent = 'psutil未安装';
|
||||
document.getElementById('sysBootTime').textContent = '-';
|
||||
return;
|
||||
}
|
||||
|
||||
// 系统概览
|
||||
document.getElementById('sysUptime').textContent = data.system.uptime;
|
||||
document.getElementById('sysBootTime').textContent = data.system.boot_time;
|
||||
document.getElementById('sysProcessCount').textContent = data.system.process_count;
|
||||
document.getElementById('sysCpuCount').textContent = data.cpu.logical + '核';
|
||||
|
||||
// CPU
|
||||
document.getElementById('cpuPercent').textContent = data.cpu.percent.toFixed(1) + '%';
|
||||
document.getElementById('cpuBar').style.width = data.cpu.percent + '%';
|
||||
document.getElementById('cpuPhysical').textContent = data.cpu.count;
|
||||
document.getElementById('cpuLogical').textContent = data.cpu.logical;
|
||||
|
||||
// 内存
|
||||
document.getElementById('memPercent').textContent = data.memory.percent.toFixed(1) + '%';
|
||||
document.getElementById('memBar').style.width = data.memory.percent + '%';
|
||||
document.getElementById('memUsed').textContent = data.memory.used_gb;
|
||||
document.getElementById('memTotal').textContent = data.memory.total_gb;
|
||||
document.getElementById('memAvailable').textContent = data.memory.available_gb;
|
||||
|
||||
// 磁盘
|
||||
document.getElementById('diskPercent').textContent = data.disk.percent.toFixed(1) + '%';
|
||||
document.getElementById('diskBar').style.width = data.disk.percent + '%';
|
||||
document.getElementById('diskUsed').textContent = data.disk.used_gb;
|
||||
document.getElementById('diskTotal').textContent = data.disk.total_gb;
|
||||
document.getElementById('diskFree').textContent = data.disk.free_gb;
|
||||
|
||||
// 网络 - 累计流量
|
||||
document.getElementById('netSent').textContent = data.network.sent_mb;
|
||||
document.getElementById('netRecv').textContent = data.network.recv_mb;
|
||||
// 实时网速
|
||||
document.getElementById('netSentSpeed').textContent = data.network.sent_speed || '-';
|
||||
document.getElementById('netRecvSpeed').textContent = data.network.recv_speed || '-';
|
||||
|
||||
} catch (e) {
|
||||
console.error('系统资源加载失败:', e);
|
||||
}
|
||||
}
|
||||
|
||||
function toggleRealtime() {
|
||||
const checked = document.getElementById('realtimeCheck').checked;
|
||||
const toggle = document.getElementById('realtimeToggle');
|
||||
const indicator = document.getElementById('realtimeIndicator');
|
||||
|
||||
if (checked) {
|
||||
toggle.classList.add('active');
|
||||
indicator.textContent = '每' + realtimeInterval + '秒';
|
||||
// 立即加载一次
|
||||
loadSystemStats();
|
||||
// 启动定时器
|
||||
realtimeTimer = setInterval(loadSystemStats, realtimeInterval * 1000);
|
||||
} else {
|
||||
toggle.classList.remove('active');
|
||||
indicator.textContent = '';
|
||||
// 停止定时器
|
||||
if (realtimeTimer) {
|
||||
clearInterval(realtimeTimer);
|
||||
realtimeTimer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IP 保存
|
||||
|
||||
64
logs/app.log
64
logs/app.log
@@ -1,8 +1,8 @@
|
||||
[2026-04-23 16:56:14] ==================================================
|
||||
[2026-04-23 16:56:14] 项目服务管理面板 v2.0.0 启动
|
||||
[2026-04-23 16:56:14] 访问地址: http://localhost:19013
|
||||
[2026-04-23 16:56:14] 进程PID: 1118301
|
||||
[2026-04-23 16:56:14] ==================================================
|
||||
[2026-04-23 17:27:44] ==================================================
|
||||
[2026-04-23 17:27:44] 项目服务管理面板 v2.0.0 启动
|
||||
[2026-04-23 17:27:44] 访问地址: http://localhost:19013
|
||||
[2026-04-23 17:27:44] 进程PID: 1130035
|
||||
[2026-04-23 17:27:44] ==================================================
|
||||
* Serving Flask app 'app'
|
||||
* Debug mode: off
|
||||
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
|
||||
@@ -10,27 +10,33 @@ WARNING: This is a development server. Do not use it in a production deployment.
|
||||
* Running on http://127.0.0.1:19013
|
||||
* Running on http://192.168.2.17:19013
|
||||
Press CTRL+C to quit
|
||||
127.0.0.1 - - [23/Apr/2026 16:56:17] "GET / HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 16:56:17] "GET / HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 16:56:18] "GET / HTTP/1.1" 200 -
|
||||
192.168.2.14 - - [23/Apr/2026 16:56:19] "GET /api/projects HTTP/1.1" 200 -
|
||||
192.168.2.8 - - [23/Apr/2026 16:56:20] "GET /api/projects HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 16:56:21] "GET / HTTP/1.1" 200 -
|
||||
192.168.2.14 - - [23/Apr/2026 16:56:22] "GET /api/projects HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 16:56:27] "GET / HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 16:56:28] "GET / HTTP/1.1" 200 -
|
||||
192.168.2.14 - - [23/Apr/2026 16:56:29] "GET /api/projects HTTP/1.1" 200 -
|
||||
192.168.2.8 - - [23/Apr/2026 16:56:30] "GET /api/projects HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 16:56:36] "GET / HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 16:56:37] "GET / HTTP/1.1" 200 -
|
||||
192.168.2.8 - - [23/Apr/2026 16:56:38] "GET /api/projects HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 16:56:38] "GET / HTTP/1.1" 200 -
|
||||
192.168.2.14 - - [23/Apr/2026 16:56:39] "GET /api/projects HTTP/1.1" 200 -
|
||||
192.168.2.8 - - [23/Apr/2026 16:56:40] "GET /api/projects HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 16:56:47] "GET / HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 16:56:48] "GET / HTTP/1.1" 200 -
|
||||
192.168.2.14 - - [23/Apr/2026 16:56:49] "GET /api/projects HTTP/1.1" 200 -
|
||||
192.168.2.8 - - [23/Apr/2026 16:56:50] "GET /api/projects HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 16:56:50] "GET / HTTP/1.1" 200 -
|
||||
192.168.2.14 - - [23/Apr/2026 16:56:52] "GET /api/projects HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 16:56:57] "GET / HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:27:49] "GET /api/system/stats HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:27:51] "GET / HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:27:52] "GET / HTTP/1.1" 200 -
|
||||
192.168.2.14 - - [23/Apr/2026 17:27:53] "GET /api/projects HTTP/1.1" 200 -
|
||||
192.168.2.8 - - [23/Apr/2026 17:27:54] "GET /api/projects HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:28:02] "GET / HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:28:02] "GET / HTTP/1.1" 200 -
|
||||
192.168.2.14 - - [23/Apr/2026 17:28:03] "GET /api/projects HTTP/1.1" 200 -
|
||||
192.168.2.8 - - [23/Apr/2026 17:28:04] "GET /api/projects HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:28:10] "GET / HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:28:12] "GET / HTTP/1.1" 200 -
|
||||
192.168.2.8 - - [23/Apr/2026 17:28:12] "GET /api/projects HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:28:12] "GET / HTTP/1.1" 200 -
|
||||
192.168.2.14 - - [23/Apr/2026 17:28:13] "GET /api/projects HTTP/1.1" 200 -
|
||||
192.168.2.8 - - [23/Apr/2026 17:28:14] "GET /api/projects HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:28:21] "GET / HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:28:22] "GET / HTTP/1.1" 200 -
|
||||
192.168.2.14 - - [23/Apr/2026 17:28:23] "GET /api/projects HTTP/1.1" 200 -
|
||||
192.168.2.8 - - [23/Apr/2026 17:28:24] "GET /api/projects HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:28:31] "GET / HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:28:32] "GET / HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:28:33] "GET /api/system/stats HTTP/1.1" 200 -
|
||||
192.168.2.14 - - [23/Apr/2026 17:28:33] "GET /api/projects HTTP/1.1" 200 -
|
||||
192.168.2.8 - - [23/Apr/2026 17:28:34] "GET /api/projects HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:28:40] "GET / HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:28:41] "GET / HTTP/1.1" 200 -
|
||||
192.168.2.8 - - [23/Apr/2026 17:28:42] "GET /api/projects HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [23/Apr/2026 17:28:43] "GET / HTTP/1.1" 200 -
|
||||
192.168.2.14 - - [23/Apr/2026 17:28:43] "GET /api/projects HTTP/1.1" 200 -
|
||||
192.168.2.8 - - [23/Apr/2026 17:28:44] "GET /api/projects HTTP/1.1" 200 -
|
||||
|
||||
Reference in New Issue
Block a user