Skip to content

Server Health Check #1135

Server Health Check

Server Health Check #1135

Workflow file for this run

name: Server Health Check
on:
schedule:
# 每 5 分钟运行一次
- cron: "*/5 * * * *"
workflow_dispatch: # 允许手动触发
jobs:
health-check:
if: github.repository == 'Project-N-E-K-O/N.E.K.O' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
# ── 检查 lanlan.app (US, old) ──
- name: Check lanlan.app (old)
id: check_app
run: |
HTTP_CODE=$(curl -s -o /tmp/resp_app.json -w "%{http_code}" \
--max-time 30 --connect-timeout 10 \
-X POST "https://lanlan.app/text/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer free-access" \
-d '{"model":"free-mini-model","messages":[{"role":"user","content":"sends some useful information"}],"max_completion_tokens":5}' \
2>/dev/null || echo "000")
BODY=$(cat /tmp/resp_app.json 2>/dev/null || echo "{}")
echo "http_code=$HTTP_CODE" >> "$GITHUB_OUTPUT"
if [ "$HTTP_CODE" = "200" ]; then
if echo "$BODY" | jq -e '(.choices | type) == "array" and (.choices | length) > 0 and (.choices[0].message | type) == "object" and .choices[0].message.role == "assistant" and (.choices[0].message | has("content"))' >/dev/null 2>&1; then
echo "healthy=true" >> "$GITHUB_OUTPUT"
else
echo "healthy=false" >> "$GITHUB_OUTPUT"
fi
else
echo "healthy=false" >> "$GITHUB_OUTPUT"
fi
# ── 检查 www.lanlan.app (US, new) ──
- name: Check www.lanlan.app (new)
id: check_api_app
run: |
HTTP_CODE=$(curl -s -o /tmp/resp_api_app.json -w "%{http_code}" \
--max-time 30 --connect-timeout 10 \
-X POST "https://www.lanlan.app/text/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer free-access" \
-d '{"model":"free-mini-model","messages":[{"role":"user","content":"sends some useful information"}],"max_completion_tokens":5}' \
2>/dev/null || echo "000")
BODY=$(cat /tmp/resp_api_app.json 2>/dev/null || echo "{}")
echo "http_code=$HTTP_CODE" >> "$GITHUB_OUTPUT"
if [ "$HTTP_CODE" = "200" ]; then
if echo "$BODY" | jq -e '(.choices | type) == "array" and (.choices | length) > 0 and (.choices[0].message | type) == "object" and .choices[0].message.role == "assistant" and (.choices[0].message | has("content"))' >/dev/null 2>&1; then
echo "healthy=true" >> "$GITHUB_OUTPUT"
else
echo "healthy=false" >> "$GITHUB_OUTPUT"
fi
else
echo "healthy=false" >> "$GITHUB_OUTPUT"
fi
# ── 检查 www.lanlan.tech (China, new) ──
- name: Check www.lanlan.tech (new)
id: check_api_tech
run: |
HTTP_CODE=$(curl -s -o /tmp/resp_api_tech.json -w "%{http_code}" \
--max-time 30 --connect-timeout 10 \
-X POST "https://www.lanlan.tech/text/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer free-access" \
-d '{"model":"free-mini-model","messages":[{"role":"user","content":"sends some useful information"}],"max_completion_tokens":5}' \
2>/dev/null || echo "000")
BODY=$(cat /tmp/resp_api_tech.json 2>/dev/null || echo "{}")
echo "http_code=$HTTP_CODE" >> "$GITHUB_OUTPUT"
if [ "$HTTP_CODE" = "200" ]; then
if echo "$BODY" | jq -e '(.choices | type) == "array" and (.choices | length) > 0 and (.choices[0].message | type) == "object" and .choices[0].message.role == "assistant" and (.choices[0].message | has("content"))' >/dev/null 2>&1; then
echo "healthy=true" >> "$GITHUB_OUTPUT"
else
echo "healthy=false" >> "$GITHUB_OUTPUT"
fi
else
echo "healthy=false" >> "$GITHUB_OUTPUT"
fi
# ── 推送结果到 Discord(仅当 secret 存在时) ──
- name: Send Discord notification
env:
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_HEALTH_WEBHOOK_URL }}
if: env.DISCORD_WEBHOOK_URL != ''
run: |
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
APP_HEALTHY="${{ steps.check_app.outputs.healthy }}"
APP_CODE="${{ steps.check_app.outputs.http_code }}"
API_APP_HEALTHY="${{ steps.check_api_app.outputs.healthy }}"
API_TECH_HEALTHY="${{ steps.check_api_tech.outputs.healthy }}"
API_APP_CODE="${{ steps.check_api_app.outputs.http_code }}"
API_TECH_CODE="${{ steps.check_api_tech.outputs.http_code }}"
ALL_HEALTHY="true"
ANY_DOWN="false"
for h in "$APP_HEALTHY" "$API_APP_HEALTHY" "$API_TECH_HEALTHY"; do
if [ "$h" = "false" ]; then
ALL_HEALTHY="false"
ANY_DOWN="true"
fi
done
if [ "$ALL_HEALTHY" = "true" ]; then
COLOR=3066993 # green
TITLE="All Servers Healthy"
elif [ "$APP_HEALTHY" = "false" ] && [ "$API_APP_HEALTHY" = "false" ] && [ "$API_TECH_HEALTHY" = "false" ]; then
COLOR=15158332 # red
TITLE="All Servers Down"
else
COLOR=15105570 # orange
TITLE="Partial Outage"
fi
if [ "$APP_HEALTHY" = "true" ]; then
APP_STATUS=":white_check_mark: OK (HTTP $APP_CODE)"
else
APP_STATUS=":x: DOWN (HTTP $APP_CODE)"
fi
if [ "$API_APP_HEALTHY" = "true" ]; then
API_APP_STATUS=":white_check_mark: OK (HTTP $API_APP_CODE)"
else
API_APP_STATUS=":x: DOWN (HTTP $API_APP_CODE)"
fi
if [ "$API_TECH_HEALTHY" = "true" ]; then
API_TECH_STATUS=":white_check_mark: OK (HTTP $API_TECH_CODE)"
else
API_TECH_STATUS=":x: DOWN (HTTP $API_TECH_CODE)"
fi
# 只在有故障时 @everyone
CONTENT=""
if [ "$ANY_DOWN" = "true" ]; then
CONTENT="@everyone Server alert!"
fi
PAYLOAD=$(jq -n \
--arg content "$CONTENT" \
--arg title "$TITLE" \
--argjson color "$COLOR" \
--arg app_status "$APP_STATUS" \
--arg api_app_status "$API_APP_STATUS" \
--arg api_tech_status "$API_TECH_STATUS" \
--arg timestamp "$TIMESTAMP" \
'{
content: (if $content == "" then null else $content end),
embeds: [{
title: $title,
color: $color,
fields: [
{name: "lanlan.app (US, old)", value: $app_status, inline: true},
{name: "\u200b", value: "\u200b", inline: false},
{name: "www.lanlan.app (US, new)", value: $api_app_status, inline: true},
{name: "www.lanlan.tech (China, new)", value: $api_tech_status, inline: true}
],
footer: {text: "N.E.K.O Health Monitor"},
timestamp: $timestamp
}]
}')
curl -s -X POST "$DISCORD_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "$PAYLOAD"