Логирование attribution-данных для диагностики

Web Vitals предоставляет API для измерения ключевых показателей производительности пользовательского опыта: Largest Contentful Paint (LCP), First Input Delay (FID), Cumulative Layout Shift (CLS) и другие метрики. Одним из важных аспектов работы с этими метриками является сбор attribution-данных — информации о том, где и как произошли события, которые влияют на показатели, и что их вызвало. Эти данные критичны для диагностики и оптимизации производительности.

Понимание attribution-данных

Attribution-данные включают:

  • Источник события: элемент DOM, который инициировал метрику (например, изображение или блок текста для LCP).
  • Тип события: описание события, которое повлияло на метрику (например, click, layout-shift).
  • Временные метки: точные временные значения начала и завершения события.
  • Контекст исполнения: информация о видимости элемента, состоянии документа, используемом устройстве и браузере.

Эти данные позволяют выявлять узкие места в рендеринге и интерактивности страницы, а также понять, какие элементы наиболее критичны для пользовательского опыта.

Использование библиотеки web-vitals для логирования

Библиотека web-vitals экспортирует функции для измерения каждой ключевой метрики. Основные функции:

import { getCLS, getFID, getLCP } from 'web-vitals';

Каждая функция принимает callback, в который передается объект с метрикой, содержащий как базовые значения, так и атрибутивные данные:

getLCP((metric) => {
  console.log('LCP Value:', metric.value);
  console.log('Attribution Data:', metric.entries);
});
  • metric.value — численное значение метрики (например, миллисекунды для LCP или FID).
  • metric.entries — массив событий, которые вызвали метрику, с детализацией для диагностики.

Структура attribution-данных

Для LCP объект события (PerformanceEntry) содержит:

  • element — DOM-элемент, который стал LCP.
  • startTime — момент, когда элемент был впервые визуализирован.
  • url — источник ресурса (например, URL изображения).
  • size — размер элемента в пикселях, влияющий на метрику.

Для CLS attribution включает:

  • sources — список элементов, вызвавших сдвиг.
  • node — DOM-узел, на который приходится сдвиг.
  • previousRect и currentRect — координаты элемента до и после изменения.

Для FID данные включают:

  • target — элемент, на который пользователь кликнул или коснулся.
  • startTime и processingStart — время начала события и момент, когда браузер начал обработку.

Сохранение и отправка данных на сервер

Для полноценной диагностики необходимо сохранять attribution-данные на сервер. Пример отправки с помощью fetch:

function sendMetricToServer(metric) {
  fetch('/collect-metrics', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      name: metric.name,
      value: metric.value,
      entries: metric.entries.map(entry => ({
        element: entry.element ? entry.element.tagName : null,
        url: entry.url || null,
        startTime: entry.startTime,
        size: entry.size || null
      })),
      timestamp: Date.now()
    })
  });
}

getLCP(sendMetricToServer);
getCLS(sendMetricToServer);
getFID(sendMetricToServer);

Такой подход обеспечивает:

  • централизованное хранение данных о производительности,
  • возможность построения отчетов и анализа узких мест,
  • детальный аудит того, какие элементы страницы негативно влияют на опыт пользователя.

Рекомендации по расширенному логированию

  1. Фильтрация элементов: логировать только элементы, превышающие пороговое значение метрики, чтобы уменьшить объем данных.
  2. Контекст браузера и устройства: добавлять информацию о userAgent, размере окна и сети для выявления зависимостей.
  3. Временные серии: сохранять метрики с точной временной отметкой для анализа динамики изменений страницы.
  4. Агрегация событий CLS: суммировать сдвиги для каждого уникального элемента, чтобы понять общий вклад в метрику.

Пример комплексного логирования LCP с attribution

getLCP((metric) => {
  const lcpEntry = metric.entries[metric.entries.length - 1]; // Последний LCP элемент
  const logData = {
    metric: 'LCP',
    value: metric.value,
    elementTag: lcpEntry.element ? lcpEntry.element.tagName : null,
    elementId: lcpEntry.element ? lcpEntry.element.id : null,
    url: lcpEntry.url || null,
    startTime: lcpEntry.startTime,
    size: lcpEntry.size
  };
  console.log('LCP Attribution:', logData);
});

Такой подход дает полное понимание того, какие элементы влияют на ключевые метрики и как они распределяются по странице.