test-observability
PlaywrightテストとOpenTelemetryなどのツールを連携させ、分散システムにおけるテストの失敗原因特定、性能測定、ダッシュボード作成、バックエンドの追跡を可能にするSkill。
📜 元の英語説明(参考)
Integrate Playwright tests with OpenTelemetry, Grafana, Prometheus, Loki, and Tempo. Use when debugging test failures across distributed systems, measuring test performance, creating test dashboards, or correlating tests with backend traces.
🇯🇵 日本人クリエイター向け解説
PlaywrightテストとOpenTelemetryなどのツールを連携させ、分散システムにおけるテストの失敗原因特定、性能測定、ダッシュボード作成、バックエンドの追跡を可能にするSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o test-observability.zip https://jpskill.com/download/9519.zip && unzip -o test-observability.zip && rm test-observability.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/9519.zip -OutFile "$d\test-observability.zip"; Expand-Archive "$d\test-observability.zip" -DestinationPath $d -Force; ri "$d\test-observability.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
test-observability.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
test-observabilityフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
テストの可観測性
概要
Playwright テストを可観測性スタック (Grafana、Prometheus、Loki、Tempo) に接続して、以下を実現します。
- トレース相関: ブラウザのクリック → バックエンド → データベースまでの完全なトレースを確認
- テストメトリクス: 合格率、実行時間、不安定さを示すダッシュボード
- ログ集約: アプリケーションログと並行してテストログを表示
- 障害分析: 分散システム全体にわたる根本原因を迅速に特定
アーキテクチャ
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Playwright │────▶│ OTEL Collector │────▶│ Tempo (Traces) │
│ Tests │ │ │────▶│ Loki (Logs) │
│ │ │ │────▶│ Prometheus │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ Grafana │
│ Test Dashboard │
└─────────────────┘
クイックスタート: OTEL Reporter
1. 依存関係のインストール
npm install playwright-opentelemetry-reporter @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-http
2. Reporter の設定
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [
['html'],
['playwright-opentelemetry-reporter', {
serviceName: 'playwright-tests',
endpoint: process.env.OTEL_ENDPOINT || 'http://localhost:4318/v1/traces',
}],
],
});
3. テストの実行
# ローカルの OTEL collector を使用する場合
OTEL_ENDPOINT=http://localhost:4318/v1/traces npx playwright test
# Railway の OTEL collector を使用する場合
OTEL_ENDPOINT=http://otel-collector.railway.internal:4318/v1/traces npx playwright test
4. Grafana での表示
- Grafana → Explore → Tempo を開きます
service.name = "playwright-tests"を検索します- 実行時間、ステータス、ステップを含むテストスパンを確認します
Tracetest 統合 (高度)
Tracetest は トレースベースのテスト を可能にします。分散トレース内の任意のスパンに対してアサートできます。
インストール
npm install @tracetest/playwright
設定
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [
['html'],
['@tracetest/playwright', {
serverUrl: process.env.TRACETEST_URL || 'http://localhost:11633',
apiKey: process.env.TRACETEST_API_KEY,
}],
],
});
トレースベースのアサーション
// tests/checkout.spec.ts
import { test, expect } from '@playwright/test';
import { Tracetest } from '@tracetest/playwright';
test('checkout creates order', async ({ page }) => {
const tracetest = new Tracetest();
// トレースキャプチャを開始
await tracetest.capture();
// ユーザーアクションの実行
await page.goto('/checkout');
await page.click('#place-order');
await expect(page.locator('.order-confirmation')).toBeVisible();
// バックエンドトレースに対してアサート!
await tracetest.assertOnTrace({
assertions: [
// API 応答時間
{
selector: 'span[name="POST /api/orders"]',
assertion: 'attr:http.status_code = 201',
},
// データベースクエリ時間
{
selector: 'span[name="INSERT orders"]',
assertion: 'attr:db.duration < 100ms',
},
// 支払いサービス
{
selector: 'span[name="payment.process"]',
assertion: 'attr:payment.status = "success"',
},
],
});
});
利点
- 80% 高速なデバッグ: 障害が発生した場所を正確に確認
- 完全な可視性: ブラウザ → API → データベース → サービス
- バックエンドアサーション: データベースクエリ、サービス呼び出しをテスト
- パフォーマンス検証: スパンの実行時間に対してアサート
Grafana ダッシュボード
ダッシュボードのインポート
- Grafana → Dashboards → Import を開きます
dashboards/test-results-dashboard.jsonをアップロードします- Prometheus および Tempo データソースを選択します
主要なパネル
| パネル | クエリ | 目的 |
|---|---|---|
| 合格率 | sum(playwright_test_passed) / sum(playwright_test_total) |
全体的な健全性 |
| テスト実行時間 (p95) | histogram_quantile(0.95, playwright_test_duration_bucket) |
パフォーマンス |
| 失敗したテスト | playwright_test_failed{status="failed"} |
迅速なトリアージ |
| 不安定なテスト | playwright_test_retries > 1 |
不安定性の特定 |
| 最も遅いテスト | topk(10, playwright_test_duration) |
最適化のターゲット |
カスタムメトリクス
// テストからカスタムメトリクスをエクスポート
import { test } from '@playwright/test';
import { metrics } from '@opentelemetry/api';
const testMeter = metrics.getMeter('playwright-tests');
const testDuration = testMeter.createHistogram('test.duration');
const testCounter = testMeter.createCounter('test.count');
test('custom metrics', async ({ page }) => {
const start = Date.now();
await page.goto('/');
await page.click('.action');
// カスタムメトリクスの記録
testDuration.record(Date.now() - start, {
test: 'homepage-action',
browser: 'chromium',
});
testCounter.add(1, { status: 'passed' });
});
Railway 統合
既存の Railway 可観測性スタックに接続します。
環境変数
# Railway サービスまたは .env で設定
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector.railway.internal:4318
OTEL_SERVICE_NAME=playwright-tests
Playwright 設定
// playwright.config.ts
export default defineConfig({
reporter: [
['playwright-opentelemetry-reporter', {
serviceName: process.env.OTEL_SERVICE_NAME || 'playwright-tests',
endpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
headers: {
// 必要に応じて認証を追加
'Authorization': `Bearer ${process.env.OTEL_AUTH_TOKEN}`,
},
}],
],
});
接続の確認
# OTEL collec をテスト 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Test Observability
Overview
Connect your Playwright tests to your observability stack (Grafana, Prometheus, Loki, Tempo) for:
- Trace Correlation: See full trace from browser click → backend → database
- Test Metrics: Dashboard with pass rates, durations, flakiness
- Log Aggregation: Test logs alongside application logs
- Failure Analysis: Quickly identify root cause across distributed systems
Architecture
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Playwright │────▶│ OTEL Collector │────▶│ Tempo (Traces) │
│ Tests │ │ │────▶│ Loki (Logs) │
│ │ │ │────▶│ Prometheus │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ Grafana │
│ Test Dashboard │
└─────────────────┘
Quick Start: OTEL Reporter
1. Install Dependencies
npm install playwright-opentelemetry-reporter @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-http
2. Configure Reporter
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [
['html'],
['playwright-opentelemetry-reporter', {
serviceName: 'playwright-tests',
endpoint: process.env.OTEL_ENDPOINT || 'http://localhost:4318/v1/traces',
}],
],
});
3. Run Tests
# With local OTEL collector
OTEL_ENDPOINT=http://localhost:4318/v1/traces npx playwright test
# With Railway OTEL collector
OTEL_ENDPOINT=http://otel-collector.railway.internal:4318/v1/traces npx playwright test
4. View in Grafana
- Open Grafana → Explore → Tempo
- Search for
service.name = "playwright-tests" - See test spans with duration, status, steps
Tracetest Integration (Advanced)
Tracetest enables trace-based testing - assert on any span in the distributed trace.
Installation
npm install @tracetest/playwright
Configuration
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [
['html'],
['@tracetest/playwright', {
serverUrl: process.env.TRACETEST_URL || 'http://localhost:11633',
apiKey: process.env.TRACETEST_API_KEY,
}],
],
});
Trace-Based Assertions
// tests/checkout.spec.ts
import { test, expect } from '@playwright/test';
import { Tracetest } from '@tracetest/playwright';
test('checkout creates order', async ({ page }) => {
const tracetest = new Tracetest();
// Start trace capture
await tracetest.capture();
// Perform user action
await page.goto('/checkout');
await page.click('#place-order');
await expect(page.locator('.order-confirmation')).toBeVisible();
// Assert on backend trace!
await tracetest.assertOnTrace({
assertions: [
// API response time
{
selector: 'span[name="POST /api/orders"]',
assertion: 'attr:http.status_code = 201',
},
// Database query time
{
selector: 'span[name="INSERT orders"]',
assertion: 'attr:db.duration < 100ms',
},
// Payment service
{
selector: 'span[name="payment.process"]',
assertion: 'attr:payment.status = "success"',
},
],
});
});
Benefits
- 80% faster debugging: See exactly where failures occur
- Full visibility: Browser → API → Database → Services
- Backend assertions: Test database queries, service calls
- Performance validation: Assert on span durations
Grafana Dashboard
Import Dashboard
- Open Grafana → Dashboards → Import
- Upload
dashboards/test-results-dashboard.json - Select Prometheus and Tempo data sources
Key Panels
| Panel | Query | Purpose |
|---|---|---|
| Pass Rate | sum(playwright_test_passed) / sum(playwright_test_total) |
Overall health |
| Test Duration (p95) | histogram_quantile(0.95, playwright_test_duration_bucket) |
Performance |
| Failed Tests | playwright_test_failed{status="failed"} |
Quick triage |
| Flaky Tests | playwright_test_retries > 1 |
Identify flakiness |
| Slowest Tests | topk(10, playwright_test_duration) |
Optimization targets |
Custom Metrics
// Export custom metrics from tests
import { test } from '@playwright/test';
import { metrics } from '@opentelemetry/api';
const testMeter = metrics.getMeter('playwright-tests');
const testDuration = testMeter.createHistogram('test.duration');
const testCounter = testMeter.createCounter('test.count');
test('custom metrics', async ({ page }) => {
const start = Date.now();
await page.goto('/');
await page.click('.action');
// Record custom metric
testDuration.record(Date.now() - start, {
test: 'homepage-action',
browser: 'chromium',
});
testCounter.add(1, { status: 'passed' });
});
Railway Integration
Connect to your existing Railway observability stack.
Environment Variables
# Set in Railway service or .env
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector.railway.internal:4318
OTEL_SERVICE_NAME=playwright-tests
Playwright Config
// playwright.config.ts
export default defineConfig({
reporter: [
['playwright-opentelemetry-reporter', {
serviceName: process.env.OTEL_SERVICE_NAME || 'playwright-tests',
endpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
headers: {
// Add auth if needed
'Authorization': `Bearer ${process.env.OTEL_AUTH_TOKEN}`,
},
}],
],
});
Verify Connection
# Test OTEL collector is receiving data
curl -X POST http://otel-collector.railway.internal:4318/v1/traces \
-H "Content-Type: application/json" \
-d '{"resourceSpans":[]}'
# Should return 200 OK
Log Correlation
Send test logs to Loki alongside traces.
Winston + OTEL
// tests/fixtures/logger.ts
import winston from 'winston';
import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
export const logger = winston.createLogger({
transports: [
new winston.transports.Console(),
// Send to OTEL collector → Loki
new OTLPLogTransport({
endpoint: process.env.OTEL_ENDPOINT,
}),
],
});
// In tests
import { logger } from './fixtures/logger';
test('with logging', async ({ page }) => {
logger.info('Starting test', { test: 'checkout' });
await page.goto('/checkout');
logger.debug('Page loaded', { url: page.url() });
await page.click('#submit');
logger.info('Order submitted');
});
View Logs in Grafana
1. Grafana → Explore → Loki
2. Query: {service="playwright-tests"}
3. Filter: |= "error" or |json | level="error"
Alerting
Set up alerts for test failures.
Prometheus Alert Rules
# alerts/test-alerts.yml
groups:
- name: playwright-tests
rules:
- alert: TestFailureRate
expr: |
(sum(rate(playwright_test_failed[5m])) / sum(rate(playwright_test_total[5m]))) > 0.1
for: 5m
labels:
severity: warning
annotations:
summary: "High test failure rate (>10%)"
- alert: TestDurationSpike
expr: |
histogram_quantile(0.95, playwright_test_duration_bucket) > 30
for: 5m
labels:
severity: warning
annotations:
summary: "Test duration p95 > 30 seconds"
Grafana Alert
- Edit dashboard panel
- Alert tab → Create alert
- Condition:
avg() of A is above 0.1 - Notifications: Slack, email, PagerDuty
Workflow: Debugging with Traces
1. Test Fails in CI
❌ tests/checkout.spec.ts:15 - Order creation failed
Expected: Order confirmation visible
Actual: Error page shown
2. Find Trace in Grafana
Grafana → Explore → Tempo
Query: service.name="playwright-tests" AND name="checkout.spec.ts"
3. Analyze Trace
Browser click "Place Order" (50ms)
└─ POST /api/orders (200ms)
└─ Validate cart (10ms)
└─ Process payment ❌ (timeout after 30s)
└─ Payment gateway unreachable
└─ Create order (skipped)
4. Root Cause
Found: Payment gateway timeout caused order failure.
Without traces: Would have debugged browser-side for hours.
Best Practices
1. Add Trace Context to Tests
import { context, trace } from '@opentelemetry/api';
test('with trace context', async ({ page }) => {
const tracer = trace.getTracer('playwright');
await tracer.startActiveSpan('checkout-flow', async (span) => {
span.setAttribute('test.name', 'checkout');
span.setAttribute('test.browser', 'chromium');
await page.goto('/checkout');
await page.click('#submit');
span.setStatus({ code: 1 }); // OK
span.end();
});
});
2. Propagate Context to Backend
// Ensure trace ID passes from browser to backend
test('trace propagation', async ({ page }) => {
// Get current trace ID
const traceId = trace.getActiveSpan()?.spanContext().traceId;
// Add to request headers
await page.route('**/*', route => {
route.continue({
headers: {
...route.request().headers(),
'traceparent': `00-${traceId}-${spanId}-01`,
},
});
});
});
3. Tag Tests for Filtering
test('with tags', async ({ page }) => {
const span = trace.getActiveSpan();
span?.setAttribute('test.suite', 'e2e');
span?.setAttribute('test.priority', 'critical');
span?.setAttribute('test.feature', 'checkout');
// Now filter in Grafana: test.feature="checkout"
});
References
references/tracetest-integration.md- Full Tracetest setupreferences/otel-reporter-setup.md- OTEL reporter configurationreferences/grafana-dashboards.md- Dashboard creation guidedashboards/test-results-dashboard.json- Ready-to-import dashboard
Test observability transforms debugging from guesswork to precision - see the full picture from click to database.