Lambdaで外形監視をしてサービスダウンしたらDatadogでアラートを出させる

Datadogで監視をしているシステムで外形監視をしたいということがあったのだけど、Datadogで用意されている外形監視の方法というのがDatadogエージェントが必要になってしまう。 それだと監視用のホストで余分にお金がかかってしまうので、Lambdaから1分間隔で監視をして、連続してアクセスできなかった回数をメトリクスとしてDatadogに転送させることで外形監視をさせることにした(3回連続で失敗したらアラートを出させる)。

Lambdaの環境変数を使っているので、「ERR_COUNT」でデフォルト値0で定義しておくのを忘れずに行うこと。 httpステータスが200以外の場合はアラートが出るようにしている(あと、タイムアウトとLambda自体でエラーが出た場合にアラートが出るとうざいかと思ったので、そこは出さないようにしている)。 事前にDatadogの契約をしておき、まず以下のコードをLambda関数として登録し、Cloudwatch Alertで定期実行(外形監視なので1分くらいか?)させる(APIキーとか環境変数に突っ込んでも良かったんだけど、とりあえず最初に定義させてる)。

CheckHttpStatus
var https = require ('https'); var host = 'orebibou.com'; var testTarget = 'https://' + host; //監視対象url var ddpost = function (now_utime,tghost,post_var){ var ddhost = 'app.datadoghq.com'; //Datadogホスト var ddkey = 'APIキー'; //Datadog APIキー var ddpath = '/api/v1/series' + '?api_key=' + ddkey; // Datadogにエラーカウントをポスト let postData = { "series": [{"metric":"urlcheck." + tghost, "points":[[now_utime, post_var]], "type":"gauge", "tags":["env:lambda","url:"+tghost]}] }; let postDataStr = JSON.stringify(postData); let options = { host: ddhost, path: ddpath, method: 'POST', headers: { 'd-Type': 'application/json' } }; let post = https.request(options, (post) => { console.log('STATUS: ' + post.statusCode); console.log('HEADERS: ' + JSON.stringify(post.headers)); post.setEncoding('utf8'); post.on('data', (chunk) => { console.log('BODY: ' + chunk); }); }); post.on('error', (e) => { console.log('problem with request: ' + e.message); }); post.write(postDataStr); post.end(); }; exports.handler = function(event, context,callback){ context.callbackWaitsForEmptyEventLoop = false; var now = Math.floor(new Date() / 1000); //現在時刻のUNIXタイム var req = https.request(testTarget, function (response) { console.log(now); console.log("ERR_COUNT:"+process.env.ERR_COUNT); var code = response.statusCode; var message = testTarget + " : " + code; console.log(message); // ステータスコードに応じてカウント if(code == '200'){ process.env.ERR_COUNT = 0; }else{ process.env.ERR_COUNT++; } console.log("ERR_COUNT : " + process.env.ERR_COUNT); ddpost(now,host,process.env.ERR_COUNT); callback(null,'exit'); }); // タイムアウト時の挙動について req.setTimeout(5000); req.on('timeout', function() { var message = testTarget + " : timeout"; process.env.ERR_COUNT++; ddpost(now,host,process.env.ERR_COUNT); console.log(message); req.abort(); }); // エラー発生時(404等ではなく、処理自体のエラー)の挙動について req.on('error', function (error) { var message = testTarget + " : " + error.message; process.env.ERR_COUNT++; ddpost(now,host,process.env.ERR_COUNT); console.log(message); }); req.end(); };

あとは、Datadog側でERR_COUNTを計上しているメトリクスを確認させて、対象のメトリクスが一定回数以上だったらアラートを出すようにモニターを作成すればいい。 流石にDatadogのモニターの作成方法やLambdaの定期実行方法は書かなくてもいいだろうと思うので割愛。