
従来、ソフトウェア開発とSREは、文化的な視点や優先度が異なるサイロで仕事をしてきました。DevOpsの目標は、ソフトウェア開発と運用に共通する補完的な手順を確立することです。しかし、組織によっては本当の意味でのコラボレーションがほとんど見られず、効果的なDevOpsパートナーシップを構築するには至っていません。
文化的な問題の他に、このような断絶が生じる最も一般的な理由の1つは、同様の目標を達成するために異なるツールを使用していることにあります。たとえば、エンドツーエンド(e2e)テストとシンセティック監視という2つのツールが存在しています。
このブログでは、このような手法の概要について紹介します。さらに、サンプルリポジトリcarlyrichmond/synthetics-replicatorを使用して、Playwright、@elastic/synthetics、GitHub ActionsがどのようにElastic Syntheticsやそのレコーダーと連携して、開発チームとSREチームを一体化させ、Netlifyのようなプロバイダーでホストされる単純なWebアプリケーションのユーザーエクスペリエンスを検証および監視できるのかについても説明します。
最近、Elasticで導入されたシンセティック監視は、以前のブログでも紹介したように、e2eテストを完全に置き換えることができます。1つのツールに集約し、ユーザーワークフローを早期に検証することで、ユーザーの問題を再現し、修正内容を検証するための共通言語が得られます。
シンセティック監視とe2eテスト
開発ツールと運用ツールが戦争状態にあると、それぞれの異なる文化を統一することが困難です。これらのアプローチの定義を検討すると、実は同じ目的を達成するためのものであることがわかります。
e2eテストは、クリック、ユーザーテキスト入力、ナビゲーションを含むユーザーパスを再現する一連のテストです。これはソフトウェアアプリケーションのレイヤーの統合をテストするものだという意見も多いのですが、e2eテストでエミュレートされるのはユーザーワークフローです。一方、シンセティック監視(特に、ブラウザー監視と呼ばれる部分)は、アプリケーションを通過するユーザーパスをエミュレートするアプリケーションパフォーマンス監視の手法です。
どちらの手法も、ユーザーパスをエミュレートします。開発者と運用者の垣根を越えたツールを使用し、連携して取り組むことで、Webアプリケーションの運用監視も可能なテストを構築できます。
ユーザージャーニーを作成する
アプリケーションで新しいユーザーワークフロー、つまり重要な目標を達成する一連の機能を開発しているときには、開発者は@elastic/synthetics を使用してユーザージャーニーを作成できます。以下の例のように、インストール後にinit ユーティリティを使用して、初期プロジェクトの足場を作成することができます。なお、このユーティリティを使用する前には、Node.jsをインストールしておく必要があります。
npm install -g @elastic/synthetics
npx @elastic/synthetics init synthetics-replicator-tests
ウィザードを開始する前に、Elasticクラスター情報とElastic Synthetics統合がクラスターで設定されていることを確認してください。必要な条件:
- ドキュメントに記載されている開始手順の前提条件に従って、Elastic Syntheticsアプリ内でMonitor Managementを有効にする必要があります。
- Elastic CloudクラスターのクラウドID(Elastic Cloudを使用している場合)。また、オンプレミスのホスティングを使用している場合は、Kibanaエンドポイントを入力する必要があります。
- クラスターから生成されたAPIキー。Syntheticsアプリケーションの[Settings]にあるショートカットを使用すると、[Project API Keys]タブの下にこのキーが生成されます。こちらのドキュメントを参照してください。
このウィザードに従うと、次に示す構造に似た、構成とサンプル監視ジャーニーを含むサンプルプロジェクトが生成されます。

