Syntheticsモニタリングを使用すると、アプリを監視しテストできるので、エンドユーザーに影響が生じる前に問題に対処できます。そのフルパワーを活用するための5つのヒントを以下にご紹介します。
1. Syntheticモニターを選択
Syntheticsモニターは、ウェブサイトのパフォーマンスを測定し、読み込み時間、稼働時間、平均ダウンロードサイズの集計値をキャプチャする仮想ブラウザです。また、ダウンタイムインシデントと各ページリソースに関する詳細な統計情報にもアクセスできます。
モニターの対象と方法に応じて、7種類のSyntheticモニターから選択できます。たとえば、ステップモニターは、コードを記述せずにスクリプト化されたブラウザとして、本質的に機能するものを作成するための優れた方法です。Syntheticモニターの自動管理をお探しの場合は、当社のNerdGraph APIを使用すると、API呼び出しを通じてSyntheticモニターを作成、更新、削除できます。
Syntheticモニターを追加する
- モニターを追加するには、one.newrelic.com > Syntheticsの順に移動します。(EUベースのアカウントをお持ちの場合は、one.eu.newrelic.comに移動します。) Create monitorをクリックします。
モニタータイプを選択し、すべての必須フィールドに入力します。
タグの追加、期間の変更、または別のランタイムバージョンの選択ができます。pingおよび単純なブラウザモニターでは、検証文字列を追加できます。高度なオプションを使用して、次のタイプの応答検証の部分文字列モニタリングを有効にすることができます。
SSL検証(Pingとシンプルブラウザ用)。このオプションは、SSL証明書チェーンの有効性を検証します。次の構文を実行することによって複製することができます。
bash$openssl s_client -servername {YOUR_HOSTNAME} -connect {YOUR_HOSTNAME}:443 -CApath /etc/ssl/certs > /dev/nullHEADリクエストのバイパス(Pingモニター用)。このオプションは、デフォルトのHEADリクエストをスキップし、その代わりにpingチェックを含むGET動詞を使用します。HEADリクエストが失敗した場合、GETリクエストは常時発生します。
Redirect is Failure(Ping用)。
Redirect is Failure
が有効になっているときにリダイレクト結果が発生すると、Syntheticsモニターはリダイレクトにしたがって、結果のURLをチェックするのではなく、結果をエラーとして分類します。
モニターを実行するロケーションを選択します。誤検出を避けるために、少なくとも3つの場所を選択するようにしてください。つまり、少なくとも1つの場所が成功した結果を返す場合、エンドポイントは稼働しており、アラートのトリガーを回避できます。
モニターの種類に応じて、モニターの保存、検証、スクリプトの記述のいずれかを行うよう求められます。
結果を受け取ったら、概要ページで表示します。
2. Syntheticモニターの概要ページを表示する
概要ページには、Syntheticモニターのステータスに関する情報が表示されます。アラートをトリガーするアクティブなインシデントが作成された場合は、このモニターのクリティカルなアラートをクリックして新しいタブで開きます。また、クリックしてページ上部のすべてのモニターのアラートポリシーを管理すると、モニターのすべてのアラートポリシーにアクセスすることもできます。
3. アプリケーションのパフォーマンスの全体像を把握
アプリケーションのパフォーマンス結果を継続的に確認して、ウェブサービスが適切に機能し、期待どおりに動作し、エラーが発生しないようにする必要があります。Syntheticsモニタリングでは、選択した場所ごとにウェブアプリケーションで自動テストを実行することで確実にします。Syntheticsモニターは、ダウンタイムインスタンス(「違反」と呼びます)を記録し、各ページリソースの集計数、結果、および詳細な統計情報を収集します。
モニターの障害をすばやく検出するには、合成モニターインデックスページを使用して、未解決の違反があるモニター、24時間にわたる成功率、障害が発生した場所の数、モニター期間、モニタータイプを確認できます。モニターをクリックすると概要ページが表示され、特定のモニターがどこで故障しているか、なぜ故障しているか(最後のエラーメッセージ、エラーレスポンスコード、ドメイン別の期間)などを評価するための情報が表示され、経時的なアプリケーションのパフォーマンスに関する深い洞察が提供されます。
エクスプローラーでモニターを表示する
4. 個々のモニター結果を表示する
世界中のさまざまな地域からアクセスされるウェブアプリのパフォーマンスを確認する必要があります。結果ページには、開発から本番までのすべてがユーザー体験にいかに影響するかが表示されます。リストされているものを並べ替えて、問題のある領域や異常結果を特定できます。場所別にフィルタリングして、さまざまな場所からのモニターのパフォーマンスを比較してみてください。(以下の「ネットワークタイミング」グラフは、一定期間にわたるウェブページのパフォーマンスのスナップショットを示しています。)これを行うには、以下を実行します。
- one.newrelic.com > Syntheticsの順に移動します。
- モニタータブからモニターを選択します。
- モニターをクリックし、結果をクリックします。
結果から監視対象の各場所に対して最も遅いページロードの最新のビューが得られます。
5. 各リソースのロードタイムへの影響を把握する
Syntheticsリソースページには、ウェブサイトのさまざまなコンポーネント(CSS、JavaScript、画像、HTMLなど)が全体的な負荷にどのように影響しているかが表示されます。ランタイムに収集される詳細なメトリクスを掘り下げて調べ、サードパーティリソースによって費やされる時間に関するパフォーマンス情報を検出し、各リソースのHTTP応答コードを特定することができます。これを行うには、以下を実行します。
- one.newrelic.comへ移動します。Syntheticsをクリックします。
- モニタードロップダウンメニューから、モニターを選択します。
- モニターをクリックし、リソースをクリックします。
6. スクリプト化ブラウザテストを設定して開発する
スクリプト化ブラウザを使用して、Selenium JavaScript Webdriverバインディングで複雑な監視ワークフローを構築できます。たとえば、アプリケーションにログインして特定のリンクにナビゲートし、ページ要素がロードされてアサーションを追加するのを待機できます。これを行うには、以下を実行します。
- one.newrelic.com > Syntheticsの順に移動します。
- モニタータイプ(スクリプト化ブラウザなど)を選択します。
- モニターの名前と詳細(
sitename.com
のスクリプト化ブラウザなど)を入力します - モニターを実行する場所 (ムンバイ、ソウル、コロンバス、モントリオールなど) を選択します。
- ここからモニターを実行する頻度 (5分など) を選択します。
- パフォーマンス違反が発生した際にチームに送信するアラート通知を設定します。
- これでスクリプトを記述する準備ができました。(以下は、newrelic.comのパフォーマンスをテストし、特定の要素が読み込まれたことを確認するスクリプトの例です。)
/** * Script Name: Best Practices - Chrome 100 * Author: New Relic * Version: 1.3 * Purpose: best practices example * Reference: https://docs.newrelic.com/docs/synthetics/synthetic-monitoring/scripting-monitors/synthetic-scripted-browser-reference-monitor-versions-chrome-100/ */
// -------------------- CONSTANTSconst SCRIPT_NAME = "Best Practices - Chrome 100" // name to record in script logconst IMPLICIT_TIMEOUT = 3000 // default implicit timeout is 10 seconds // 4 seconds x 14 findElement operations = 42 seconds // assuming all operations time outconst PAGE_LOAD_TIMEOUT = 60000 // default page load timeout is 60 seconds // fail early to prevent long duration timeoutsconst SCRIPT_TIMEOUT = 20000 // default script timeout is 30 secondsconst USER_AGENT = "default" // set the user agent for Chromeconst PROTOCOL = "https://" // set the protocolconst USERNAME = "" // username:const PASSWORD = "" // password@const DOMAIN = "newrelic.com" // your domainconst PATH = "" // path to main pageconst CHECK = "Why New Relic?" // text to match on pageconst AUTH = USERNAME + PASSWORDconst MAIN_URL = PROTOCOL + AUTH + DOMAIN + PATH
// -------------------- DEPENDENCIESvar assert = require("assert")
// -------------------- CONFIGURATIONawait $webDriver.manage().setTimeouts({ implicit: IMPLICIT_TIMEOUT, // sets element load timeout pageLoad: PAGE_LOAD_TIMEOUT, // sets page load timeout script: SCRIPT_TIMEOUT // sets script timeout})
// -------------------- VARIABLESvar By = $selenium.Byvar loc = { main: By.id("main-content"), nav: By.className("js-header-site-nav"), why: By.xpath("/html/body/div[2]/main/article/div[7]/div[1]/div[2]/div[1]/div/div/div/h2"), platform: By.css("#header-main > nav > ul > li:nth-child(1)"), p: [ { service: 'apm', selector: By.xpath("//*[@id='header-main']/nav/ul/li[1]/div/div/div/div/div[2]/div/ul/li[1]/a/div") }, { service: 'k8s', selector: By.xpath("//*[@id='header-main']/nav/ul/li[1]/div/div/div/div/div[2]/div/ul/li[2]/a/div") }, { service: 'infra', selector: By.xpath("//*[@id='header-main']/nav/ul/li[1]/div/div/div/div/div[3]/div/ul/li[1]/a/small") }, { service: 'logs', selector: By.xpath("//*[@id='header-main']/nav/ul/li[1]/div/div/div/div/div[3]/div/ul/li[2]/a/div") }, { service: 'network', selector: By.xpath("//*[@id='header-main']/nav/ul/li[1]/div/div/div/div/div[4]/div/ul/li[1]/a/small") }, { service: 'browser', selector: By.xpath("//*[@id='header-main']/nav/ul/li[1]/div/div/div/div/div[4]/div/ul/li[2]/a/small") } ]}
// -------------------- FUNCTIONS// for backwards compatibility with legacy runtimesasync function waitForAndFindElement(locator, timeout) { const element = await $webDriver.wait( $selenium.until.elementLocated(locator), timeout, "Timed-out waiting for element to be located using: " + locator ) await $webDriver.wait( $selenium.until.elementIsVisible(element), timeout, "Timed-out waiting for element to be visible using ${element}" ) return await $webDriver.findElement(locator)}
// -------------------- START OF SCRIPTconsole.log("Starting synthetics script: " + SCRIPT_NAME)
// confirm timeouts are setconst {implicit, pageLoad, script} = await $webDriver.manage().getTimeouts()console.log("Timeouts are set to:")console.log(" IMPLICIT: " + implicit / 1000 + "s")console.log(" PAGE LOAD: " + pageLoad / 1000 + "s")console.log(" SCRIPT: " + script / 1000 + "s")
// Setting User Agent is not then-able, so we do this first (if defined and not default)if (USER_AGENT && 0 !== USER_AGENT.trim().length && USER_AGENT != "default") { $headers.add("User-Agent", USER_AGENT) console.log("Setting User-Agent to " + USER_AGENT)}
// if an error happens at any step, script execution is halted and a failed result is returnedconsole.log("1. GET main page")console.log("URI: " + MAIN_URL)await $webDriver.get(MAIN_URL)
console.log("2. waitForAndFindElement: " + loc.main)await waitForAndFindElement(loc.main, IMPLICIT_TIMEOUT)
console.log("3. waitForAndFindElement: " + loc.nav)await waitForAndFindElement(loc.nav, IMPLICIT_TIMEOUT)
console.log("4. waitForAndFindElement: " + loc.why)const textBlock = await waitForAndFindElement(loc.why, IMPLICIT_TIMEOUT)
console.log("5. getText: " + CHECK)const text = await textBlock.getText()
console.log("6. assert.equal: " + text)assert.equal(text, CHECK, "validation text not found")
console.log("7. waitForAndFindElement: " + loc.platform)const platformMenu = await waitForAndFindElement(loc.platform, IMPLICIT_TIMEOUT)
console.log("8. hover over Platform menu")await $webDriver.actions().move(platformMenu).perform()
console.log("9. take screenshot")await $webDriver.takeScreenshot()
console.log("10. verify platform services")loc.p.forEach(async function (nr, i) { let n = i + 1 try{ // verify each asset has loaded console.log(" " + n + ". " + nr.service) await $webDriver.findElement(nr.selector) }catch(exception){ console.error("Failure in Step 10." + n) throw exception }})