synthetic-monitoring

安装量: 114
排名: #7495

安装

npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill synthetic-monitoring

Synthetic Monitoring Overview

Set up synthetic monitoring to automatically simulate real user journeys, API workflows, and critical business transactions to detect issues and validate performance.

When to Use End-to-end workflow validation API flow testing User journey simulation Transaction monitoring Critical path validation Instructions 1. Synthetic Tests with Playwright // synthetic-tests.js const { chromium } = require('playwright');

class SyntheticMonitor { constructor(config = {}) { this.baseUrl = config.baseUrl || 'https://app.example.com'; this.timeout = config.timeout || 30000; }

async testUserFlow() { const browser = await chromium.launch(); const page = await browser.newPage(); const metrics = { steps: {} }; const startTime = Date.now();

try {
  // Step 1: Navigate to login
  let stepStart = Date.now();
  await page.goto(`${this.baseUrl}/login`, { waitUntil: 'networkidle' });
  metrics.steps.navigation = Date.now() - stepStart;

  // Step 2: Perform login
  stepStart = Date.now();
  await page.fill('input[name="email"]', 'test@example.com');
  await page.fill('input[name="password"]', 'password123');
  await page.click('button[type="submit"]');
  await page.waitForNavigation({ waitUntil: 'networkidle' });
  metrics.steps.login = Date.now() - stepStart;

  // Step 3: Navigate to dashboard
  stepStart = Date.now();
  await page.goto(`${this.baseUrl}/dashboard`, { waitUntil: 'networkidle' });
  metrics.steps.dashboard = Date.now() - stepStart;

  // Step 4: Search for products
  stepStart = Date.now();
  await page.fill('input[placeholder="Search products"]', 'laptop');
  await page.waitForSelector('.product-list');
  metrics.steps.search = Date.now() - stepStart;

  // Step 5: Add to cart
  stepStart = Date.now();
  const firstProduct = await page.$('.product-item');
  if (firstProduct) {
    await firstProduct.click();
    await page.click('button:has-text("Add to Cart")');
    await page.waitForSelector('[data-testid="cart-count"]');
  }
  metrics.steps.addToCart = Date.now() - stepStart;

  metrics.totalTime = Date.now() - startTime;
  metrics.status = 'success';
} catch (error) {
  metrics.status = 'failed';
  metrics.error = error.message;
  metrics.totalTime = Date.now() - startTime;
} finally {
  await browser.close();
}

return metrics;

}

async testMobileUserFlow() { const browser = await chromium.launch(); const context = await browser.createBrowserContext({ ...chromium.devices['iPhone 12'] }); const page = await context.newPage();

try {
  const metrics = { device: 'iPhone 12', steps: {} };
  const startTime = Date.now();

  let stepStart = Date.now();
  await page.goto(this.baseUrl, { waitUntil: 'networkidle' });
  metrics.steps.navigation = Date.now() - stepStart;

  const viewport = page.viewportSize();
  metrics.viewport = viewport;

  stepStart = Date.now();
  await page.click('.menu-toggle');
  await page.waitForSelector('.mobile-menu.open');
  metrics.steps.mobileInteraction = Date.now() - stepStart;

  metrics.totalTime = Date.now() - startTime;
  metrics.status = 'success';

  return metrics;
} catch (error) {
  return { status: 'failed', error: error.message, device: 'iPhone 12' };
} finally {
  await browser.close();
}

}

async testWithPerformanceMetrics() { const browser = await chromium.launch(); const page = await browser.newPage();

try {
  await page.goto(this.baseUrl, { waitUntil: 'networkidle' });

  const perfMetrics = JSON.parse(
    await page.evaluate(() => JSON.stringify(window.performance.timing))
  );

  const metrics = {
    navigationTiming: {
      domInteractive: perfMetrics.domInteractive - perfMetrics.navigationStart,
      domComplete: perfMetrics.domComplete - perfMetrics.navigationStart,
      loadComplete: perfMetrics.loadEventEnd - perfMetrics.navigationStart
    },
    status: 'success'
  };

  return metrics;
} catch (error) {
  return { status: 'failed', error: error.message };
} finally {
  await browser.close();
}

}

async recordMetrics(testName, metrics) { try { await axios.post('http://monitoring-service/synthetic-results', { testName, timestamp: new Date(), metrics, passed: metrics.status === 'success' }); } catch (error) { console.error('Failed to record metrics:', error); } } }

module.exports = SyntheticMonitor;

  1. API Synthetic Tests // api-synthetic-tests.js const axios = require('axios');

class APISyntheticTests { constructor(config = {}) { this.baseUrl = config.baseUrl || 'https://api.example.com'; this.client = axios.create({ baseURL: this.baseUrl }); }

async testAuthenticationFlow() { const results = { steps: {}, status: 'success' };

try {
  const registerStart = Date.now();
  const registerRes = await this.client.post('/auth/register', {
    email: `test-${Date.now()}@example.com`,
    password: 'Test@123456'
  });
  results.steps.register = Date.now() - registerStart;

  if (registerRes.status !== 201) throw new Error('Registration failed');

  const loginStart = Date.now();
  const loginRes = await this.client.post('/auth/login', {
    email: registerRes.data.email,
    password: 'Test@123456'
  });
  results.steps.login = Date.now() - loginStart;

  const token = loginRes.data.token;

  const authStart = Date.now();
  await this.client.get('/api/profile', {
    headers: { Authorization: `Bearer ${token}` }
  });
  results.steps.authenticatedRequest = Date.now() - authStart;

  const logoutStart = Date.now();
  await this.client.post('/auth/logout', {}, {
    headers: { Authorization: `Bearer ${token}` }
  });
  results.steps.logout = Date.now() - logoutStart;

  return results;
} catch (error) {
  results.status = 'failed';
  results.error = error.message;
  return results;
}

}

async testTransactionFlow() { const results = { steps: {}, status: 'success' };

try {
  const orderStart = Date.now();
  const orderRes = await this.client.post('/api/orders', {
    items: [{ sku: 'ITEM-001', quantity: 2 }]
  }, {
    headers: { 'X-Idempotency-Key': `order-${Date.now()}` }
  });
  results.steps.createOrder = Date.now() - orderStart;

  const getStart = Date.now();
  const getRes = await this.client.get(`/api/orders/${orderRes.data.id}`);
  results.steps.getOrder = Date.now() - getStart;

  const paymentStart = Date.now();
  await this.client.post(`/api/orders/${orderRes.data.id}/payment`, {
    method: 'credit_card',
    amount: getRes.data.total
  });
  results.steps.processPayment = Date.now() - paymentStart;

  return results;
} catch (error) {
  results.status = 'failed';
  results.error = error.message;
  return results;
}

}

async testUnderLoad(concurrentUsers = 10, duration = 60000) { const startTime = Date.now(); const results = { totalRequests: 0, successfulRequests: 0, failedRequests: 0, averageResponseTime: 0, p95ResponseTime: 0 };

const responseTimes = [];

const makeRequest = async () => {
  const reqStart = Date.now();
  try {
    await this.client.get('/api/health');
    results.successfulRequests++;
    responseTimes.push(Date.now() - reqStart);
  } catch {
    results.failedRequests++;
  }
  results.totalRequests++;
};

const userSimulations = Array(concurrentUsers).fill(null).map(async () => {
  while (Date.now() - startTime < duration) {
    await makeRequest();
    await new Promise(r => setTimeout(r, Math.random() * 1000));
  }
});

await Promise.all(userSimulations);

responseTimes.sort((a, b) => a - b);
results.averageResponseTime =
  responseTimes.reduce((a, b) => a + b, 0) / responseTimes.length;
results.p95ResponseTime =
  responseTimes[Math.floor(responseTimes.length * 0.95)];

return results;

} }

module.exports = APISyntheticTests;

  1. Scheduled Synthetic Monitoring // scheduled-monitor.js const cron = require('node-cron'); const SyntheticMonitor = require('./synthetic-tests'); const APISyntheticTests = require('./api-synthetic-tests'); const axios = require('axios');

class ScheduledSyntheticMonitor { constructor(config = {}) { this.eMonitor = new SyntheticMonitor(config); this.apiTests = new APISyntheticTests(config); this.alertThreshold = config.alertThreshold || 5000; }

start() { cron.schedule('/5 * * * ', () => this.runE2ETests()); cron.schedule('/2 * * * ', () => this.runAPITests()); cron.schedule('0 * * * *', () => this.runLoadTest()); }

async runE2ETests() { try { const metrics = await this.eMonitor.testUserFlow(); await this.recordResults('e2e-user-flow', metrics);

  if (metrics.totalTime > this.alertThreshold) {
    await this.sendAlert('e2e-user-flow', metrics);
  }
} catch (error) {
  console.error('E2E test failed:', error);
}

}

async runAPITests() { try { const authMetrics = await this.apiTests.testAuthenticationFlow(); const transactionMetrics = await this.apiTests.testTransactionFlow();

  await this.recordResults('api-auth-flow', authMetrics);
  await this.recordResults('api-transaction-flow', transactionMetrics);

  if (authMetrics.status === 'failed' || transactionMetrics.status === 'failed') {
    await this.sendAlert('api-tests', { authMetrics, transactionMetrics });
  }
} catch (error) {
  console.error('API test failed:', error);
}

}

async runLoadTest() { try { const results = await this.apiTests.testUnderLoad(10, 30000); await this.recordResults('load-test', results);

  if (results.failedRequests > 0) {
    await this.sendAlert('load-test', results);
  }
} catch (error) {
  console.error('Load test failed:', error);
}

}

async recordResults(testName, metrics) { try { await axios.post('http://monitoring-service/synthetic-results', { testName, timestamp: new Date(), metrics }); console.log(Recorded: ${testName}, metrics); } catch (error) { console.error('Failed to record results:', error); } }

async sendAlert(testName, metrics) { try { await axios.post('http://alerting-service/alerts', { type: 'synthetic_monitoring', testName, severity: 'warning', message: Synthetic test '${testName}' has issues, metrics, timestamp: new Date() }); console.log(Alert sent for ${testName}); } catch (error) { console.error('Failed to send alert:', error); } } }

module.exports = ScheduledSyntheticMonitor;

Best Practices ✅ DO Test critical user journeys Simulate real browser conditions Monitor from multiple locations Track response times Alert on test failures Rotate test data Test mobile and desktop Include error scenarios ❌ DON'T Test with production data Reuse test accounts Skip timeout configurations Ignore test maintenance Test too frequently Hard-code credentials Ignore geographic variations Test only happy paths Key Metrics Response time Success rate Availability Core Web Vitals Error rate

返回排行榜