Docker 파일
This commit is contained in:
@@ -1,36 +1,29 @@
|
|||||||
import { getDb } from '../../../utils/db'
|
import { query } from '../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const query = getQuery(event)
|
const queryParams = getQuery(event)
|
||||||
const { year, month, week } = query as { year?: string, month?: string, week?: string }
|
const { year, month, week } = queryParams as { year?: string, month?: string, week?: string }
|
||||||
|
|
||||||
if (!year || !month || !week) {
|
if (!year || !month || !week) {
|
||||||
return { error: 'year, month, week are required' }
|
return { error: 'year, month, week are required' }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 해당 월의 첫날과 마지막날
|
|
||||||
const y = parseInt(year)
|
const y = parseInt(year)
|
||||||
const m = parseInt(month)
|
const m = parseInt(month)
|
||||||
const w = parseInt(week)
|
const w = parseInt(week)
|
||||||
|
|
||||||
// 해당 월의 첫날
|
|
||||||
const firstDayOfMonth = new Date(y, m - 1, 1)
|
const firstDayOfMonth = new Date(y, m - 1, 1)
|
||||||
const firstDayWeekday = firstDayOfMonth.getDay() // 0=일, 1=월, ...
|
const firstDayWeekday = firstDayOfMonth.getDay()
|
||||||
|
|
||||||
// 주차의 시작일 계산 (월요일 기준)
|
|
||||||
// 1주차: 1일이 포함된 주
|
|
||||||
const mondayOffset = firstDayWeekday === 0 ? -6 : 1 - firstDayWeekday
|
const mondayOffset = firstDayWeekday === 0 ? -6 : 1 - firstDayWeekday
|
||||||
const firstMondayOfMonth = new Date(y, m - 1, 1 + mondayOffset)
|
const firstMondayOfMonth = new Date(y, m - 1, 1 + mondayOffset)
|
||||||
|
|
||||||
// 선택한 주차의 월요일
|
|
||||||
const weekStart = new Date(firstMondayOfMonth)
|
const weekStart = new Date(firstMondayOfMonth)
|
||||||
weekStart.setDate(weekStart.getDate() + (w - 1) * 7)
|
weekStart.setDate(weekStart.getDate() + (w - 1) * 7)
|
||||||
|
|
||||||
// 주차의 일요일
|
|
||||||
const weekEnd = new Date(weekStart)
|
const weekEnd = new Date(weekStart)
|
||||||
weekEnd.setDate(weekEnd.getDate() + 6)
|
weekEnd.setDate(weekEnd.getDate() + 6)
|
||||||
|
|
||||||
// 해당 주의 날짜 목록 생성
|
|
||||||
const weekDates: string[] = []
|
const weekDates: string[] = []
|
||||||
for (let i = 0; i < 7; i++) {
|
for (let i = 0; i < 7; i++) {
|
||||||
const d = new Date(weekStart)
|
const d = new Date(weekStart)
|
||||||
@@ -39,31 +32,23 @@ export default defineEventHandler(async (event) => {
|
|||||||
weekDates.push(dateStr)
|
weekDates.push(dateStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = getDb()
|
|
||||||
|
|
||||||
// 시작/종료 날짜
|
|
||||||
const startDate = weekDates[0]
|
const startDate = weekDates[0]
|
||||||
const endDate = weekDates[6]
|
const endDate = weekDates[6]
|
||||||
|
|
||||||
// 1시간 단위 성공률 조회
|
const heatmapData = await query(`
|
||||||
const heatmapData = db.prepare(`
|
|
||||||
SELECT
|
SELECT
|
||||||
date(checked_at) as date,
|
TO_CHAR(checked_at::timestamp, 'YYYY-MM-DD') as date,
|
||||||
strftime('%H', checked_at) || ':00' as time_slot,
|
TO_CHAR(checked_at::timestamp, 'HH24:00') as time_slot,
|
||||||
COUNT(*) as total_count,
|
COUNT(*) as total_count,
|
||||||
SUM(CASE WHEN is_success = 1 THEN 1 ELSE 0 END) as success_count,
|
SUM(CASE WHEN is_success = 1 THEN 1 ELSE 0 END) as success_count,
|
||||||
ROUND(SUM(CASE WHEN is_success = 1 THEN 1.0 ELSE 0.0 END) / COUNT(*) * 100, 1) as success_rate
|
ROUND(SUM(CASE WHEN is_success = 1 THEN 1.0 ELSE 0.0 END) / COUNT(*) * 100, 1) as success_rate
|
||||||
FROM privnet_logs
|
FROM privnet_logs
|
||||||
WHERE date(checked_at) >= ? AND date(checked_at) <= ?
|
WHERE checked_at::date >= $1 AND checked_at::date <= $2
|
||||||
GROUP BY date, time_slot
|
GROUP BY date, time_slot
|
||||||
ORDER BY date, time_slot
|
ORDER BY date, time_slot
|
||||||
`).all(startDate, endDate)
|
`, [startDate, endDate])
|
||||||
|
|
||||||
// 해당 월의 주차 수 계산
|
|
||||||
const lastDayOfMonth = new Date(y, m, 0)
|
const lastDayOfMonth = new Date(y, m, 0)
|
||||||
const lastDate = lastDayOfMonth.getDate()
|
|
||||||
|
|
||||||
// 마지막 날이 몇 주차인지 계산
|
|
||||||
const lastDayFromFirstMonday = Math.floor((lastDayOfMonth.getTime() - firstMondayOfMonth.getTime()) / (1000 * 60 * 60 * 24))
|
const lastDayFromFirstMonday = Math.floor((lastDayOfMonth.getTime() - firstMondayOfMonth.getTime()) / (1000 * 60 * 60 * 24))
|
||||||
const totalWeeks = Math.ceil((lastDayFromFirstMonday + 1) / 7)
|
const totalWeeks = Math.ceil((lastDayFromFirstMonday + 1) / 7)
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { getDb } from '../../../utils/db'
|
import { query } from '../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const query = getQuery(event)
|
const queryParams = getQuery(event)
|
||||||
const { year, month, day, hour } = query as {
|
const { year, month, day, hour } = queryParams as {
|
||||||
year?: string, month?: string, day?: string, hour?: string
|
year?: string, month?: string, day?: string, hour?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10,13 +10,10 @@ export default defineEventHandler(async (event) => {
|
|||||||
return { error: 'year, month, day, hour are required' }
|
return { error: 'year, month, day, hour are required' }
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = getDb()
|
|
||||||
|
|
||||||
// 해당 시간대 로그 조회
|
|
||||||
const startTime = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')} ${hour.padStart(2, '0')}:00:00`
|
const startTime = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')} ${hour.padStart(2, '0')}:00:00`
|
||||||
const endTime = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')} ${hour.padStart(2, '0')}:59:59`
|
const endTime = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')} ${hour.padStart(2, '0')}:59:59`
|
||||||
|
|
||||||
const logs = db.prepare(`
|
const logs = await query(`
|
||||||
SELECT
|
SELECT
|
||||||
l.id,
|
l.id,
|
||||||
l.checked_at,
|
l.checked_at,
|
||||||
@@ -25,9 +22,9 @@ export default defineEventHandler(async (event) => {
|
|||||||
t.url as target_url
|
t.url as target_url
|
||||||
FROM privnet_logs l
|
FROM privnet_logs l
|
||||||
JOIN privnet_targets t ON l.target_id = t.id
|
JOIN privnet_targets t ON l.target_id = t.id
|
||||||
WHERE l.checked_at >= ? AND l.checked_at <= ?
|
WHERE l.checked_at >= $1 AND l.checked_at <= $2
|
||||||
ORDER BY l.checked_at DESC
|
ORDER BY l.checked_at DESC
|
||||||
`).all(startTime, endTime)
|
`, [startTime, endTime])
|
||||||
|
|
||||||
return { logs }
|
return { logs }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
import { getDb } from '../../../utils/db'
|
import { query, queryOne } from '../../../utils/db'
|
||||||
import { privnetScheduler } from '../../../utils/privnet-scheduler'
|
import { privnetScheduler } from '../../../utils/privnet-scheduler'
|
||||||
|
|
||||||
export default defineEventHandler(() => {
|
export default defineEventHandler(async () => {
|
||||||
const db = getDb()
|
const status = await queryOne(`
|
||||||
|
|
||||||
// 현재 상태 조회
|
|
||||||
const status = db.prepare(`
|
|
||||||
SELECT
|
SELECT
|
||||||
ps.*,
|
ps.*,
|
||||||
pt.name as last_target_name,
|
pt.name as last_target_name,
|
||||||
@@ -13,10 +10,9 @@ export default defineEventHandler(() => {
|
|||||||
FROM privnet_status ps
|
FROM privnet_status ps
|
||||||
LEFT JOIN privnet_targets pt ON ps.last_target_id = pt.id
|
LEFT JOIN privnet_targets pt ON ps.last_target_id = pt.id
|
||||||
WHERE ps.id = 1
|
WHERE ps.id = 1
|
||||||
`).get()
|
`)
|
||||||
|
|
||||||
// 최근 10개 로그
|
const recentLogs = await query(`
|
||||||
const recentLogs = db.prepare(`
|
|
||||||
SELECT
|
SELECT
|
||||||
pl.*,
|
pl.*,
|
||||||
pt.name as target_name,
|
pt.name as target_name,
|
||||||
@@ -25,17 +21,16 @@ export default defineEventHandler(() => {
|
|||||||
JOIN privnet_targets pt ON pl.target_id = pt.id
|
JOIN privnet_targets pt ON pl.target_id = pt.id
|
||||||
ORDER BY pl.checked_at DESC
|
ORDER BY pl.checked_at DESC
|
||||||
LIMIT 10
|
LIMIT 10
|
||||||
`).all()
|
`)
|
||||||
|
|
||||||
// 활성 타겟 수
|
const targetCount = await queryOne<{ cnt: number }>(`
|
||||||
const targetCount = db.prepare(`
|
|
||||||
SELECT COUNT(*) as cnt FROM privnet_targets WHERE is_active = 1
|
SELECT COUNT(*) as cnt FROM privnet_targets WHERE is_active = 1
|
||||||
`).get() as { cnt: number }
|
`)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status,
|
status,
|
||||||
recentLogs,
|
recentLogs,
|
||||||
targetCount: targetCount.cnt,
|
targetCount: targetCount?.cnt || 0,
|
||||||
schedulerRunning: privnetScheduler.getIsRunning()
|
schedulerRunning: privnetScheduler.getIsRunning()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { getDb } from '../../../../utils/db'
|
import { execute } from '../../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler((event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const db = getDb()
|
|
||||||
const id = getRouterParam(event, 'id')
|
const id = getRouterParam(event, 'id')
|
||||||
|
|
||||||
db.prepare(`DELETE FROM privnet_targets WHERE id = ?`).run(id)
|
await execute(`DELETE FROM privnet_targets WHERE id = $1`, [id])
|
||||||
|
|
||||||
return { success: true }
|
return { success: true }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { getDb } from '../../../../utils/db'
|
import { execute } from '../../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const db = getDb()
|
|
||||||
const id = getRouterParam(event, 'id')
|
const id = getRouterParam(event, 'id')
|
||||||
const body = await readBody(event)
|
const body = await readBody(event)
|
||||||
|
|
||||||
@@ -14,11 +13,11 @@ export default defineEventHandler(async (event) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
db.prepare(`
|
await execute(`
|
||||||
UPDATE privnet_targets
|
UPDATE privnet_targets
|
||||||
SET name = ?, url = ?, is_active = ?, updated_at = datetime('now', 'localtime')
|
SET name = $1, url = $2, is_active = $3, updated_at = TO_CHAR(NOW(), 'YYYY-MM-DD HH24:MI:SS')
|
||||||
WHERE id = ?
|
WHERE id = $4
|
||||||
`).run(name, url, is_active ? 1 : 0, id)
|
`, [name, url, is_active ? 1 : 0, id])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: Number(id),
|
id: Number(id),
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import { getDb } from '../../../../utils/db'
|
import { query } from '../../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler(() => {
|
export default defineEventHandler(async () => {
|
||||||
const db = getDb()
|
const targets = await query(`
|
||||||
|
|
||||||
const targets = db.prepare(`
|
|
||||||
SELECT * FROM privnet_targets
|
SELECT * FROM privnet_targets
|
||||||
ORDER BY id ASC
|
ORDER BY id ASC
|
||||||
`).all()
|
`)
|
||||||
|
|
||||||
return targets
|
return targets
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { getDb } from '../../../../utils/db'
|
import { queryOne } from '../../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const db = getDb()
|
|
||||||
const body = await readBody(event)
|
const body = await readBody(event)
|
||||||
|
|
||||||
const { name, url, is_active } = body
|
const { name, url, is_active } = body
|
||||||
@@ -13,13 +12,14 @@ export default defineEventHandler(async (event) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = db.prepare(`
|
const result = await queryOne<{ id: number }>(`
|
||||||
INSERT INTO privnet_targets (name, url, is_active)
|
INSERT INTO privnet_targets (name, url, is_active)
|
||||||
VALUES (?, ?, ?)
|
VALUES ($1, $2, $3)
|
||||||
`).run(name, url, is_active ? 1 : 0)
|
RETURNING id
|
||||||
|
`, [name, url, is_active ? 1 : 0])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: result.lastInsertRowid,
|
id: result?.id,
|
||||||
name,
|
name,
|
||||||
url,
|
url,
|
||||||
is_active: is_active ? 1 : 0
|
is_active: is_active ? 1 : 0
|
||||||
|
|||||||
@@ -1,36 +1,29 @@
|
|||||||
import { getDb } from '../../../utils/db'
|
import { query } from '../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const query = getQuery(event)
|
const queryParams = getQuery(event)
|
||||||
const { year, month, week } = query as { year?: string, month?: string, week?: string }
|
const { year, month, week } = queryParams as { year?: string, month?: string, week?: string }
|
||||||
|
|
||||||
if (!year || !month || !week) {
|
if (!year || !month || !week) {
|
||||||
return { error: 'year, month, week are required' }
|
return { error: 'year, month, week are required' }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 해당 월의 첫날과 마지막날
|
|
||||||
const y = parseInt(year)
|
const y = parseInt(year)
|
||||||
const m = parseInt(month)
|
const m = parseInt(month)
|
||||||
const w = parseInt(week)
|
const w = parseInt(week)
|
||||||
|
|
||||||
// 해당 월의 첫날
|
|
||||||
const firstDayOfMonth = new Date(y, m - 1, 1)
|
const firstDayOfMonth = new Date(y, m - 1, 1)
|
||||||
const firstDayWeekday = firstDayOfMonth.getDay() // 0=일, 1=월, ...
|
const firstDayWeekday = firstDayOfMonth.getDay()
|
||||||
|
|
||||||
// 주차의 시작일 계산 (월요일 기준)
|
|
||||||
// 1주차: 1일이 포함된 주
|
|
||||||
const mondayOffset = firstDayWeekday === 0 ? -6 : 1 - firstDayWeekday
|
const mondayOffset = firstDayWeekday === 0 ? -6 : 1 - firstDayWeekday
|
||||||
const firstMondayOfMonth = new Date(y, m - 1, 1 + mondayOffset)
|
const firstMondayOfMonth = new Date(y, m - 1, 1 + mondayOffset)
|
||||||
|
|
||||||
// 선택한 주차의 월요일
|
|
||||||
const weekStart = new Date(firstMondayOfMonth)
|
const weekStart = new Date(firstMondayOfMonth)
|
||||||
weekStart.setDate(weekStart.getDate() + (w - 1) * 7)
|
weekStart.setDate(weekStart.getDate() + (w - 1) * 7)
|
||||||
|
|
||||||
// 주차의 일요일
|
|
||||||
const weekEnd = new Date(weekStart)
|
const weekEnd = new Date(weekStart)
|
||||||
weekEnd.setDate(weekEnd.getDate() + 6)
|
weekEnd.setDate(weekEnd.getDate() + 6)
|
||||||
|
|
||||||
// 해당 주의 날짜 목록 생성
|
|
||||||
const weekDates: string[] = []
|
const weekDates: string[] = []
|
||||||
for (let i = 0; i < 7; i++) {
|
for (let i = 0; i < 7; i++) {
|
||||||
const d = new Date(weekStart)
|
const d = new Date(weekStart)
|
||||||
@@ -39,31 +32,23 @@ export default defineEventHandler(async (event) => {
|
|||||||
weekDates.push(dateStr)
|
weekDates.push(dateStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = getDb()
|
|
||||||
|
|
||||||
// 시작/종료 날짜
|
|
||||||
const startDate = weekDates[0]
|
const startDate = weekDates[0]
|
||||||
const endDate = weekDates[6]
|
const endDate = weekDates[6]
|
||||||
|
|
||||||
// 1시간 단위 성공률 조회
|
const heatmapData = await query(`
|
||||||
const heatmapData = db.prepare(`
|
|
||||||
SELECT
|
SELECT
|
||||||
date(checked_at) as date,
|
TO_CHAR(checked_at::timestamp, 'YYYY-MM-DD') as date,
|
||||||
strftime('%H', checked_at) || ':00' as time_slot,
|
TO_CHAR(checked_at::timestamp, 'HH24:00') as time_slot,
|
||||||
COUNT(*) as total_count,
|
COUNT(*) as total_count,
|
||||||
SUM(CASE WHEN is_success = 1 THEN 1 ELSE 0 END) as success_count,
|
SUM(CASE WHEN is_success = 1 THEN 1 ELSE 0 END) as success_count,
|
||||||
ROUND(SUM(CASE WHEN is_success = 1 THEN 1.0 ELSE 0.0 END) / COUNT(*) * 100, 1) as success_rate
|
ROUND(SUM(CASE WHEN is_success = 1 THEN 1.0 ELSE 0.0 END) / COUNT(*) * 100, 1) as success_rate
|
||||||
FROM pubnet_logs
|
FROM pubnet_logs
|
||||||
WHERE date(checked_at) >= ? AND date(checked_at) <= ?
|
WHERE checked_at::date >= $1 AND checked_at::date <= $2
|
||||||
GROUP BY date, time_slot
|
GROUP BY date, time_slot
|
||||||
ORDER BY date, time_slot
|
ORDER BY date, time_slot
|
||||||
`).all(startDate, endDate)
|
`, [startDate, endDate])
|
||||||
|
|
||||||
// 해당 월의 주차 수 계산
|
|
||||||
const lastDayOfMonth = new Date(y, m, 0)
|
const lastDayOfMonth = new Date(y, m, 0)
|
||||||
const lastDate = lastDayOfMonth.getDate()
|
|
||||||
|
|
||||||
// 마지막 날이 몇 주차인지 계산
|
|
||||||
const lastDayFromFirstMonday = Math.floor((lastDayOfMonth.getTime() - firstMondayOfMonth.getTime()) / (1000 * 60 * 60 * 24))
|
const lastDayFromFirstMonday = Math.floor((lastDayOfMonth.getTime() - firstMondayOfMonth.getTime()) / (1000 * 60 * 60 * 24))
|
||||||
const totalWeeks = Math.ceil((lastDayFromFirstMonday + 1) / 7)
|
const totalWeeks = Math.ceil((lastDayFromFirstMonday + 1) / 7)
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { getDb } from '../../../utils/db'
|
import { query } from '../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const query = getQuery(event)
|
const queryParams = getQuery(event)
|
||||||
const { year, month, day, hour } = query as {
|
const { year, month, day, hour } = queryParams as {
|
||||||
year?: string, month?: string, day?: string, hour?: string
|
year?: string, month?: string, day?: string, hour?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10,13 +10,10 @@ export default defineEventHandler(async (event) => {
|
|||||||
return { error: 'year, month, day, hour are required' }
|
return { error: 'year, month, day, hour are required' }
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = getDb()
|
|
||||||
|
|
||||||
// 해당 시간대 로그 조회
|
|
||||||
const startTime = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')} ${hour.padStart(2, '0')}:00:00`
|
const startTime = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')} ${hour.padStart(2, '0')}:00:00`
|
||||||
const endTime = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')} ${hour.padStart(2, '0')}:59:59`
|
const endTime = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')} ${hour.padStart(2, '0')}:59:59`
|
||||||
|
|
||||||
const logs = db.prepare(`
|
const logs = await query(`
|
||||||
SELECT
|
SELECT
|
||||||
l.id,
|
l.id,
|
||||||
l.checked_at,
|
l.checked_at,
|
||||||
@@ -25,9 +22,9 @@ export default defineEventHandler(async (event) => {
|
|||||||
t.url as target_url
|
t.url as target_url
|
||||||
FROM pubnet_logs l
|
FROM pubnet_logs l
|
||||||
JOIN pubnet_targets t ON l.target_id = t.id
|
JOIN pubnet_targets t ON l.target_id = t.id
|
||||||
WHERE l.checked_at >= ? AND l.checked_at <= ?
|
WHERE l.checked_at >= $1 AND l.checked_at <= $2
|
||||||
ORDER BY l.checked_at DESC
|
ORDER BY l.checked_at DESC
|
||||||
`).all(startTime, endTime)
|
`, [startTime, endTime])
|
||||||
|
|
||||||
return { logs }
|
return { logs }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
import { getDb } from '../../../utils/db'
|
import { query, queryOne } from '../../../utils/db'
|
||||||
import { pubnetScheduler } from '../../../utils/pubnet-scheduler'
|
import { pubnetScheduler } from '../../../utils/pubnet-scheduler'
|
||||||
|
|
||||||
export default defineEventHandler(() => {
|
export default defineEventHandler(async () => {
|
||||||
const db = getDb()
|
const status = await queryOne(`
|
||||||
|
|
||||||
// 현재 상태 조회
|
|
||||||
const status = db.prepare(`
|
|
||||||
SELECT
|
SELECT
|
||||||
ps.*,
|
ps.*,
|
||||||
pt.name as last_target_name,
|
pt.name as last_target_name,
|
||||||
@@ -13,10 +10,9 @@ export default defineEventHandler(() => {
|
|||||||
FROM pubnet_status ps
|
FROM pubnet_status ps
|
||||||
LEFT JOIN pubnet_targets pt ON ps.last_target_id = pt.id
|
LEFT JOIN pubnet_targets pt ON ps.last_target_id = pt.id
|
||||||
WHERE ps.id = 1
|
WHERE ps.id = 1
|
||||||
`).get()
|
`)
|
||||||
|
|
||||||
// 최근 10개 로그
|
const recentLogs = await query(`
|
||||||
const recentLogs = db.prepare(`
|
|
||||||
SELECT
|
SELECT
|
||||||
pl.*,
|
pl.*,
|
||||||
pt.name as target_name,
|
pt.name as target_name,
|
||||||
@@ -25,17 +21,16 @@ export default defineEventHandler(() => {
|
|||||||
JOIN pubnet_targets pt ON pl.target_id = pt.id
|
JOIN pubnet_targets pt ON pl.target_id = pt.id
|
||||||
ORDER BY pl.checked_at DESC
|
ORDER BY pl.checked_at DESC
|
||||||
LIMIT 10
|
LIMIT 10
|
||||||
`).all()
|
`)
|
||||||
|
|
||||||
// 활성 타겟 수
|
const targetCount = await queryOne<{ cnt: number }>(`
|
||||||
const targetCount = db.prepare(`
|
|
||||||
SELECT COUNT(*) as cnt FROM pubnet_targets WHERE is_active = 1
|
SELECT COUNT(*) as cnt FROM pubnet_targets WHERE is_active = 1
|
||||||
`).get() as { cnt: number }
|
`)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status,
|
status,
|
||||||
recentLogs,
|
recentLogs,
|
||||||
targetCount: targetCount.cnt,
|
targetCount: targetCount?.cnt || 0,
|
||||||
schedulerRunning: pubnetScheduler.getIsRunning()
|
schedulerRunning: pubnetScheduler.getIsRunning()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { getDb } from '../../../../utils/db'
|
import { execute } from '../../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler((event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const db = getDb()
|
|
||||||
const id = getRouterParam(event, 'id')
|
const id = getRouterParam(event, 'id')
|
||||||
|
|
||||||
db.prepare(`DELETE FROM pubnet_targets WHERE id = ?`).run(id)
|
await execute(`DELETE FROM pubnet_targets WHERE id = $1`, [id])
|
||||||
|
|
||||||
return { success: true }
|
return { success: true }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { getDb } from '../../../../utils/db'
|
import { execute } from '../../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const db = getDb()
|
|
||||||
const id = getRouterParam(event, 'id')
|
const id = getRouterParam(event, 'id')
|
||||||
const body = await readBody(event)
|
const body = await readBody(event)
|
||||||
|
|
||||||
@@ -14,11 +13,11 @@ export default defineEventHandler(async (event) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
db.prepare(`
|
await execute(`
|
||||||
UPDATE pubnet_targets
|
UPDATE pubnet_targets
|
||||||
SET name = ?, url = ?, is_active = ?, updated_at = datetime('now', 'localtime')
|
SET name = $1, url = $2, is_active = $3, updated_at = TO_CHAR(NOW(), 'YYYY-MM-DD HH24:MI:SS')
|
||||||
WHERE id = ?
|
WHERE id = $4
|
||||||
`).run(name, url, is_active ? 1 : 0, id)
|
`, [name, url, is_active ? 1 : 0, id])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: Number(id),
|
id: Number(id),
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import { getDb } from '../../../../utils/db'
|
import { query } from '../../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler(() => {
|
export default defineEventHandler(async () => {
|
||||||
const db = getDb()
|
const targets = await query(`
|
||||||
|
|
||||||
const targets = db.prepare(`
|
|
||||||
SELECT * FROM pubnet_targets
|
SELECT * FROM pubnet_targets
|
||||||
ORDER BY id ASC
|
ORDER BY id ASC
|
||||||
`).all()
|
`)
|
||||||
|
|
||||||
return targets
|
return targets
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { getDb } from '../../../../utils/db'
|
import { queryOne } from '../../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const db = getDb()
|
|
||||||
const body = await readBody(event)
|
const body = await readBody(event)
|
||||||
|
|
||||||
const { name, url, is_active } = body
|
const { name, url, is_active } = body
|
||||||
@@ -13,13 +12,14 @@ export default defineEventHandler(async (event) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = db.prepare(`
|
const result = await queryOne<{ id: number }>(`
|
||||||
INSERT INTO pubnet_targets (name, url, is_active)
|
INSERT INTO pubnet_targets (name, url, is_active)
|
||||||
VALUES (?, ?, ?)
|
VALUES ($1, $2, $3)
|
||||||
`).run(name, url, is_active ? 1 : 0)
|
RETURNING id
|
||||||
|
`, [name, url, is_active ? 1 : 0])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: result.lastInsertRowid,
|
id: result?.id,
|
||||||
name,
|
name,
|
||||||
url,
|
url,
|
||||||
is_active: is_active ? 1 : 0
|
is_active: is_active ? 1 : 0
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { getDb } from '../../../utils/db'
|
import { query } from '../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler((event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const query = getQuery(event)
|
const queryParams = getQuery(event)
|
||||||
const targetId = query.target_id as string
|
const targetId = queryParams.target_id as string
|
||||||
|
|
||||||
if (!targetId) {
|
if (!targetId) {
|
||||||
throw createError({
|
throw createError({
|
||||||
@@ -11,20 +11,22 @@ export default defineEventHandler((event) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = getDb()
|
let containers: any[] = []
|
||||||
|
try {
|
||||||
// 최신 수집 시간 기준 컨테이너 목록
|
containers = await query(`
|
||||||
const containers = db.prepare(`
|
SELECT DISTINCT container_name
|
||||||
SELECT DISTINCT container_name
|
FROM server_containers
|
||||||
FROM server_containers
|
WHERE target_id = $1
|
||||||
WHERE target_id = ?
|
AND collected_at = (
|
||||||
AND collected_at = (
|
SELECT MAX(collected_at)
|
||||||
SELECT MAX(collected_at)
|
FROM server_containers
|
||||||
FROM server_containers
|
WHERE target_id = $1
|
||||||
WHERE target_id = ?
|
)
|
||||||
)
|
ORDER BY container_name ASC
|
||||||
ORDER BY container_name ASC
|
`, [targetId])
|
||||||
`).all(targetId, targetId)
|
} catch (e) {
|
||||||
|
containers = []
|
||||||
|
}
|
||||||
|
|
||||||
return containers.map((c: any) => c.container_name)
|
return containers.map((c: any) => c.container_name)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { getDb } from '../../../utils/db'
|
import { query } from '../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler((event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const query = getQuery(event)
|
const queryParams = getQuery(event)
|
||||||
const targetId = query.target_id as string
|
const targetId = queryParams.target_id as string
|
||||||
const period = (query.period as string) || '1h'
|
const period = (queryParams.period as string) || '1h'
|
||||||
|
|
||||||
if (!targetId) {
|
if (!targetId) {
|
||||||
throw createError({
|
throw createError({
|
||||||
@@ -13,41 +13,44 @@ export default defineEventHandler((event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const periodMap: Record<string, string> = {
|
const periodMap: Record<string, string> = {
|
||||||
'1h': '-1 hour',
|
'1h': '1 hour',
|
||||||
'2h': '-2 hours',
|
'2h': '2 hours',
|
||||||
'3h': '-3 hours',
|
'3h': '3 hours',
|
||||||
'4h': '-4 hours',
|
'4h': '4 hours',
|
||||||
'5h': '-5 hours',
|
'5h': '5 hours',
|
||||||
'6h': '-6 hours',
|
'6h': '6 hours',
|
||||||
'12h': '-12 hours',
|
'12h': '12 hours',
|
||||||
'18h': '-18 hours',
|
'18h': '18 hours',
|
||||||
'24h': '-24 hours',
|
'24h': '24 hours',
|
||||||
'7d': '-7 days',
|
'7d': '7 days',
|
||||||
'30d': '-30 days'
|
'30d': '30 days'
|
||||||
}
|
}
|
||||||
|
|
||||||
const timeOffset = periodMap[period] || '-1 hour'
|
const interval = periodMap[period] || '1 hour'
|
||||||
|
|
||||||
const db = getDb()
|
let containers: any[] = []
|
||||||
|
try {
|
||||||
const containers = db.prepare(`
|
containers = await query(`
|
||||||
SELECT
|
SELECT
|
||||||
container_id,
|
container_id,
|
||||||
container_name,
|
container_name,
|
||||||
container_status,
|
container_status,
|
||||||
cpu_percent,
|
cpu_percent,
|
||||||
memory_usage,
|
memory_usage,
|
||||||
memory_limit,
|
memory_limit,
|
||||||
memory_percent,
|
memory_percent,
|
||||||
uptime,
|
uptime,
|
||||||
network_rx,
|
network_rx,
|
||||||
network_tx,
|
network_tx,
|
||||||
collected_at
|
collected_at
|
||||||
FROM server_containers
|
FROM server_containers
|
||||||
WHERE target_id = ?
|
WHERE target_id = $1
|
||||||
AND collected_at >= datetime('now', 'localtime', ?)
|
AND collected_at >= NOW() - INTERVAL '${interval}'
|
||||||
ORDER BY collected_at ASC, container_name ASC
|
ORDER BY collected_at ASC, container_name ASC
|
||||||
`).all(targetId, timeOffset)
|
`, [targetId])
|
||||||
|
} catch (e) {
|
||||||
|
containers = []
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
target_id: targetId,
|
target_id: targetId,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { getDb } from '../../../utils/db'
|
import { query } from '../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler((event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const query = getQuery(event)
|
const queryParams = getQuery(event)
|
||||||
const targetId = query.target_id as string
|
const targetId = queryParams.target_id as string
|
||||||
|
|
||||||
if (!targetId) {
|
if (!targetId) {
|
||||||
throw createError({
|
throw createError({
|
||||||
@@ -11,19 +11,21 @@ export default defineEventHandler((event) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = getDb()
|
let disks: any[] = []
|
||||||
|
try {
|
||||||
// 최신 수집 시간 기준 디스크 목록 (물리 디스크만)
|
disks = await query(`
|
||||||
const disks = db.prepare(`
|
SELECT DISTINCT device_name, mount_point, fs_type, disk_total, disk_used, disk_percent
|
||||||
SELECT DISTINCT device_name, mount_point, fs_type, disk_total, disk_used, disk_percent
|
FROM server_disks
|
||||||
FROM server_disks
|
WHERE target_id = $1
|
||||||
WHERE target_id = ?
|
AND collected_at = (SELECT MAX(collected_at) FROM server_disks WHERE target_id = $1)
|
||||||
AND collected_at = (SELECT MAX(collected_at) FROM server_disks WHERE target_id = ?)
|
AND device_name NOT LIKE '%loop%'
|
||||||
AND device_name NOT LIKE '%loop%'
|
AND mount_point NOT LIKE '%/snap%'
|
||||||
AND mount_point NOT LIKE '%/snap%'
|
AND fs_type NOT IN ('tmpfs', 'squashfs', 'overlay')
|
||||||
AND fs_type NOT IN ('tmpfs', 'squashfs', 'overlay')
|
ORDER BY mount_point ASC
|
||||||
ORDER BY mount_point ASC
|
`, [targetId])
|
||||||
`).all(targetId, targetId)
|
} catch (e) {
|
||||||
|
disks = []
|
||||||
|
}
|
||||||
|
|
||||||
return disks
|
return disks
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { getDb } from '../../../utils/db'
|
import { query } from '../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler((event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const query = getQuery(event)
|
const queryParams = getQuery(event)
|
||||||
const targetId = query.target_id as string
|
const targetId = queryParams.target_id as string
|
||||||
const period = (query.period as string) || '1h'
|
const period = (queryParams.period as string) || '1h'
|
||||||
|
|
||||||
if (!targetId) {
|
if (!targetId) {
|
||||||
throw createError({
|
throw createError({
|
||||||
@@ -13,38 +13,41 @@ export default defineEventHandler((event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const periodMap: Record<string, string> = {
|
const periodMap: Record<string, string> = {
|
||||||
'1h': '-1 hour',
|
'1h': '1 hour',
|
||||||
'2h': '-2 hours',
|
'2h': '2 hours',
|
||||||
'3h': '-3 hours',
|
'3h': '3 hours',
|
||||||
'4h': '-4 hours',
|
'4h': '4 hours',
|
||||||
'5h': '-5 hours',
|
'5h': '5 hours',
|
||||||
'6h': '-6 hours',
|
'6h': '6 hours',
|
||||||
'12h': '-12 hours',
|
'12h': '12 hours',
|
||||||
'18h': '-18 hours',
|
'18h': '18 hours',
|
||||||
'24h': '-24 hours',
|
'24h': '24 hours',
|
||||||
'7d': '-7 days',
|
'7d': '7 days',
|
||||||
'30d': '-30 days'
|
'30d': '30 days'
|
||||||
}
|
}
|
||||||
|
|
||||||
const timeOffset = periodMap[period] || '-1 hour'
|
const interval = periodMap[period] || '1 hour'
|
||||||
|
|
||||||
const db = getDb()
|
let disks: any[] = []
|
||||||
|
try {
|
||||||
const disks = db.prepare(`
|
disks = await query(`
|
||||||
SELECT
|
SELECT
|
||||||
disk_id,
|
disk_id,
|
||||||
device_name,
|
device_name,
|
||||||
mount_point,
|
mount_point,
|
||||||
fs_type,
|
fs_type,
|
||||||
disk_total,
|
disk_total,
|
||||||
disk_used,
|
disk_used,
|
||||||
disk_percent,
|
disk_percent,
|
||||||
collected_at
|
collected_at
|
||||||
FROM server_disks
|
FROM server_disks
|
||||||
WHERE target_id = ?
|
WHERE target_id = $1
|
||||||
AND collected_at >= datetime('now', 'localtime', ?)
|
AND collected_at >= NOW() - INTERVAL '${interval}'
|
||||||
ORDER BY collected_at ASC, mount_point ASC
|
ORDER BY collected_at ASC, mount_point ASC
|
||||||
`).all(targetId, timeOffset)
|
`, [targetId])
|
||||||
|
} catch (e) {
|
||||||
|
disks = []
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
target_id: targetId,
|
target_id: targetId,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { getDb } from '../../../utils/db'
|
import { queryOne } from '../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler((event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const query = getQuery(event)
|
const queryParams = getQuery(event)
|
||||||
const targetId = query.target_id as string
|
const targetId = queryParams.target_id as string
|
||||||
|
|
||||||
if (!targetId) {
|
if (!targetId) {
|
||||||
throw createError({
|
throw createError({
|
||||||
@@ -11,22 +11,17 @@ export default defineEventHandler((event) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = getDb()
|
const snapshot = await queryOne(`
|
||||||
|
|
||||||
// 최신 스냅샷
|
|
||||||
const snapshot = db.prepare(`
|
|
||||||
SELECT
|
SELECT
|
||||||
s.*,
|
l.*,
|
||||||
t.server_name,
|
t.name as server_name,
|
||||||
t.server_ip,
|
t.host as server_ip
|
||||||
t.glances_url,
|
FROM server_logs l
|
||||||
t.collect_interval
|
JOIN server_targets t ON l.target_id = t.target_id
|
||||||
FROM server_snapshots s
|
WHERE l.target_id = $1
|
||||||
JOIN server_targets t ON s.target_id = t.target_id
|
ORDER BY l.checked_at DESC
|
||||||
WHERE s.target_id = ?
|
|
||||||
ORDER BY s.collected_at DESC
|
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
`).get(targetId)
|
`, [targetId])
|
||||||
|
|
||||||
return snapshot || null
|
return snapshot || null
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { getDb } from '../../../utils/db'
|
import { query } from '../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler((event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const query = getQuery(event)
|
const queryParams = getQuery(event)
|
||||||
const targetId = query.target_id as string
|
const targetId = queryParams.target_id as string
|
||||||
const period = (query.period as string) || '1h'
|
const period = (queryParams.period as string) || '1h'
|
||||||
|
|
||||||
if (!targetId) {
|
if (!targetId) {
|
||||||
throw createError({
|
throw createError({
|
||||||
@@ -13,38 +13,41 @@ export default defineEventHandler((event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const periodMap: Record<string, string> = {
|
const periodMap: Record<string, string> = {
|
||||||
'1h': '-1 hour',
|
'1h': '1 hour',
|
||||||
'2h': '-2 hours',
|
'2h': '2 hours',
|
||||||
'3h': '-3 hours',
|
'3h': '3 hours',
|
||||||
'4h': '-4 hours',
|
'4h': '4 hours',
|
||||||
'5h': '-5 hours',
|
'5h': '5 hours',
|
||||||
'6h': '-6 hours',
|
'6h': '6 hours',
|
||||||
'12h': '-12 hours',
|
'12h': '12 hours',
|
||||||
'18h': '-18 hours',
|
'18h': '18 hours',
|
||||||
'24h': '-24 hours',
|
'24h': '24 hours',
|
||||||
'7d': '-7 days',
|
'7d': '7 days',
|
||||||
'30d': '-30 days'
|
'30d': '30 days'
|
||||||
}
|
}
|
||||||
|
|
||||||
const timeOffset = periodMap[period] || '-1 hour'
|
const interval = periodMap[period] || '1 hour'
|
||||||
|
|
||||||
const db = getDb()
|
let networks: any[] = []
|
||||||
|
try {
|
||||||
const networks = db.prepare(`
|
networks = await query(`
|
||||||
SELECT
|
SELECT
|
||||||
network_id,
|
network_id,
|
||||||
interface_name,
|
interface_name,
|
||||||
bytes_recv,
|
bytes_recv,
|
||||||
bytes_sent,
|
bytes_sent,
|
||||||
speed_recv,
|
speed_recv,
|
||||||
speed_sent,
|
speed_sent,
|
||||||
is_up,
|
is_up,
|
||||||
collected_at
|
collected_at
|
||||||
FROM server_networks
|
FROM server_networks
|
||||||
WHERE target_id = ?
|
WHERE target_id = $1
|
||||||
AND collected_at >= datetime('now', 'localtime', ?)
|
AND collected_at >= NOW() - INTERVAL '${interval}'
|
||||||
ORDER BY collected_at ASC, interface_name ASC
|
ORDER BY collected_at ASC, interface_name ASC
|
||||||
`).all(targetId, timeOffset)
|
`, [targetId])
|
||||||
|
} catch (e) {
|
||||||
|
networks = []
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
target_id: targetId,
|
target_id: targetId,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { getDb } from '../../../utils/db'
|
import { query } from '../../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler((event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const query = getQuery(event)
|
const queryParams = getQuery(event)
|
||||||
const targetId = query.target_id as string
|
const targetId = queryParams.target_id as string
|
||||||
const period = (query.period as string) || '1h'
|
const period = (queryParams.period as string) || '1h'
|
||||||
|
|
||||||
if (!targetId) {
|
if (!targetId) {
|
||||||
throw createError({
|
throw createError({
|
||||||
@@ -12,44 +12,35 @@ export default defineEventHandler((event) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 기간별 시간 계산
|
|
||||||
const periodMap: Record<string, string> = {
|
const periodMap: Record<string, string> = {
|
||||||
'1h': '-1 hour',
|
'1h': '1 hour',
|
||||||
'2h': '-2 hours',
|
'2h': '2 hours',
|
||||||
'3h': '-3 hours',
|
'3h': '3 hours',
|
||||||
'4h': '-4 hours',
|
'4h': '4 hours',
|
||||||
'5h': '-5 hours',
|
'5h': '5 hours',
|
||||||
'6h': '-6 hours',
|
'6h': '6 hours',
|
||||||
'12h': '-12 hours',
|
'12h': '12 hours',
|
||||||
'18h': '-18 hours',
|
'18h': '18 hours',
|
||||||
'24h': '-24 hours',
|
'24h': '24 hours',
|
||||||
'7d': '-7 days',
|
'7d': '7 days',
|
||||||
'30d': '-30 days'
|
'30d': '30 days'
|
||||||
}
|
}
|
||||||
|
|
||||||
const timeOffset = periodMap[period] || '-1 hour'
|
const interval = periodMap[period] || '1 hour'
|
||||||
|
|
||||||
const db = getDb()
|
const snapshots = await query(`
|
||||||
|
|
||||||
const snapshots = db.prepare(`
|
|
||||||
SELECT
|
SELECT
|
||||||
snapshot_id,
|
log_id,
|
||||||
cpu_percent,
|
cpu_usage as cpu_percent,
|
||||||
cpu_temp,
|
memory_usage as memory_percent,
|
||||||
load_percent,
|
disk_usage as disk_percent,
|
||||||
memory_percent,
|
is_success as is_online,
|
||||||
memory_used,
|
checked_at as collected_at
|
||||||
memory_total,
|
FROM server_logs
|
||||||
swap_percent,
|
WHERE target_id = $1
|
||||||
swap_used,
|
AND checked_at >= NOW() - INTERVAL '${interval}'
|
||||||
swap_total,
|
ORDER BY checked_at ASC
|
||||||
is_online,
|
`, [targetId])
|
||||||
collected_at
|
|
||||||
FROM server_snapshots
|
|
||||||
WHERE target_id = ?
|
|
||||||
AND collected_at >= datetime('now', 'localtime', ?)
|
|
||||||
ORDER BY collected_at ASC
|
|
||||||
`).all(targetId, timeOffset)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
target_id: targetId,
|
target_id: targetId,
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
import { getDb } from '../../utils/db'
|
import { query } from '../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler(() => {
|
export default defineEventHandler(async () => {
|
||||||
const db = getDb()
|
let rows: any[] = []
|
||||||
|
try {
|
||||||
|
rows = await query(`
|
||||||
|
SELECT category, metric, warning, critical, danger, updated_at
|
||||||
|
FROM thresholds
|
||||||
|
ORDER BY category, metric
|
||||||
|
`)
|
||||||
|
} catch (e) {
|
||||||
|
rows = []
|
||||||
|
}
|
||||||
|
|
||||||
const rows = db.prepare(`
|
|
||||||
SELECT category, metric, warning, critical, danger, updated_at
|
|
||||||
FROM thresholds
|
|
||||||
ORDER BY category, metric
|
|
||||||
`).all() as any[]
|
|
||||||
|
|
||||||
// 카테고리별로 그룹화
|
|
||||||
const result: Record<string, Record<string, { warning: number; critical: number; danger: number }>> = {}
|
const result: Record<string, Record<string, { warning: number; critical: number; danger: number }>> = {}
|
||||||
|
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getDb } from '../../utils/db'
|
import { execute } from '../../utils/db'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const body = await readBody(event)
|
const body = await readBody(event)
|
||||||
@@ -10,15 +10,8 @@ export default defineEventHandler(async (event) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = getDb()
|
|
||||||
const now = new Date().toLocaleString('sv-SE', { timeZone: 'Asia/Seoul' }).replace('T', ' ')
|
const now = new Date().toLocaleString('sv-SE', { timeZone: 'Asia/Seoul' }).replace('T', ' ')
|
||||||
|
|
||||||
const stmt = db.prepare(`
|
|
||||||
UPDATE thresholds
|
|
||||||
SET warning = ?, critical = ?, danger = ?, updated_at = ?
|
|
||||||
WHERE category = ? AND metric = ?
|
|
||||||
`)
|
|
||||||
|
|
||||||
let updated = 0
|
let updated = 0
|
||||||
|
|
||||||
for (const [category, metrics] of Object.entries(body)) {
|
for (const [category, metrics] of Object.entries(body)) {
|
||||||
@@ -29,7 +22,6 @@ export default defineEventHandler(async (event) => {
|
|||||||
|
|
||||||
const { warning, critical, danger } = values
|
const { warning, critical, danger } = values
|
||||||
|
|
||||||
// 유효성 검사
|
|
||||||
if (typeof warning !== 'number' || typeof critical !== 'number' || typeof danger !== 'number') {
|
if (typeof warning !== 'number' || typeof critical !== 'number' || typeof danger !== 'number') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -45,8 +37,16 @@ export default defineEventHandler(async (event) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = stmt.run(warning, critical, danger, now, category, metric)
|
try {
|
||||||
if (result.changes > 0) updated++
|
const result = await execute(`
|
||||||
|
UPDATE thresholds
|
||||||
|
SET warning = $1, critical = $2, danger = $3, updated_at = $4
|
||||||
|
WHERE category = $5 AND metric = $6
|
||||||
|
`, [warning, critical, danger, now, category, metric])
|
||||||
|
if (result > 0) updated++
|
||||||
|
} catch (e) {
|
||||||
|
// 테이블이 없는 경우 무시
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user