mirror of
https://github.com/pockethost/pockethost.git
synced 2025-03-30 15:08:30 +00:00
remove unneeded discordAlert from health check
This commit is contained in:
parent
54837acc60
commit
57f5535910
@ -8,7 +8,6 @@ import {
|
||||
DISCORD_HEALTH_CHANNEL_URL,
|
||||
LoggerService,
|
||||
MOTHERSHIP_PORT,
|
||||
discordAlert,
|
||||
stringify,
|
||||
} from '../../../../core'
|
||||
|
||||
@ -24,217 +23,209 @@ export const checkHealth = async () => {
|
||||
|
||||
info(`Starting`)
|
||||
|
||||
try {
|
||||
const _exec = (cmd: string) =>
|
||||
execSync(cmd, { shell: '/bin/bash', maxBuffer: 1024 * 1024 * 10 })
|
||||
.toString()
|
||||
.split(`\n`)
|
||||
const _exec = (cmd: string) =>
|
||||
execSync(cmd, { shell: '/bin/bash', maxBuffer: 1024 * 1024 * 10 })
|
||||
.toString()
|
||||
.split(`\n`)
|
||||
|
||||
type DockerPs = {
|
||||
Command: string
|
||||
CreatedAt: string
|
||||
ID: string
|
||||
Image: string
|
||||
Labels: string
|
||||
LocalVolumes: string
|
||||
Mounts: string
|
||||
Names: string
|
||||
Networks: string
|
||||
Ports: string
|
||||
RunningFor: string
|
||||
Size: string
|
||||
State: string
|
||||
Status: string
|
||||
}
|
||||
type DockerPs = {
|
||||
Command: string
|
||||
CreatedAt: string
|
||||
ID: string
|
||||
Image: string
|
||||
Labels: string
|
||||
LocalVolumes: string
|
||||
Mounts: string
|
||||
Names: string
|
||||
Networks: string
|
||||
Ports: string
|
||||
RunningFor: string
|
||||
Size: string
|
||||
State: string
|
||||
Status: string
|
||||
}
|
||||
|
||||
const SAMPLE: DockerPs = {
|
||||
Command: '"docker-entrypoint.s…"',
|
||||
CreatedAt: '2024-01-23 04:36:09 +0000 UTC',
|
||||
ID: '6e0921e84391',
|
||||
Image: 'pockethost-instance',
|
||||
Labels: '',
|
||||
LocalVolumes: '0',
|
||||
Mounts:
|
||||
'/home/pocketho…,/home/pocketho…,/home/pocketho…,/home/pocketho…,/home/pocketho…',
|
||||
Names: 'kekbase-1705984569777',
|
||||
Networks: 'bridge',
|
||||
Ports: '0.0.0.0:44447-\u003e8090/tcp, :::44447-\u003e8090/tcp',
|
||||
RunningFor: '7 hours ago',
|
||||
Size: '0B (virtual 146MB)',
|
||||
State: 'running',
|
||||
Status: 'Up 7 hours',
|
||||
}
|
||||
const SAMPLE: DockerPs = {
|
||||
Command: '"docker-entrypoint.s…"',
|
||||
CreatedAt: '2024-01-23 04:36:09 +0000 UTC',
|
||||
ID: '6e0921e84391',
|
||||
Image: 'pockethost-instance',
|
||||
Labels: '',
|
||||
LocalVolumes: '0',
|
||||
Mounts:
|
||||
'/home/pocketho…,/home/pocketho…,/home/pocketho…,/home/pocketho…,/home/pocketho…',
|
||||
Names: 'kekbase-1705984569777',
|
||||
Networks: 'bridge',
|
||||
Ports: '0.0.0.0:44447-\u003e8090/tcp, :::44447-\u003e8090/tcp',
|
||||
RunningFor: '7 hours ago',
|
||||
Size: '0B (virtual 146MB)',
|
||||
State: 'running',
|
||||
Status: 'Up 7 hours',
|
||||
}
|
||||
|
||||
type Check = {
|
||||
name: string
|
||||
priority: number
|
||||
emoji: string
|
||||
isHealthy: boolean
|
||||
url: string
|
||||
type Check = {
|
||||
name: string
|
||||
priority: number
|
||||
emoji: string
|
||||
isHealthy: boolean
|
||||
url: string
|
||||
|
||||
// Instance
|
||||
port?: number
|
||||
ago?: string
|
||||
mem?: string
|
||||
created?: Date
|
||||
}
|
||||
// Instance
|
||||
port?: number
|
||||
ago?: string
|
||||
mem?: string
|
||||
created?: Date
|
||||
}
|
||||
|
||||
const containers = _exec(`docker ps --format '{{json .}}'`)
|
||||
.filter((line) => line.trim())
|
||||
.map((line) => {
|
||||
dbg(line)
|
||||
return line
|
||||
})
|
||||
.map((line) => JSON.parse(line) as DockerPs)
|
||||
.map<Check>((rec) => {
|
||||
const name = rec.Names.replace(/-\d+/, '')
|
||||
const port = parseInt(rec.Ports.match(/:(\d+)/)?.[1] || '0', 10)
|
||||
const mem = rec.Size.match(/(\d+MB)/)?.[1] || '0MB'
|
||||
const created = new Date(rec.CreatedAt)
|
||||
return {
|
||||
name,
|
||||
priority: 0,
|
||||
emoji: ':octopus:',
|
||||
port,
|
||||
isHealthy: false,
|
||||
url: `http://localhost:${port}/api/health`,
|
||||
ago: rec.RunningFor,
|
||||
mem,
|
||||
created,
|
||||
}
|
||||
})
|
||||
|
||||
function getFreeMemoryInGB(): string {
|
||||
const freeMemoryBytes: number = freemem()
|
||||
const freeMemoryGB: number = freeMemoryBytes / Math.pow(1024, 3)
|
||||
return freeMemoryGB.toFixed(2) // Rounds to 2 decimal places
|
||||
}
|
||||
|
||||
function splitIntoChunks(
|
||||
lines: string[],
|
||||
maxChars: number = 2000,
|
||||
): string[] {
|
||||
const chunks: string[] = []
|
||||
let currentChunk: string = ''
|
||||
|
||||
lines.forEach((line) => {
|
||||
// Check if adding the next line exceeds the maxChars limit
|
||||
if (currentChunk.length + line.length + 1 > maxChars) {
|
||||
chunks.push(currentChunk)
|
||||
currentChunk = ''
|
||||
}
|
||||
currentChunk += line + '\n' // Add the line and a newline character
|
||||
})
|
||||
|
||||
// Add the last chunk if it's not empty
|
||||
if (currentChunk) {
|
||||
chunks.push(currentChunk)
|
||||
const containers = _exec(`docker ps --format '{{json .}}'`)
|
||||
.filter((line) => line.trim())
|
||||
.map((line) => {
|
||||
dbg(line)
|
||||
return line
|
||||
})
|
||||
.map((line) => JSON.parse(line) as DockerPs)
|
||||
.map<Check>((rec) => {
|
||||
const name = rec.Names.replace(/-\d+/, '')
|
||||
const port = parseInt(rec.Ports.match(/:(\d+)/)?.[1] || '0', 10)
|
||||
const mem = rec.Size.match(/(\d+MB)/)?.[1] || '0MB'
|
||||
const created = new Date(rec.CreatedAt)
|
||||
return {
|
||||
name,
|
||||
priority: 0,
|
||||
emoji: ':octopus:',
|
||||
port,
|
||||
isHealthy: false,
|
||||
url: `http://localhost:${port}/api/health`,
|
||||
ago: rec.RunningFor,
|
||||
mem,
|
||||
created,
|
||||
}
|
||||
})
|
||||
|
||||
return chunks
|
||||
function getFreeMemoryInGB(): string {
|
||||
const freeMemoryBytes: number = freemem()
|
||||
const freeMemoryGB: number = freeMemoryBytes / Math.pow(1024, 3)
|
||||
return freeMemoryGB.toFixed(2) // Rounds to 2 decimal places
|
||||
}
|
||||
|
||||
function splitIntoChunks(lines: string[], maxChars: number = 2000): string[] {
|
||||
const chunks: string[] = []
|
||||
let currentChunk: string = ''
|
||||
|
||||
lines.forEach((line) => {
|
||||
// Check if adding the next line exceeds the maxChars limit
|
||||
if (currentChunk.length + line.length + 1 > maxChars) {
|
||||
chunks.push(currentChunk)
|
||||
currentChunk = ''
|
||||
}
|
||||
currentChunk += line + '\n' // Add the line and a newline character
|
||||
})
|
||||
|
||||
// Add the last chunk if it's not empty
|
||||
if (currentChunk) {
|
||||
chunks.push(currentChunk)
|
||||
}
|
||||
|
||||
const limiter = new Bottleneck({ maxConcurrent: 1 })
|
||||
return chunks
|
||||
}
|
||||
|
||||
const send = (lines: string[]) =>
|
||||
Promise.all(
|
||||
splitIntoChunks(lines).map((content) =>
|
||||
limiter.schedule(() =>
|
||||
fetch(DISCORD_URL, {
|
||||
method: 'POST',
|
||||
body: stringify({
|
||||
content,
|
||||
}),
|
||||
headers: { 'content-type': 'application/json' },
|
||||
const limiter = new Bottleneck({ maxConcurrent: 1 })
|
||||
|
||||
const send = (lines: string[]) =>
|
||||
Promise.all(
|
||||
splitIntoChunks(lines).map((content) =>
|
||||
limiter.schedule(() =>
|
||||
fetch(DISCORD_URL, {
|
||||
method: 'POST',
|
||||
body: stringify({
|
||||
content,
|
||||
}),
|
||||
),
|
||||
headers: { 'content-type': 'application/json' },
|
||||
}),
|
||||
),
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
const openFiles = _exec(`cat /proc/sys/fs/file-nr`)[0]?.trim() || `Unknown`
|
||||
const openFiles = _exec(`cat /proc/sys/fs/file-nr`)[0]?.trim() || `Unknown`
|
||||
|
||||
await send([
|
||||
`===================`,
|
||||
`${new Date()}`,
|
||||
`CPUs: ${cpu.count()}`,
|
||||
`CPU Usage: ${await cpu.usage()}%`,
|
||||
`Free RAM: ${getFreeMemoryInGB()}GB`,
|
||||
`Free Storage /: ${(await drive.info(`/`)).freeGb}GB`,
|
||||
`Free Storage /mnt/sfo_data: ${
|
||||
(await drive.info(`/mnt/sfo_data`)).freeGb
|
||||
}GB`,
|
||||
`Open files: ${openFiles}`,
|
||||
`Containers: ${containers.length}`,
|
||||
])
|
||||
await send([
|
||||
`===================`,
|
||||
`${new Date()}`,
|
||||
`CPUs: ${cpu.count()}`,
|
||||
`CPU Usage: ${await cpu.usage()}%`,
|
||||
`Free RAM: ${getFreeMemoryInGB()}GB`,
|
||||
`Free Storage /: ${(await drive.info(`/`)).freeGb}GB`,
|
||||
`Free Storage /mnt/sfo_data: ${
|
||||
(await drive.info(`/mnt/sfo_data`)).freeGb
|
||||
}GB`,
|
||||
`Open files: ${openFiles}`,
|
||||
`Containers: ${containers.length}`,
|
||||
])
|
||||
|
||||
const checks: Check[] = [
|
||||
{
|
||||
name: `edge proxy`,
|
||||
priority: 10,
|
||||
emoji: `:park:`,
|
||||
isHealthy: false,
|
||||
url: `https://proxy.pockethost.io/_api/health`,
|
||||
},
|
||||
{
|
||||
name: `edge daemon`,
|
||||
priority: 8,
|
||||
emoji: `:imp:`,
|
||||
isHealthy: false,
|
||||
url: `http://localhost:${DAEMON_PORT()}/_api/health`,
|
||||
},
|
||||
{
|
||||
name: `mothership`,
|
||||
priority: 9,
|
||||
emoji: `:flying_saucer:`,
|
||||
isHealthy: false,
|
||||
url: `http://localhost:${MOTHERSHIP_PORT()}/api/health`,
|
||||
},
|
||||
...containers,
|
||||
]
|
||||
const checks: Check[] = [
|
||||
{
|
||||
name: `edge proxy`,
|
||||
priority: 10,
|
||||
emoji: `:park:`,
|
||||
isHealthy: false,
|
||||
url: `https://proxy.pockethost.io/_api/health`,
|
||||
},
|
||||
{
|
||||
name: `edge daemon`,
|
||||
priority: 8,
|
||||
emoji: `:imp:`,
|
||||
isHealthy: false,
|
||||
url: `http://localhost:${DAEMON_PORT()}/_api/health`,
|
||||
},
|
||||
{
|
||||
name: `mothership`,
|
||||
priority: 9,
|
||||
emoji: `:flying_saucer:`,
|
||||
isHealthy: false,
|
||||
url: `http://localhost:${MOTHERSHIP_PORT()}/api/health`,
|
||||
},
|
||||
]
|
||||
|
||||
await Promise.all(
|
||||
checks.map(async (check) => {
|
||||
const { url } = check
|
||||
dbg({ container: check })
|
||||
try {
|
||||
const res = await fetch(url)
|
||||
dbg({ url, status: res.status })
|
||||
check.isHealthy = res.status === 200
|
||||
return true
|
||||
} catch (e) {
|
||||
dbg(`${url}: ${e}`)
|
||||
check.isHealthy = false
|
||||
await Promise.all(
|
||||
checks.map(async (check) => {
|
||||
const { url } = check
|
||||
dbg({ container: check })
|
||||
try {
|
||||
const res = await fetch(url)
|
||||
dbg({ url, status: res.status })
|
||||
check.isHealthy = res.status === 200
|
||||
return true
|
||||
} catch (e) {
|
||||
dbg(`${url}: ${e}`)
|
||||
check.isHealthy = false
|
||||
}
|
||||
}),
|
||||
)
|
||||
dbg({ checks })
|
||||
await send([
|
||||
`---health checks---`,
|
||||
...checks
|
||||
.sort((a, b) => {
|
||||
if (a.priority > b.priority) return -1
|
||||
if (a.priority < b.priority) return 1
|
||||
const now = new Date()
|
||||
const res = +(b.created || now) - +(a.created || now)
|
||||
if (res) return res
|
||||
return a.name.localeCompare(b.name)
|
||||
})
|
||||
.map(({ name, isHealthy, emoji, mem, ago }) => {
|
||||
const isInstance = !!mem
|
||||
if (isInstance) {
|
||||
return `${
|
||||
isHealthy ? ':white_check_mark:' : ':face_vomiting: '
|
||||
} \`${name.padStart(30)} ${(mem || '').padStart(10)} ${(
|
||||
ago || ''
|
||||
).padStart(20)}\``
|
||||
} else {
|
||||
return `${
|
||||
isHealthy ? ':white_check_mark:' : ':face_vomiting: '
|
||||
} ${name}`
|
||||
}
|
||||
}),
|
||||
)
|
||||
dbg({ checks })
|
||||
await send([
|
||||
`---health checks---`,
|
||||
...checks
|
||||
.sort((a, b) => {
|
||||
if (a.priority > b.priority) return -1
|
||||
if (a.priority < b.priority) return 1
|
||||
const now = new Date()
|
||||
const res = +(b.created || now) - +(a.created || now)
|
||||
if (res) return res
|
||||
return a.name.localeCompare(b.name)
|
||||
})
|
||||
.map(({ name, isHealthy, emoji, mem, ago }) => {
|
||||
const isInstance = !!mem
|
||||
if (isInstance) {
|
||||
return `${
|
||||
isHealthy ? ':white_check_mark:' : ':face_vomiting: '
|
||||
} \`${name.padStart(30)} ${(mem || '').padStart(10)} ${(
|
||||
ago || ''
|
||||
).padStart(20)}\``
|
||||
} else {
|
||||
return `${
|
||||
isHealthy ? ':white_check_mark:' : ':face_vomiting: '
|
||||
} ${name}`
|
||||
}
|
||||
}),
|
||||
])
|
||||
} catch (e) {
|
||||
discordAlert(`${e}`)
|
||||
}
|
||||
])
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user