Files
ewoooc/n8n-workflows/25-capacity-planning.json
ogt 1b4f3a7bbe
Some checks failed
CD Pipeline / deploy (push) Failing after 59s
feat: EwoooC 初始化 — 完整專案推版至 Gitea
- 建立 Gitea Actions CD pipeline (.gitea/workflows/cd.yaml)
- 部署模式: rsync Python 檔案至 188 → docker restart (volume mount)
- Dockerfile/requirements 變動時自動重建 Docker image
- 部署通知: Telegram (開始/成功/失敗)
- 健康檢查: https://mo.wooo.work/health (最多 5 次重試)
- 同步最新 CLAUDE.md / ADR-008 / memory (2026-04-19)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 01:21:13 +08:00

136 lines
7.1 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"name": "容量規劃與趨勢分析",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 1 * *"
}
]
}
},
"id": "schedule",
"name": "每月 1 日 08:00",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [240, 300]
},
{
"parameters": {
"url": "https://mo.wooo.work/api/system/db/stats",
"options": { "timeout": 30000 }
},
"id": "uat-db-stats",
"name": "UAT DB 統計",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [460, 200],
"continueOnFail": true
},
{
"parameters": {
"url": "https://momo.wooo.work/api/system/db/stats",
"options": { "timeout": 30000 }
},
"id": "gcp-db-stats",
"name": "GCP DB 統計",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [460, 400],
"continueOnFail": true
},
{
"parameters": {
"mode": "combine",
"combineBy": "combineAll",
"options": {}
},
"id": "merge",
"name": "合併結果",
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [680, 300]
},
{
"parameters": {
"jsCode": "const results = $input.all();\nconst now = new Date();\nconst monthKey = now.toISOString().slice(0, 7);\n\n// 從 static data 讀取歷史數據\nconst history = $getWorkflowStaticData('global');\nif (!history.monthly) {\n history.monthly = [];\n}\n\nconst uatStats = results[0]?.json || {};\nconst gcpStats = results[1]?.json || {};\n\n// 記錄本月數據\nhistory.monthly.push({\n month: monthKey,\n uat: {\n dbSize: uatStats.database_size_mb || 0,\n connections: uatStats.connection_count || 0,\n tableCount: uatStats.table_count || 0\n },\n gcp: {\n dbSize: gcpStats.database_size_mb || 0,\n connections: gcpStats.connection_count || 0,\n tableCount: gcpStats.table_count || 0\n }\n});\n\n// 保留最近 12 個月\nif (history.monthly.length > 12) {\n history.monthly.shift();\n}\n\n// 計算成長趨勢\nconst monthsData = history.monthly;\nlet uatGrowthRate = 0;\nlet gcpGrowthRate = 0;\nlet uatPrediction = 0;\nlet gcpPrediction = 0;\n\nif (monthsData.length >= 2) {\n const lastMonth = monthsData[monthsData.length - 2];\n const thisMonth = monthsData[monthsData.length - 1];\n \n if (lastMonth.uat.dbSize > 0) {\n uatGrowthRate = ((thisMonth.uat.dbSize - lastMonth.uat.dbSize) / lastMonth.uat.dbSize * 100).toFixed(1);\n // 預測 6 個月後的大小\n uatPrediction = (thisMonth.uat.dbSize * Math.pow(1 + parseFloat(uatGrowthRate) / 100, 6)).toFixed(0);\n }\n \n if (lastMonth.gcp.dbSize > 0) {\n gcpGrowthRate = ((thisMonth.gcp.dbSize - lastMonth.gcp.dbSize) / lastMonth.gcp.dbSize * 100).toFixed(1);\n gcpPrediction = (thisMonth.gcp.dbSize * Math.pow(1 + parseFloat(gcpGrowthRate) / 100, 6)).toFixed(0);\n }\n}\n\n// 容量警告閾值\nconst DB_SIZE_WARNING = 8000; // 8GB\nconst DB_SIZE_CRITICAL = 9000; // 9GB\n\nconst uatWarning = (uatStats.database_size_mb || 0) > DB_SIZE_WARNING;\nconst gcpWarning = (gcpStats.database_size_mb || 0) > DB_SIZE_WARNING;\nconst uatPredictionWarning = parseFloat(uatPrediction) > DB_SIZE_CRITICAL;\nconst gcpPredictionWarning = parseFloat(gcpPrediction) > DB_SIZE_CRITICAL;\n\nreturn [{\n json: {\n uat: {\n currentSize: (uatStats.database_size_mb || 0) + ' MB',\n growthRate: uatGrowthRate + '%',\n prediction6m: uatPrediction + ' MB',\n warning: uatWarning,\n predictionWarning: uatPredictionWarning\n },\n gcp: {\n currentSize: (gcpStats.database_size_mb || 0) + ' MB',\n growthRate: gcpGrowthRate + '%',\n prediction6m: gcpPrediction + ' MB',\n warning: gcpWarning,\n predictionWarning: gcpPredictionWarning\n },\n historyMonths: monthsData.length,\n hasWarning: uatWarning || gcpWarning || uatPredictionWarning || gcpPredictionWarning\n }\n}];"
},
"id": "analyze",
"name": "分析趨勢",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [900, 300]
},
{
"parameters": {
"jsCode": "const data = $input.first().json;\nconst now = new Date().toLocaleString('zh-TW', { timeZone: 'Asia/Taipei' });\n\nlet message = `📈 <b>每月容量規劃報告</b>\\n\\n`;\n\nmessage += `<b>🟦 UAT 環境</b>\\n`;\nmessage += `├ 目前大小: ${data.uat.currentSize}\\n`;\nmessage += `├ 月成長率: ${data.uat.growthRate}\\n`;\nmessage += `├ 6 個月預測: ${data.uat.prediction6m}\\n`;\nif (data.uat.warning) {\n message += `└ ⚠️ 警告:接近容量上限\\n`;\n} else if (data.uat.predictionWarning) {\n message += `└ ⚠️ 預測6 個月內可能超過容量\\n`;\n} else {\n message += `└ ✅ 容量正常\\n`;\n}\n\nmessage += `\\n<b>🟥 GCP 環境</b>\\n`;\nmessage += `├ 目前大小: ${data.gcp.currentSize}\\n`;\nmessage += `├ 月成長率: ${data.gcp.growthRate}\\n`;\nmessage += `├ 6 個月預測: ${data.gcp.prediction6m}\\n`;\nif (data.gcp.warning) {\n message += `└ ⚠️ 警告:接近容量上限\\n`;\n} else if (data.gcp.predictionWarning) {\n message += `└ ⚠️ 預測6 個月內可能超過容量\\n`;\n} else {\n message += `└ ✅ 容量正常\\n`;\n}\n\nmessage += `\\n📊 歷史數據: ${data.historyMonths} 個月\\n`;\nmessage += `⏰ 報告時間: ${now}`;\n\nreturn [{ json: { message } }];"
},
"id": "format-report",
"name": "格式化報告",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [1120, 300]
},
{
"parameters": {
"url": "https://api.telegram.org/bot8075645931:AAH-EGKMo8ZC4QJs-Nc1_0s92xHrGdQvdpg/sendMessage",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"chat_id\": \"5619078117\",\n \"parse_mode\": \"HTML\",\n \"text\": \"{{ $json.message }}\"\n}",
"options": {}
},
"id": "telegram",
"name": "發送報告",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [1340, 300]
}
],
"connections": {
"每月 1 日 08:00": {
"main": [
[
{ "node": "UAT DB 統計", "type": "main", "index": 0 },
{ "node": "GCP DB 統計", "type": "main", "index": 0 }
]
]
},
"UAT DB 統計": {
"main": [
[{ "node": "合併結果", "type": "main", "index": 0 }]
]
},
"GCP DB 統計": {
"main": [
[{ "node": "合併結果", "type": "main", "index": 1 }]
]
},
"合併結果": {
"main": [
[{ "node": "分析趨勢", "type": "main", "index": 0 }]
]
},
"分析趨勢": {
"main": [
[{ "node": "格式化報告", "type": "main", "index": 0 }]
]
},
"格式化報告": {
"main": [
[{ "node": "發送報告", "type": "main", "index": 0 }]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [],
"triggerCount": 0,
"updatedAt": "2026-02-07T17:00:00.000Z",
"versionId": "1"
}