Web開発者にとっては、READMEやpackage.json、ロックファイルのように、馴染みの深い要素が多いと思います。以下のように、モニターの主な構成はsynthetics.config.tsで確認できます。この構成を修正することで、運用や開発に固有の構成を追加することができます。この作業は、能力を結合して、同じモニターをe2eテストに再利用し、任意のジャーニーをe2eテストと本番モニターとして使用できるようにするために不可欠です。この例では示されていませんが、Elasticのインフラからではなく、独自の専用Elasticインスタンスから監視したい場合は、非公開の場所の詳細情報を追加することができます。
import type { SyntheticsConfig } from '@elastic/synthetics';
export default env => {
const config: SyntheticsConfig = {
params: {
url: 'http://localhost:5173',
},
playwrightOptions: {
ignoreHTTPSErrors: false,
},
/**
* Configure global monitor settings
*/
monitor: {
schedule: 10,
locations: ['united_kingdom'],
privateLocations: [],
},
/**
* Project monitors settings
*/
project: {
id: 'synthetics-replicator-tests',
url: 'https://elastic-deployment:port',
space: 'default',
},
};
if (env === 'production') {
config.params = { url: 'https://synthetics-replicator.netlify.app/' }
}
return config;
};
最初のジャーニーを作成する
上記の構成はプロジェクト内のすべてのモニターに適用されますが、特定のテストのために上書きすることができます。
import { journey, step, monitor, expect, before } from '@elastic/synthetics';
journey('Replicator Order Journey', ({ page, params }) => {
// Only relevant for the push command to create
// monitors in Kibana
monitor.use({
id: 'synthetics-replicator-monitor',
schedule: 10,
});
// journey steps go here
});
@elastic/syntheticsラッパーでは、テスト内で一般的なプロパティを設定および破棄するためのbeforeコンストラクタやafterコンストラクタなど、多数の標準テストメソッドが公開されています。また、多数の共通アサーションヘルパーメソッドもサポートされます。サポートが想定されるすべてのメソッドについては、こちらのドキュメントを参照してください。また、Playwright pageオブジェクトも公開されます。このオブジェクトは、APIで提供される想定されたアクティビティ(ページ要素の検索、以降の例で示されているクリックなどのユーザーイベントのシミュレーションなど)をすべて実行できます。
import { journey, step, monitor, expect, before } from '@elastic/synthetics';
journey('Replicator Order Journey', ({ page, params }) => {
// monitor configuration goes here
before(async ()=> {
await page.goto(params.url);
});
step('assert home page loads', async () => {
const header = await page.locator('h1');
expect(await header.textContent()).toBe('Replicatr');
});
step('assert move to order page', async () => {
const orderButton = await page.locator('data-testid=order-button');
await orderButton.click();
const url = page.url();
expect(url).toContain('/order');
const menuTiles = await page.locator('data-testid=menu-item-card');
expect(await menuTiles.count()).toBeGreaterThan(2);
});
// other steps go here
});
上記の例からわかるように、journeyおよびstepコンストラクタも公開されています。このコンストラクタは、テストでアプリケーションを通過するユーザージャーニーを示すという振る舞い駆動開発(BDD)の実践を反映しています。
開発者は、機能開発の一環として、ローカルで実行されるアプリケーションに対してテストを実行し、ユーザーワークフローにおける成功や失敗のステップを確認することができます。下の例では、上部のローカルサーバーの起動コマンドが青色で囲まれています。モニター実行コマンドは、さらに下の赤色で示されています。

各ジャーニーのステップの横にある緑のチェックマークからわかるように、各テストで合格しています。
CIパイプラインのゲート制御
CIパイプラインでモニターの実行をゲートとして使用し、コードの変更をマージし、新しいバージョンのモニターをアップロードすることが重要です。GitHub Actionsワークフローの各ジョブについては、このセクションと次のセクションで説明します。
下図のように、テストジョブはテストインスタンスを起動し、ユーザージャーニーを実行して、変更を検証します。このステップは、開発者の変更を検証するためのプルリクエストとプッシュの両方で実行する必要があります。
jobs:
test:
env:
NODE_ENV: development
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm install
- run: npm start &
- run: "npm install @elastic/synthetics && SYNTHETICS_JUNIT_FILE='junit-synthetics.xml' npx @elastic/synthetics . --reporter=junit"
working-directory: ./apps/synthetics-replicator-tests/journeys
- name: Publish Unit Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
junit_files: '**/junit-*.xml'
check_name: Elastic Synthetics Tests
ローカルコンピューターでのジャーニー実行とは異なり、npx @elastic/syntheticsを実行するときには、--reporter=junitオプションを使用して、CIジョブへのジャーニーの合格(または、時には残念ながら失敗)を可視化することができます。

モニターを自動的にアップロードする
Elastic Uptimeで確実に最新のモニターを利用できるようにするには、以下のタスク例のように、CIワークフローの一部としてプログラム上でモニターをプッシュすることをお勧めします。このワークフローには、以下に示すように、2番目のジョブのpushがあります。このジョブは、モニターをクラスターにアップロードするtestジョブの実行が成功することが条件となっています。なお、このジョブは、プルリクエストで実行されただけではなく、変更が検証されたことを保証するために、プッシュ時にも実行されるようにワークフローで設定されています。
jobs:
test: …
push:
env:
NODE_ENV: production
SYNTHETICS_API_KEY: ${{ secrets.SYNTHETICS_API_KEY }}
needs: test
defaults:
run:
working-directory: ./apps/synthetics-replicator-tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm install
- run: npm run push
@elastic/synthetics initウィザードでは、プロジェクト作成時にプッシュコマンドを生成し、それをプロジェクトフォルダーからトリガーすることができます。以下のstepsおよびworking_directory構成では、この動作を示します。pushコマンドにはElasticクラスターのAPIキーが必要です。このキーは信頼できる格納域にシークレットとして保存し、ワークフロー環境変数で参照してください。また、本番の監視を壊さないようにするため、更新されたモニター構成をElastic Syntheticsインスタンスにプッシュする前に、モニターが検証で合格することも重要です。 テスト環境に対して行うe2eテストとは異なり、壊れたモニターはSRE活動に影響を与えるため、すべての変更を検証する必要があります。そのため、needsオプションでテストステップに依存関係を適用することをお勧めします。

Elastic Syntheticsを使用して監視する
モニターがアップロードされると、SREチームはモニターから得られる定期的なチェックポイントを利用してユーザーワークフローが意図したとおりに機能しているかどうかを確認できます。これが可能になるのは、前述のようにモニターがプロジェクトや個々のテストに設定された定期的なスケジュールで実行されることに加え、すべてのモニター実行の状態を確認し、オンデマンドでそれを実行できる機能があるからです。
[Monitors Overview]タブには、設定されている全モニターの最新のステータスが表示されます。さらにカードの[...]メニューを使うと、モニターを手動で実行することもできます。

[Monitor]画面では、個々のモニターの実行状況の概要を表示して、問題を調査することもできます。

監視に関連してSREが得られるもう1つの大きなメリットは、APM、メトリック、ログなど、SREがアプリケーションのパフォーマンスや可用性を調査する際に現在使用している馴染みのあるツールにこのモニターを統合できることです。Investigateというふさわしい名前のメニューは、SREが潜在的な障害やボトルネックの調査を行う際に簡単に操作できます。
また、問題を発見することと、潜在的な問題を自動的に通知することとのバランスもあります。問題の通知のルールやしきい値を設定することにはすでに慣れているSREにとっては、ブラウザーモニターでもこの作業ができるのは嬉しいでしょう。ルールの例の編集は次のとおりです。

ブラウザーモニタのステータスは、上記のステータスチェックのように個別のモニターまたはモニターのグループが繰り返しダウンしているかどうかを考慮するよう設定するだけでなく、一定期間のチェック合格率から全体的な可用性を測定するように設定することもできます。SREは、従来の本番管理の方法で問題に対応するだけでなく、アプリケーションの可用性も改善したいと考えています。
ユーザーワークフローを記録する
開発ライフサイクルを通じてe2eテストを生成することの限界は、チームがすべてを逃さずに捉えられるわけではないということです。以前のツールセットは開発チーム向けになっています。部門横断的なチームを使用する直感的な製品を設計するという理想的な意図があっても、ユーザーは想定外の方法でアプリケーションを使うことがあります。さらに、開発者が作成したモニターは、想定されたワークフローをカバーするだけであり、本番で失敗したとき、あるいは異常検知が適用された場合にモニターが異なる動作をし始めたときに、アラームを発行します。
ユーザーの問題が発生したとき、その問題をモニターと同じ形式で再現することは有効です。また、ユーザージャーニーの作成においては、SREの経験を活用することも重要です。SREは、開発者が苦労するかもしれない障害ケースを直感的に考慮し、成功ケースに集中するからです。ただし、すべてのSREがPlaywrightと@elastic/syntheticsを使用して、このようなジャーニーを作成する経験や自信を備えているわけではありません。
Elastic Synthetics Recorderの登場です。上の動画では、ユーザージャーニーのステップを記録し、それをJavaScriptファイルにエクスポートしてモニタープロジェクトに含めるために使用する方法を説明しています。これは、開発フェーズにフィードバックして、問題を解決するために開発された修正をテストするのに有効です。このようなアプローチは、全員が力を合わせてこれらのモニターを使わなければできないことです。
お試しください。
8.8では、@elastic/syntheticsとElastic Syntheticsアプリは一般公開されていますが、信頼レコーダーはベータ版となっています。シンセティック監視を利用して開発者と運用者の垣根を越えた経験がありましたら、コミュニティディスカッションフォーラムのアップタイムカテゴリやSlackで共有してください。
優れた監視を実現しましょう。
2023年2月6日初回発行、2023年5月23日更新。