feat(admin): 성능 모니터링 API 연동 및 UI 개선
- TPS, MSPT, 메모리 사용량 실시간 표시 - CPU → MSPT로 변경 (서버 틱 처리 시간) - formatStatusForClient에 성능 필드 추가 - 모바일 성능 UI 반응형 레이아웃 (1열/3열) - 타이틀 '관리자 콘솔'로 통일
This commit is contained in:
parent
dd17cb5c5e
commit
f6e7a8922a
2 changed files with 37 additions and 17 deletions
|
|
@ -47,6 +47,10 @@ function formatStatusForClient(modStatus, motdData) {
|
||||||
version: "Unknown",
|
version: "Unknown",
|
||||||
icon: null,
|
icon: null,
|
||||||
uptime: "오프라인",
|
uptime: "오프라인",
|
||||||
|
tps: 0,
|
||||||
|
mspt: 0,
|
||||||
|
memoryUsedMb: 0,
|
||||||
|
memoryMaxMb: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,6 +85,10 @@ function formatStatusForClient(modStatus, motdData) {
|
||||||
difficulty: modStatus.difficulty || "알 수 없음",
|
difficulty: modStatus.difficulty || "알 수 없음",
|
||||||
gameRules: modStatus.gameRules || {},
|
gameRules: modStatus.gameRules || {},
|
||||||
mods: modStatus.mods || [],
|
mods: modStatus.mods || [],
|
||||||
|
tps: modStatus.tps || 0,
|
||||||
|
mspt: modStatus.mspt || 0,
|
||||||
|
memoryUsedMb: modStatus.memoryUsedMb || 0,
|
||||||
|
memoryMaxMb: modStatus.memoryMaxMb || 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -131,11 +131,11 @@ export default function Admin({ isMobile = false }) {
|
||||||
const [whitelistRemoveTarget, setWhitelistRemoveTarget] = useState(null); // 삭제 확인 다이얼로그용
|
const [whitelistRemoveTarget, setWhitelistRemoveTarget] = useState(null); // 삭제 확인 다이얼로그용
|
||||||
const [whitelistLoading, setWhitelistLoading] = useState(false);
|
const [whitelistLoading, setWhitelistLoading] = useState(false);
|
||||||
|
|
||||||
// 성능 모니터링 상태 (더미)
|
// 성능 모니터링 상태 (소켓에서 업데이트)
|
||||||
const [serverPerformance, setServerPerformance] = useState({
|
const [serverPerformance, setServerPerformance] = useState({
|
||||||
tps: 19.8,
|
tps: 0,
|
||||||
cpu: 35.2,
|
mspt: 0,
|
||||||
memory: { used: 2150, max: 4096 },
|
memory: { used: 0, max: 0 },
|
||||||
});
|
});
|
||||||
|
|
||||||
// 권한 확인
|
// 권한 확인
|
||||||
|
|
@ -568,6 +568,17 @@ export default function Admin({ isMobile = false }) {
|
||||||
};
|
};
|
||||||
setDifficulty(difficultyMap[status.difficulty] || 'normal');
|
setDifficulty(difficultyMap[status.difficulty] || 'normal');
|
||||||
}
|
}
|
||||||
|
// 성능 모니터링 데이터 업데이트
|
||||||
|
if (status?.tps !== undefined || status?.memoryUsedMb !== undefined) {
|
||||||
|
setServerPerformance(prev => ({
|
||||||
|
tps: status.tps ?? prev.tps,
|
||||||
|
mspt: status.mspt ?? prev.mspt,
|
||||||
|
memory: {
|
||||||
|
used: status.memoryUsedMb ?? prev.memory.used,
|
||||||
|
max: status.memoryMaxMb ?? prev.memory.max
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 월드 정보에서 시간/날씨 가져오기
|
// 월드 정보에서 시간/날씨 가져오기
|
||||||
|
|
@ -825,7 +836,7 @@ export default function Admin({ isMobile = false }) {
|
||||||
<ArrowLeft size={20} />
|
<ArrowLeft size={20} />
|
||||||
</Link>
|
</Link>
|
||||||
<div className="ml-2">
|
<div className="ml-2">
|
||||||
<h1 className="text-lg font-bold text-white">관리자</h1>
|
<h1 className="text-lg font-bold text-white">관리자 콘솔</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
@ -835,7 +846,7 @@ export default function Admin({ isMobile = false }) {
|
||||||
{/* 데스크탑용 타이틀 */}
|
{/* 데스크탑용 타이틀 */}
|
||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<h1 className="text-2xl font-bold text-white">관리자 페이지</h1>
|
<h1 className="text-2xl font-bold text-white">관리자 콘솔</h1>
|
||||||
<p className="text-sm text-zinc-500 mt-1">서버 관리 및 설정</p>
|
<p className="text-sm text-zinc-500 mt-1">서버 관리 및 설정</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -872,7 +883,7 @@ export default function Admin({ isMobile = false }) {
|
||||||
{/* 서버 성능 모니터링 */}
|
{/* 서버 성능 모니터링 */}
|
||||||
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-4">
|
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-4">
|
||||||
<h3 className="text-white font-medium mb-3">📊 서버 성능</h3>
|
<h3 className="text-white font-medium mb-3">📊 서버 성능</h3>
|
||||||
<div className="grid grid-cols-3 gap-3">
|
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
|
||||||
{/* TPS */}
|
{/* TPS */}
|
||||||
<div className="bg-zinc-800/50 rounded-xl p-3">
|
<div className="bg-zinc-800/50 rounded-xl p-3">
|
||||||
<div className="flex items-center justify-between mb-2">
|
<div className="flex items-center justify-between mb-2">
|
||||||
|
|
@ -895,24 +906,24 @@ export default function Admin({ isMobile = false }) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* CPU */}
|
{/* MSPT */}
|
||||||
<div className="bg-zinc-800/50 rounded-xl p-3">
|
<div className="bg-zinc-800/50 rounded-xl p-3">
|
||||||
<div className="flex items-center justify-between mb-2">
|
<div className="flex items-center justify-between mb-2">
|
||||||
<span className="text-zinc-400 text-xs">CPU</span>
|
<span className="text-zinc-400 text-xs">MSPT</span>
|
||||||
<span className={`font-bold text-sm ${
|
<span className={`font-bold text-sm ${
|
||||||
serverPerformance.cpu <= 50 ? 'text-mc-green' :
|
serverPerformance.mspt <= 40 ? 'text-mc-green' :
|
||||||
serverPerformance.cpu <= 80 ? 'text-yellow-400' : 'text-red-400'
|
serverPerformance.mspt <= 50 ? 'text-yellow-400' : 'text-red-400'
|
||||||
}`}>
|
}`}>
|
||||||
{serverPerformance.cpu.toFixed(0)}%
|
{serverPerformance.mspt.toFixed(1)}ms
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-1.5 bg-zinc-700 rounded-full overflow-hidden">
|
<div className="h-1.5 bg-zinc-700 rounded-full overflow-hidden">
|
||||||
<div
|
<div
|
||||||
className={`h-full transition-all ${
|
className={`h-full transition-all ${
|
||||||
serverPerformance.cpu <= 50 ? 'bg-mc-green' :
|
serverPerformance.mspt <= 40 ? 'bg-mc-green' :
|
||||||
serverPerformance.cpu <= 80 ? 'bg-yellow-400' : 'bg-red-400'
|
serverPerformance.mspt <= 50 ? 'bg-yellow-400' : 'bg-red-400'
|
||||||
}`}
|
}`}
|
||||||
style={{ width: `${serverPerformance.cpu}%` }}
|
style={{ width: `${Math.min(100, (serverPerformance.mspt / 50) * 100)}%` }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -922,16 +933,17 @@ export default function Admin({ isMobile = false }) {
|
||||||
<div className="flex items-center justify-between mb-2">
|
<div className="flex items-center justify-between mb-2">
|
||||||
<span className="text-zinc-400 text-xs">메모리</span>
|
<span className="text-zinc-400 text-xs">메모리</span>
|
||||||
<span className="font-bold text-sm text-mc-diamond">
|
<span className="font-bold text-sm text-mc-diamond">
|
||||||
{(serverPerformance.memory.used / 1024).toFixed(1)}GB
|
{(serverPerformance.memory.used / 1024).toFixed(1)}GB / {(serverPerformance.memory.max / 1024).toFixed(1)}GB
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-1.5 bg-zinc-700 rounded-full overflow-hidden">
|
<div className="h-1.5 bg-zinc-700 rounded-full overflow-hidden">
|
||||||
<div
|
<div
|
||||||
className={`h-full transition-all ${
|
className={`h-full transition-all ${
|
||||||
|
serverPerformance.memory.max === 0 ? 'bg-mc-diamond' :
|
||||||
(serverPerformance.memory.used / serverPerformance.memory.max) > 0.9 ? 'bg-red-400' :
|
(serverPerformance.memory.used / serverPerformance.memory.max) > 0.9 ? 'bg-red-400' :
|
||||||
(serverPerformance.memory.used / serverPerformance.memory.max) > 0.7 ? 'bg-yellow-400' : 'bg-mc-diamond'
|
(serverPerformance.memory.used / serverPerformance.memory.max) > 0.7 ? 'bg-yellow-400' : 'bg-mc-diamond'
|
||||||
}`}
|
}`}
|
||||||
style={{ width: `${(serverPerformance.memory.used / serverPerformance.memory.max) * 100}%` }}
|
style={{ width: `${serverPerformance.memory.max === 0 ? 0 : (serverPerformance.memory.used / serverPerformance.memory.max) * 100}%` }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue