Ejemplo 04: Filtrar frames por severidad

← Volver al índice

No todos los frames lentos son iguales

Un frame de 51ms es técnicamente "lento", pero no es tan crítico como uno de 300ms. Necesitamos categorizar los frames por severidad para priorizar qué optimizar.

En este ejemplo aprenderemos a filtrar y categorizar frames usando blockingDuration.

Niveles de severidad

Nivel Blocking Duration Impacto Acción
🔴 Crítico > 200ms Muy malo para INP Optimizar urgentemente
🟡 Alto 100ms - 200ms Problemático Priorizar optimización
🔵 Medio 50ms - 100ms Aceptable, mejorable Revisar si hay tiempo

Demo interactiva

📊 Frames detectados:
🔴 Críticos: 0 | 🟡 Altos: 0 | 🔵 Medios: 0

Últimos frames detectados:

Código del filtrado

Función de categorización

function getFrameSeverity(blockingDuration) {
  if (blockingDuration > 200) {
    return {
      level: 'critical',
      label: 'Crítico',
      color: '#d32f2f',
      icon: '🔴'
    };
  }

  if (blockingDuration > 100) {
    return {
      level: 'high',
      label: 'Alto',
      color: '#f57c00',
      icon: '🟡'
    };
  }

  if (blockingDuration > 50) {
    return {
      level: 'medium',
      label: 'Medio',
      color: '#1a73e8',
      icon: '🔵'
    };
  }

  return {
    level: 'low',
    label: 'Bajo',
    color: '#388e3c',
    icon: '🟢'
  };
}

Usar el filtro en el observer

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    const severity = getFrameSeverity(entry.blockingDuration);

    // Solo loggear frames críticos
    if (severity.level === 'critical') {
      console.error('Frame crítico detectado!', entry);
      sendToMonitoring(entry); // Enviar a sistema de alertas
    }

    // O loggear solo frames alto/crítico
    if (severity.level === 'critical' || severity.level === 'high') {
      console.warn(\`Frame \${severity.label}:\`, entry);
    }
  }
});

Estrategias de filtrado

1. Filtrar por umbral mínimo

// Solo procesar frames muy problemáticos
const CRITICAL_THRESHOLD = 200;

observer.observe((list) => {
  for (const entry of list.getEntries()) {
    if (entry.blockingDuration > CRITICAL_THRESHOLD) {
      handleCriticalFrame(entry);
    }
  }
});

2. Diferentes acciones por severidad

const severity = getFrameSeverity(entry.blockingDuration);

switch (severity.level) {
  case 'critical':
    // Alertar inmediatamente
    sendAlert(entry);
    logToServer(entry);
    break;

  case 'high':
    // Loggear para revisión
    logToServer(entry);
    break;

  case 'medium':
    // Solo en desarrollo
    if (isDevelopment) {
      console.log('Frame medio:', entry);
    }
    break;
}

3. Sampling en producción

// Solo enviar 10% de frames medios a analytics
const severity = getFrameSeverity(entry.blockingDuration);

if (severity.level === 'critical') {
  sendToAnalytics(entry); // Siempre
} else if (severity.level === 'high') {
  sendToAnalytics(entry); // Siempre
} else if (severity.level === 'medium' && Math.random() < 0.1) {
  sendToAnalytics(entry); // 10% de las veces
}
⚠️ En producción:

Usa sampling para frames de baja severidad para evitar sobrecarga de datos. Los frames críticos siempre deben capturarse al 100%.

¿Por qué usar blockingDuration?

blockingDuration es más útil que duration porque:

// Ejemplo
entry.duration = 234ms
entry.blockingDuration = 184ms  // 234 - 50 = 184ms de bloqueo real

El blockingDuration refleja mejor el impacto real en la experiencia del usuario.