こんにちは、エンジニアの君島です。
いつの間にか、Webサイトに新しいページがたくさん追加されていることってありますよね。サイト自体の死活監視はもちろんのこと、意図しないリンク切れが発生していても気付かないこともあります。
今回は、Amazon CloudWatch SyntheticsをBlueprintのまま使うのだけではなく、手を加えてより実用的に外形監視する方法について紹介します。
目次
はじめに
やりたいこと
運用中のWebページのリンク切れチェックを実現してみよう、というのが主目的です。
更にもう少し要望を詳細化してみましょう。
- お手軽に実現できて、メンテナンスも簡単だといいな
- チェックのタイミングも変更したい
- ブログ記事のような動的に増えていくページはチェックから除外してもいいか
- エラー通知もあるといい(正常時にも通知するかは後で変更できると嬉しい)
考えたこと
やりたいことを実現するのに必要な機能を大別すると以下のようになります。
- スケジュール実行機能
- 実行タイミングを変更することができる
- リンク切れチェック処理
- ある程度対象のURLの制御ができる
- スクリーンショットは無くていい
- 通知機能
これらを実現するためには、まだ色々な方法が考えられます。
- URL一覧を作成して順にチェックする
- 実行基盤はLambdaやECSで0から全ての処理を書く
といった力技でも実現可能ですが、お手軽に実現できて、運用やメンテナンスも容易になるという要望を踏まえると、もう少し賢いやり方を考えられるはずです。
Amazon CloudWatch Syntheticsとは
前回の記事をご覧ください。
前回は解説が多かったので、今回は実用に重きを置いてみます。
実装
お手軽に実現
リンク切れチェッカーのBlueprintを利用します。
これだけでもかなり工数削減になります。通常であれば、VPC内にLambda関数を設置するようなアーキテクチャから考えて作業することになりますが、これで開発者はソースコードにだけ集中することができます。
スケジュール実行機能
チェックのタイミングは以下の通りに指定することができます。
- 継続的に実行
- CRON式
- 1回のみ実行
今回は、1日1回の間隔で指定してみます。UTCでの時刻設定になる点は気を付けてください。
リンク切れチェック処理
BlueprintでLambda関数も定義されるので、そこに手をを加えていきましょう。
環境変数は以下の2種類を設定しました。
- INC_PREFIX:チェック対象に含めるURLのPREFIX
- EXC_PREFIX:チェック対象から除外したいURLのPREFIX
ここから具体的にプログラムを編集していきましょう。
上記の環境変数は、チェック対象に含めたい、もしくは除外したいURLがあった場合に設定する目的です。
具体的には、
- 指定したサイトではない外部リンクのチェックを防ぐためにINC_PREFIX
- 指定したサイト内でも除外したいURLがある場合にEXC_PREFIX
を指定しています。
ページ内のリンクを取得するのはgrabLinks関数ですので、その内部の処理に判定を追加します。
1 2 3 4 5 6 |
if (element) { let url = element.url; if (!url.startsWith(process.env.INC_PREFIX) || url.startsWith(process.env.EXC_PREFIX)) continue; let originalBorderProp = element.originalBorderProp; exploredUrls.push(url); |
また、自社サイトのようにメニューを持つページの場合、既に検証済みのリンクについてもチェックをしてしまうことがありました。
こちらもgrabLinks関数内で、既に配列の要素に含まれるURLは除くように判定を追加します。
1 2 3 4 5 |
let element = jsHandle[i]; let url = String(element.href).trim(); // Condition for grabbing a link if (url != null && url.length > 0 && !exploredUrls.includes(url) && (url.startsWith('http') || url.startsWith('https'))) { |
あとはお好みになりますが、スクリーンショットが不要である場合はフラグ値をfalseにしておきましょう。
1 2 3 4 5 6 7 8 9 |
// Captures source page annotated screenshot for each link followed on a page. const captureSourcePageScreenshot = false; // Captures destination page screenshot after loading a link successfully. const captureDestinationPageScreenshotOnSuccess = false; // Captures destination page screenshot for broken links only. Note that links which do not return response have no destination screenshots. const captureDestinationPageScreenshotOnFailure = false; |
なお、いつの間にかマネジメントコンソールから設定できるようになっていました。
ただ、スクリーンショットを撮らないようにすると、チェック対象のURLのソース元が分かりにくいのでログに残す等工夫をしておきましょう。
例えば、grabLinks関数に以下のようなコードを入れてみます。
1 2 3 4 5 |
let originalBorderProp = element.originalBorderProp; linkInfo = "New url:"+ url +" is found in sourceUrl:" + sourceUrl; log.info(linkInfo); exploredUrls.push(url); |
また、リンク切れ検証のタイムアウトは一律30秒となっているので、長すぎると思う場合は変更してみます。正常に動作しているのであればすぐに応答は返ってきますので、変更による影響は小さいです。
なお、timeoutの単位はmsecとなっています。
以下のコードでは10秒でタイムアウトとなっています。
1 2 |
response = await page.goto(nav_url, {waitUntil: ['load', 'networkidle0'], timeout: 10000}); |
通知機能
実装する必要なく、アラームとSNSトピックを設定することができます。
複数のアラームを設定することもできますが、こういった通知は失敗した場合にのみ通知するようにしておくことが多いかと思います。
これで通知も解決します。
結果
実行してみたところ、対象のWebサイト内にまさにステータスコード404でリング切れになっているページがあることを検出することができました。
実行ログはs3やマネジメントコンソールから確認できるので、内容を見て修正箇所を簡単に特定することができます。
また、スクリーンショットを撮っていれば、リンクのある要素をハイライトした結果をマネジメントコンソールから確認することもできます。
また、BlueprintのままとカスタマイズしたCanaryとで結果を比較してみたところ以下のようになりました。
Canary | リンク数 | 実行時間[s] | 結果 | 備考 |
---|---|---|---|---|
Blueprint | 100 | 645 | NG | 外部リンクを参照してNG |
Customize | 100 | 465 | OK |
同じリンク数をチェックしていても実行時間に差が出たのは、Blueprintはタイムアウトを30秒としている点が影響していました。
また、注意点としては、Canaryの最大実行時間はLambdaのクォータの15分に対応した14分=840秒となる点です。
マネジメントコンソールから15分を指定したところ、バリデーションエラーとなりました。
合計の実行時間が840秒以内になるように、リンク数の設定やパラメータ指定は必要になるので注意が必要です。
まとめ
Amazon CloudWatch Synthetics Canaryのリンク切れチェッカーのソースコードを改変し、パラメータをチューニングして、Webサイトのリンク切れチェックを実際に行いました。
Canaryを実行したところ、実際のリンク切れの検知もできて、対象箇所の特定と修正も容易に行うことができることまで確認しました。
通知とスケジュール設定も行ったので、これで新たにリンク切れが検知できれば通知が飛んでくるようになりました。手を動かしてチェックしたり、心配する必要もなくなるだけでなく、E2Eの自動テストと違って新たにページ追加したことによるテストスクリプトの変更もないので、今後の運用でも耐えられそうです。
改めてBlueprintの偉大さを感じました。アーキテクチャを設計したり、構築する必要がないので、ソースコードを中心に労力を割くことができます。
そのため、お手軽に短時間で以下の要望していた機能を実現することができました。
- スケジュール実行機能
- 実行タイミングを変更することができる
- リンク切れチェック処理
- ある程度対象のURLの制御ができる
- スクリーンショットは無くていい
- 通知機能
- CLIでAmazon S3にあるファイル内の文字列検索をしてみる - 2024-02-01
- 不完全なマルチパートアップロードをCLIで確認してS3の無駄コストを無くそう - 2024-01-29
- AlmaLinux9.3にPHP8.3を入れてLaravel9から10にバージョンアップする - 2024-01-12
- AWS CloudShellの表現力を確認してみよう - 2024-01-01
- AWSのアーキテクチャーを学べるAWS Card Clash攻略Wiki - 2023-12-26