mirror of
https://github.com/syuilo/ai.git
synced 2024-11-22 13:17:59 +00:00
Add server monitoring module
This commit is contained in:
parent
0b6c9323df
commit
3d3147c606
|
@ -10,6 +10,7 @@ import GuessingGameModule from './modules/guessing-game';
|
||||||
import KeywordModule from './modules/keyword';
|
import KeywordModule from './modules/keyword';
|
||||||
import WelcomeModule from './modules/welcome';
|
import WelcomeModule from './modules/welcome';
|
||||||
import TimerModule from './modules/timer';
|
import TimerModule from './modules/timer';
|
||||||
|
import ServerModule from './modules/server';
|
||||||
|
|
||||||
import * as request from 'request-promise-native';
|
import * as request from 'request-promise-native';
|
||||||
import IModule from './module';
|
import IModule from './module';
|
||||||
|
@ -34,7 +35,8 @@ promiseRetry(retry => {
|
||||||
new FortuneModule(),
|
new FortuneModule(),
|
||||||
new GuessingGameModule(),
|
new GuessingGameModule(),
|
||||||
new ReversiModule(),
|
new ReversiModule(),
|
||||||
new TimerModule()
|
new TimerModule(),
|
||||||
|
new ServerModule()
|
||||||
];
|
];
|
||||||
|
|
||||||
if (config.keywordEnabled) modules.push(new KeywordModule());
|
if (config.keywordEnabled) modules.push(new KeywordModule());
|
||||||
|
|
106
src/modules/server/index.ts
Normal file
106
src/modules/server/index.ts
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -228,5 +228,9 @@ export default {
|
||||||
tooLong: '長すぎます…',
|
tooLong: '長すぎます…',
|
||||||
|
|
||||||
notify: (time, name) => name ? `${name}、${time}経ちましたよ!` : `${time}経ちましたよ!`
|
notify: (time, name) => name ? `${name}、${time}経ちましたよ!` : `${time}経ちましたよ!`
|
||||||
|
},
|
||||||
|
|
||||||
|
server: {
|
||||||
|
cpu: 'サーバーの負荷が高そうです。大丈夫でしょうか...?'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,6 +46,9 @@ Misskeyに24時間常駐している。AIなので睡眠は不要だが、たま
|
||||||
### なでなで
|
### なでなで
|
||||||
スキンシップ。(メッセージでのみ反応)
|
スキンシップ。(メッセージでのみ反応)
|
||||||
|
|
||||||
|
### サーバー監視
|
||||||
|
サーバーの状態を監視し、負荷が高くなっているときは教えてくれます。
|
||||||
|
|
||||||
### ping
|
### ping
|
||||||
PONGを返します。生存確認にどうぞ
|
PONGを返します。生存確認にどうぞ
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue