はじめに
1つ前の記事 でLambdaについてなんとなく把握したので、今回はWebサイトのレスポンスタイムの計測をLambdaで実施してみることにします
Google SpreadSheetに計測結果を記録しておけば、簡単にグラフ化できそうなので便利そうです。
ということで、結果はSheets APIを使って記録することにします
SpreadSheetの準備
- Sheets APIを使うために必要なので、Google API Console(旧称)でサービスアカウントキーを発行して、jsonファイルをダウンロードしておきます
参考:https://www.magellanic-clouds.com/blocks/guide/create-gcp-service-account-key/
ファイル名はcredentials.json
とします - Google SpreadSheetを新規作成し、「シート1」を雛形として以下のようにします
このシートを日毎にコピーして結果を記録していくことにします - このSpreadSheetの共有設定で、1で発行したサービスアカウントのメールアドレスに対して書き込み権限を与えます
npm
package.jsonを作ります
npm init -y
Sheets APIの実行でgoogleapis
、
日付の操作でdate-utils
、
curlコマンドを実行するのにchild_process
が必要なのでインストールします
yarn add googleapis date-utils child_process
これで準備完了
コード
SSLを使っていて、ウェブサーバー2台構成それぞれがグローバルIPを持っていて、それぞれのサーバーの計測をすることを想定しています
Sheets APIのNode.jsサンプルはOAuthのものしかなくて苦労しました
Sheets APIのドキュメントは最初は理解しづらいけど、いちど見方がわかばなんとかなります
'use strict';
const { google } = require('googleapis');
require('date-utils');
const spreadsheetId = process.env.SPREADSHEETID;
const credentials = './credentials.json';
const hostname = 'expamle.com';
const hosts = {
'server1': '123.123.123.123',
'server2': '123.124.124.124'
};
exports.handler = async () => {
let response;
let worksheetTitle = new Date().toFormat('YYYY/MM/DD');
let datetime = new Date().toFormat('YYYY/MM/DD HH24:MI:SS');
// サービスアカウントキーを使って認証
const client = await google.auth.getClient({
keyFile: credentials,
scopes: 'https://www.googleapis.com/auth/spreadsheets'
});
// SheetsAPI
const sheets = google.sheets({
version: 'v4',
auth: client
});
// sheet一覧の取得
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/get
response = await sheets.spreadsheets.get({
spreadsheetId
});
// すでに当日のsheetがあるか確認する
let sheetsExists = false;
await response.data.sheets.some(worksheet => {
if (worksheet.properties.title == worksheetTitle) {
sheetsExists = true;
return;
}
});
if (sheetsExists === false) {
// sheetId = 0 をコピーする
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#duplicatesheetrequest
response = await sheets.spreadsheets.batchUpdate({
spreadsheetId,
resource: {
requests: [{
'duplicateSheet': {
sourceSheetId: 0,
newSheetName: worksheetTitle
}
}]
}
});
const newSheetId = response.data.replies[0].duplicateSheet.properties.sheetId;
await console.log('sheet duplicated: ' + newSheetId);
}
// curlを実行して計測する
const exec = require('child_process').execSync;
let responseTimes = [datetime];
for (let key in hosts) {
let $ip = hosts[key];
let curl_result = await exec('curl --connect-timeout 5 --max-time 10 -o /dev/null -s -w "%{time_namelookup}\n%{time_connect}\n%{time_appconnect}\n%{time_pretransfer}\n%{time_starttransfer}\n%{time_total}" --resolv ' + hostname + ':443:' + $ip + ' https://' + hostname).toString();
let curl_result_array = await curl_result.split('\n');
await Array.prototype.push.apply(responseTimes, curl_result_array);
}
await console.log(responseTimes);
// sheetに記録する
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/append
await sheets.spreadsheets.values.append({
spreadsheetId,
range: worksheetTitle + '!A1',
valueInputOption: 'USER_ENTERED',
requestBody: {
values: [responseTimes]
}
});
return 'success';
};
このままだと、SpreadSheetにUTCで記録されてしまうので、Lambdaの環境変数TZ
にAsia/Tokyo
と設定する必要があります
Lambdaに割り当てるメモリが多いほどレスポンスタイムが良くなります。でも1024MBを超えると大して変わりません
あとは、これをCloudWatch Eventsから好きなタイミングで呼ぶようにすればOKです
注意点
SpreadSheetの制限として、200万cellまでしか作れないようです
ずっと放置していると
Invalid requests[0].duplicateSheet: This action would increase the number of cells in the workbook above the limit of 2000000 cells.
と言われてsheetのコピーができなくなります
雛形となるシートの行数・列数を最小にしておくなどの工夫も必要でしょう