125 lines
3.8 KiB
Markdown
125 lines
3.8 KiB
Markdown
# ABE — Performance Metrics Specification
|
|
|
|
## Concepto
|
|
Durante la exploración, ABE captura métricas de rendimiento de cada
|
|
estado visitado. Inspirado en Checkly y Datadog RUM.
|
|
Esto permite detectar anomalías de rendimiento además de errores funcionales.
|
|
|
|
## Métricas capturadas por estado
|
|
```typescript
|
|
interface IPerformanceMetrics {
|
|
stateId: string;
|
|
url: string;
|
|
timestamp: number;
|
|
|
|
// Navigation Timing (disponibles via Playwright)
|
|
ttfb: number; // Time to First Byte (ms)
|
|
domContentLoaded: number; // DOMContentLoaded event (ms)
|
|
loadComplete: number; // Load event (ms)
|
|
|
|
// Core Web Vitals (via web-vitals library injected)
|
|
lcp: number | null; // Largest Contentful Paint (ms)
|
|
cls: number | null; // Cumulative Layout Shift (score)
|
|
fid: number | null; // First Input Delay (ms) - solo tras interacción
|
|
inp: number | null; // Interaction to Next Paint (ms)
|
|
|
|
// Resource counts
|
|
totalRequests: number;
|
|
failedRequests: number;
|
|
totalTransferSize: number; // bytes
|
|
}
|
|
```
|
|
|
|
## Implementación
|
|
|
|
### TTFB, DOMContentLoaded, Load
|
|
Via `page.evaluate()` usando `performance.timing` después de navigation:
|
|
```typescript
|
|
const timing = await page.evaluate(() => ({
|
|
ttfb: performance.timing.responseStart - performance.timing.requestStart,
|
|
domContentLoaded: performance.timing.domContentLoadedEventEnd - performance.timing.navigationStart,
|
|
loadComplete: performance.timing.loadEventEnd - performance.timing.navigationStart,
|
|
}));
|
|
```
|
|
|
|
### Core Web Vitals
|
|
Inyectar el script de `web-vitals` (npm) en la página:
|
|
```typescript
|
|
await page.addScriptTag({ url: 'https://unpkg.com/web-vitals/dist/web-vitals.iife.js' });
|
|
const vitals = await page.evaluate(() => new Promise(resolve => {
|
|
const result = {};
|
|
webVitals.getLCP(m => result.lcp = m.value);
|
|
webVitals.getCLS(m => result.cls = m.value);
|
|
webVitals.getINP(m => result.inp = m.value);
|
|
setTimeout(() => resolve(result), 3000); // wait 3s for vitals
|
|
}));
|
|
```
|
|
|
|
## Anomalías de rendimiento (nuevos tipos)
|
|
|
|
Añadir al AnomalyDetector con umbrales basados en Core Web Vitals de Google:
|
|
|
|
| Métrica | Good | Needs Improvement | Poor (anomalía) |
|
|
|---------|---------|-------------------|-----------------|
|
|
| LCP | <2500ms | 2500-4000ms | >4000ms → high |
|
|
| CLS | <0.1 | 0.1-0.25 | >0.25 → medium |
|
|
| INP | <200ms | 200-500ms | >500ms → high |
|
|
| TTFB | <800ms | 800-1800ms | >1800ms → medium|
|
|
|
|
Tipo de anomalía: `performance_degradation`
|
|
|
|
## Modelo de datos — añadir a SQLite
|
|
|
|
### Table: performance_metrics
|
|
```sql
|
|
CREATE TABLE IF NOT EXISTS performance_metrics (
|
|
id TEXT PRIMARY KEY,
|
|
session_id TEXT NOT NULL,
|
|
state_id TEXT NOT NULL,
|
|
url TEXT NOT NULL,
|
|
ttfb INTEGER,
|
|
dom_content_loaded INTEGER,
|
|
load_complete INTEGER,
|
|
lcp INTEGER,
|
|
cls REAL,
|
|
fid INTEGER,
|
|
inp INTEGER,
|
|
total_requests INTEGER,
|
|
failed_requests INTEGER,
|
|
total_transfer_size INTEGER,
|
|
captured_at INTEGER NOT NULL
|
|
);
|
|
```
|
|
|
|
## Frontend — Performance tab
|
|
|
|
Añadir tab "Performance" en SessionDetail:
|
|
- Tabla con todos los estados visitados y sus métricas
|
|
- Columnas con color coded: verde/amarillo/rojo según umbrales de Google
|
|
- Gráfico de barras: LCP por estado (para identificar páginas lentas)
|
|
- Summary cards: peor LCP, peor CLS, peor TTFB de la sesión
|
|
|
|
## En el bug report
|
|
|
|
Si hay anomalía performance_degradation, añadir sección en report.md:
|
|
```
|
|
## Performance Issue
|
|
- LCP: 5200ms (threshold: 4000ms) ❌
|
|
- CLS: 0.08 ✅
|
|
- TTFB: 2100ms (threshold: 1800ms) ❌
|
|
- Total page size: 4.2MB
|
|
```
|
|
|
|
## Configuración
|
|
|
|
Añadir a ExplorationConfig:
|
|
```typescript
|
|
performance: {
|
|
enabled: boolean; // default: true
|
|
lcpThresholdMs: number; // default: 4000
|
|
clsThreshold: number; // default: 0.25
|
|
inpThresholdMs: number; // default: 500
|
|
ttfbThresholdMs: number; // default: 1800
|
|
}
|
|
```
|