From 3d3147c6069a0eff8c191f18decf726492fee014 Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 3 Sep 2018 11:56:58 +0900 Subject: [PATCH] Add server monitoring module --- src/index.ts | 4 +- src/modules/server/index.ts | 106 ++++++++++++++++++++++++++++++++++++ src/serifs.ts | 4 ++ torisetu.md | 3 + 4 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 src/modules/server/index.ts diff --git a/src/index.ts b/src/index.ts index 4f7f327..e26bd05 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,6 +10,7 @@ import GuessingGameModule from './modules/guessing-game'; import KeywordModule from './modules/keyword'; import WelcomeModule from './modules/welcome'; import TimerModule from './modules/timer'; +import ServerModule from './modules/server'; import * as request from 'request-promise-native'; import IModule from './module'; @@ -34,7 +35,8 @@ promiseRetry(retry => { new FortuneModule(), new GuessingGameModule(), new ReversiModule(), - new TimerModule() + new TimerModule(), + new ServerModule() ]; if (config.keywordEnabled) modules.push(new KeywordModule()); diff --git a/src/modules/server/index.ts b/src/modules/server/index.ts new file mode 100644 index 0000000..45228b3 --- /dev/null +++ b/src/modules/server/index.ts @@ -0,0 +1,106 @@ +import * as WebSocket from 'ws'; +import 藍 from '../../ai'; +import IModule from '../../module'; +import serifs from '../../serifs'; +import config from '../../config'; +const ReconnectingWebSocket = require('../../../node_modules/reconnecting-websocket/dist/reconnecting-websocket-cjs.js'); + +export default class ServerModule implements IModule { + public readonly name = 'server'; + + private ai: 藍; + private connection?: any; + private recentStat: any; + private warned = false; + private lastWarnedAt: number; + + /** + * 1秒毎のログ1分間分 + */ + private statsLogs: any[] = []; + + public install = (ai: 藍) => { + this.ai = ai; + + this.connection = new ReconnectingWebSocket(`${config.wsUrl}/server-stats`, [], { + WebSocket: WebSocket + }); + + this.connection.addEventListener('open', () => { + console.log('server-stats stream opened'); + }); + + this.connection.addEventListener('close', () => { + console.log('server-stats stream closed'); + + this.connection.reconnect(); + }); + + this.connection.addEventListener('message', message => { + const msg = JSON.parse(message.data); + + this.onConnectionMessage(msg); + }); + + setInterval(() => { + this.statsLogs.unshift(this.recentStat); + if (this.statsLogs.length > 60) this.statsLogs.pop(); + }, 1000); + + setInterval(() => { + this.check(); + }, 3000); + } + + private check = () => { + const average = (arr) => arr.reduce((a, b) => a + b) / arr.length; + + const cpuPercentages = this.statsLogs.map(s => s.cpu_usage * 100); + const cpuPercentage = average(cpuPercentages); + if (cpuPercentage >= 70) { + this.warn(); + } else if (cpuPercentage <= 30) { + this.warned = false; + } + } + + private onConnectionMessage = (msg: any) => { + switch (msg.type) { + + case 'stats': { + this.onStats(msg.body); + break; + } + + default: + break; + } + } + + private onStats = async (stats: any) => { + this.recentStat = stats; + } + + private warn = () => { + //#region 前に警告したときから一旦落ち着いた状態を経験していなければ警告しない + // 常に負荷が高いようなサーバーで無限に警告し続けるのを防ぐため + if (this.warned) return; + //#endregion + + //#region 前の警告から1時間経っていない場合は警告しない + const now = Date.now(); + + if (this.lastWarnedAt != null) { + if (now - this.lastWarnedAt < (1000 * 60 * 60)) return; + } + + this.lastWarnedAt = now; + //#endregion + + this.ai.post({ + text: serifs.server.cpu + }); + + this.warned = true; + } +} diff --git a/src/serifs.ts b/src/serifs.ts index 6624247..1ab15e5 100644 --- a/src/serifs.ts +++ b/src/serifs.ts @@ -228,5 +228,9 @@ export default { tooLong: '長すぎます…', notify: (time, name) => name ? `${name}、${time}経ちましたよ!` : `${time}経ちましたよ!` + }, + + server: { + cpu: 'サーバーの負荷が高そうです。大丈夫でしょうか...?' } }; diff --git a/torisetu.md b/torisetu.md index a088928..739c7c1 100644 --- a/torisetu.md +++ b/torisetu.md @@ -46,6 +46,9 @@ Misskeyに24時間常駐している。AIなので睡眠は不要だが、たま ### なでなで スキンシップ。(メッセージでのみ反応) +### サーバー監視 +サーバーの状態を監視し、負荷が高くなっているときは教えてくれます。 + ### ping PONGを返します。生存確認にどうぞ