remove unneeded discordAlert from health check

This commit is contained in:
Ben Allfree 2024-09-25 04:34:23 +00:00
parent 54837acc60
commit 57f5535910

View File

@ -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}`)
}
])
}