소스 수정

This commit is contained in:
2025-12-28 16:27:46 +09:00
parent 56451c8070
commit 1fc6a9ccd9
6 changed files with 89 additions and 15 deletions

View File

@@ -45,7 +45,7 @@ export default defineEventHandler(async (event) => {
collected_at
FROM server_containers
WHERE target_id = $1
AND collected_at >= NOW() - INTERVAL '${interval}'
AND collected_at::timestamp >= NOW() - INTERVAL '${interval}'
ORDER BY collected_at ASC, container_name ASC
`, [targetId])
} catch (e) {

View File

@@ -42,7 +42,7 @@ export default defineEventHandler(async (event) => {
collected_at
FROM server_disks
WHERE target_id = $1
AND collected_at >= NOW() - INTERVAL '${interval}'
AND collected_at::timestamp >= NOW() - INTERVAL '${interval}'
ORDER BY collected_at ASC, mount_point ASC
`, [targetId])
} catch (e) {

View File

@@ -42,7 +42,7 @@ export default defineEventHandler(async (event) => {
collected_at
FROM server_networks
WHERE target_id = $1
AND collected_at >= NOW() - INTERVAL '${interval}'
AND collected_at::timestamp >= NOW() - INTERVAL '${interval}'
ORDER BY collected_at ASC, interface_name ASC
`, [targetId])
} catch (e) {

View File

@@ -171,9 +171,10 @@ async function getServerDashboard() {
const serverStatuses: any[] = []
const summaryServers = { total: servers.length, normal: 0, warning: 0, critical: 0, danger: 0, offline: 0 }
const summaryContainers = { total: 0, normal: 0, warning: 0, critical: 0, danger: 0, stopped: 0 }
for (const server of servers) {
// 최신 로그
// 최신 스냅샷
const snapshot = await queryOne(`
SELECT cpu_percent, memory_percent, collected_at
FROM server_snapshots
@@ -209,6 +210,68 @@ async function getServerDashboard() {
else if (serverLevel === 'warning') summaryServers.warning++
else summaryServers.normal++
// 컨테이너 조회 (최신 데이터만)
const containers: any[] = []
const containerSummary = { total: 0, normal: 0, warning: 0, critical: 0, stopped: 0 }
if (!isOffline) {
// 서버별 최신 컨테이너 (container_name별 최신 1건)
const latestContainers = await query(`
SELECT DISTINCT ON (container_name)
container_name as name,
container_status as status,
cpu_percent,
memory_usage,
memory_limit,
uptime,
network_rx,
network_tx
FROM server_containers
WHERE target_id = $1
ORDER BY container_name, collected_at DESC
`, [server.target_id])
for (const c of latestContainers) {
let containerLevel = 'normal'
if (c.status !== 'running') {
containerLevel = 'stopped'
containerSummary.stopped++
} else {
const cCpuLevel = getLevel(Number(c.cpu_percent), thresholds.container?.cpu || { warning: 80, critical: 90, danger: 95 })
const memPct = c.memory_limit ? (Number(c.memory_usage) / Number(c.memory_limit)) * 100 : 0
const cMemLevel = getLevel(memPct, thresholds.container?.memory || { warning: 80, critical: 90, danger: 95 })
containerLevel = getHighestLevel([cCpuLevel, cMemLevel])
if (containerLevel === 'danger') containerSummary.critical++
else if (containerLevel === 'critical') containerSummary.critical++
else if (containerLevel === 'warning') containerSummary.warning++
else containerSummary.normal++
}
containers.push({
name: c.name,
status: c.status || 'unknown',
level: containerLevel,
cpu_percent: c.cpu_percent,
memory_usage: c.memory_usage,
memory_limit: c.memory_limit,
uptime: c.uptime,
network_rx: c.network_rx,
network_tx: c.network_tx
})
containerSummary.total++
summaryContainers.total++
}
// 전체 컨테이너 요약 집계
summaryContainers.normal += containerSummary.normal
summaryContainers.warning += containerSummary.warning
summaryContainers.critical += containerSummary.critical
summaryContainers.stopped += containerSummary.stopped
}
serverStatuses.push({
target_id: server.target_id,
server_name: server.server_name,
@@ -219,7 +282,9 @@ async function getServerDashboard() {
memory_level: memLevel,
disk_percent: snapshot?.disk_percent ?? null,
disk_level: diskLevel,
last_collected: lastCollected
last_collected: lastCollected,
containers: containers,
container_summary: containerSummary
})
}
@@ -227,7 +292,7 @@ async function getServerDashboard() {
serverStatuses.sort((a, b) => a.server_name.localeCompare(b.server_name))
return {
summary: { servers: summaryServers },
summary: { servers: summaryServers, containers: summaryContainers },
servers: serverStatuses,
timestamp: new Date().toISOString()
}

View File

@@ -37,6 +37,11 @@
<span>Server Status</span>
</NuxtLink>
<NuxtLink to="/settings/thresholds" class="nav-item nav-sub-item" :class="{ active: route.path === '/settings/thresholds' }">
<span class="icon"></span>
<span>Thresholds</span>
</NuxtLink>
<div class="nav-group-title">이상감지</div>
<NuxtLink to="/anomaly/short-term" class="nav-item nav-sub-item" :class="{ active: route.path === '/anomaly/short-term' }">
@@ -58,13 +63,6 @@
<span class="icon">📉</span>
<span>추세 분석</span>
</NuxtLink>
<div class="nav-group-title">설정</div>
<NuxtLink to="/settings/thresholds" class="nav-item nav-sub-item" :class="{ active: route.path === '/settings/thresholds' }">
<span class="icon"></span>
<span>임계값 설정</span>
</NuxtLink>
</nav>
</aside>
</template>

View File

@@ -138,9 +138,20 @@ const thresholds = ref(JSON.parse(JSON.stringify(defaultThresholds)))
async function fetchThresholds() {
try {
const data = await $fetch('/api/settings/thresholds')
const data = await $fetch('/api/settings/thresholds') as any
if (data) {
thresholds.value = data as typeof defaultThresholds
// 기본값과 병합 (API 응답이 불완전할 수 있음)
thresholds.value = {
server: {
cpu: { ...defaultThresholds.server.cpu, ...data.server?.cpu },
memory: { ...defaultThresholds.server.memory, ...data.server?.memory },
disk: { ...defaultThresholds.server.disk, ...data.server?.disk }
},
container: {
cpu: { ...defaultThresholds.container.cpu, ...data.container?.cpu },
memory: { ...defaultThresholds.container.memory, ...data.container?.memory }
}
}
}
} catch (err) {
console.error('Failed to fetch thresholds:', err)