Google Chromeのヘッドレスモードで外形監視が細かくできそうなのでやってみた
こんにちは。
開発チームのワイルド担当、まんだいです。
株式会社ビヨンドは、MSPなので、お客様のオーダーによって、色々な監視をしています。
その中で外形監視という監視があり、これはユーザーがサイトにアクセスするのと同じ(もしくは近しい)方法でサイトにアクセスし、ページが正常に表示できているかをチェックするものです。
サイトにアクセスし、正常にデータが取れているかは何なりとツールもありますし、自前でcurlなどでやれなくもないですが、これらの方法では、各種モニタリングツールからのアラートを受けた人がサイトにアクセスして初めて原因を探ることができます。
それでもいいんですが、今回はGoogle Chromeのヘッドレスモードを使えば、DevToolsを経由して、どのコンテンツの取得に時間が掛かっているのかまで細かく取得が可能なので、サイトを見ずとも原因究明が可能になるかも知れないよという可能性を探ってみたいと思います。
準備編
まずは一通り試すのに必要なものを揃えます。
後の方にコピペで動くサンプルもあります。
Google Chrome
まずは、ヘッドレスモードで動くGoogle Chrome(バージョン59以上)をインストールします。
このバージョンのGoogle Chromeは既に安定版ですので、通常通りインストーラーを使ってインストールします。
また、自動更新が有効だと、既に導入されていると思います。
Node.js
今回は、最新版の8.0.0を利用しましたが、そこそこ古くても大丈夫なのではないかと思います。
以下のモジュールをnpmでインストールしています。
- chrome-launcher
- chrome-remote-interface
chrome-launcherは、Node.jsからGoogle Chromeを起動する際に利用しています。
chrome-remote-interfaceは、Node.jsからGoogle ChromeのDevToolsにアクセスする際に利用しています。
npm install chrome-launcher chrome-remote-interface
サンプルスクリプトでは、起動時に毎回Google Chromeを起動し、終了時に停止する処理が入っていますが、本格的に利用するのであれば、Google Chromeは起動しっぱなしでもいいような気もします(メモリ使用量がどんどん膨らんでいきそうな気もするので、定期的なリスタートは必要かもしれません)。
以上の2つを導入すれば、準備は完了です。
Google Chromeのヘッドレスモードに関する基本的な使い方については、Google Chrome 59でヘッドレスモードが標準搭載されたのでいじってみるを参考にしていただけると思います。
Node.jsからGoogle Chromeのヘッドレスモードを利用する基本的な方法については、Node.jsからヘッドレスGoogle Chromeを使ってみるをどうぞ。
サンプルスクリプト
以下のサンプルを用意しましたので、ご利用はご自由に!
const ChromeLauncher = require('chrome-launcher'); const CDP = require('chrome-remote-interface'); function launchChrome(headless = true) { ChromeLauncher.launch({ port: 9222, autoSelectChrome: true, chromeFlags: [ '--disable-gpu', headless ? '--headless' : '', '--no-sandbox', ], }).then(launcher => { CDP(protocol => { setTimeout(() => { protocol.close(); launcher.kill(); process.exit(); }, 10000); const {Page, Network} = protocol; Promise.all([ Page.enable(), Network.enable(), ]).then(() => { Page.navigate({url : 'https://beyondjapan.com/blog/2017/07/headless-chrome-networks'}); Network.responseReceived(res => { console.log(r) }) }) }) }) } launchChrome();
勝手に終了するわけではないので、setTimeoutを使って10秒後に終了するようにしています。
1ページ内に発生する通信が多いサイトだと出力も多いですが、1つ抜き出してみると
{ requestId: '30371.7375', frameId: '30371.1', loaderId: '30371.190', timestamp: 1197407.412915, type: 'Document', response: { url: 'https://beyondjapan.com/', status: 200, statusText: 'OK', headers: { Date: 'Tue, 18 Jul 2017 04:16:02 GMT', 'Transfer-Encoding': 'chunked', Server: 'nginx', Connection: 'keep-alive', Link: '<https://beyondjapan.com/cms-json/>; rel="https://api.w.org/"', Vary: 'Accept-Encoding', 'Content-Type': 'text/html; charset=UTF-8' }, mimeType: 'text/html', connectionReused: false, connectionId: 5394, remoteIPAddress: '122.218.102.93', remotePort: 80, fromDiskCache: false, fromServiceWorker: false, encodedDataLength: 253, timing: { requestTime: 1197406.917743, proxyStart: -1, proxyEnd: -1, dnsStart: 0.944999977946281, dnsEnd: 2.30200006626546, connectStart: 2.30200006626546, connectEnd: 7.89500004611909, sslStart: -1, sslEnd: -1, workerStart: -1, workerReady: -1, sendStart: 7.98300001770258, sendEnd: 8.11700010672212, pushStart: 0, pushEnd: 0, receiveHeadersEnd: 494.426999939606 }, protocol: 'http/1.1', securityState: 'neutral' } }
DevToolsのNetworkタブで取れる情報は概ね取得できているようです。
タイムスタンプ周りの単位は全てミリ秒となっているようです。
他にもcookieの削除や追加(これはセッションを使ったサイトの監視に便利かも)、キャッシュのクリアユーザーエージェントの書き換えなど、DevToolsでできることは一通りできるようです。
D3.jsあたりで取得したデータを表示するUIを作るのも楽しそうですね!
まとめ
Google Chromeのヘッドレスモードでやる外形監視、いかがでしたか?
監視ツールを使うほうがコストが掛からないとは思いますが、読み込むコンテンツのレスポンスが全て取れるので、CDNでなんかあったのかとか、APIからのレスポンスが激しく遅いとか、そういった切り分けが即座にできるようになりそうで使い道はありそうです。
以上です。