Отслеживание производительности веб-сайта с помощью DQL
Отслеживание производительности веб-сайта с помощью DQL
DQL предоставляет прямой доступ к пользовательским событиям и встроенным метрикам, которые собирает RUM. Используйте его, когда вам нужно выйти за рамки того, что показывают Ключевые показатели опыта и Инспектор ошибок по умолчанию — например, чтобы сегментировать Core Web Vitals по пользовательскому параметру, отслеживать тенденции загрузки страниц в разных развертываниях или исследовать медленные запросы на всех ваших фронтендах.
Выполните приведенные ниже запросы в блокнотах для оперативного анализа и создания дашбордов, или преобразуйте любой из них в пользовательскую метрику с помощью OpenPipeline.
Основные показатели веб-технологий
RUM собирает основные веб-данные как на страницах, так и в представлениях. Google рекомендует анализировать их на 75-м процентиле данных поля, чтобы оценить, соответствуют ли ваши страницы пороговым значениям «Хорошо», «Требует улучшения» или «Плохо». Приведенные ниже запросы используют сводные данные страниц, которые соответствуют спецификации Google для страниц и встроенным метрикам.
Largest Contentful Paint (LCP)
Показатель LCP измеряет время, необходимое для отображения самого крупного видимого элемента контента — например, главного изображения, заголовка или текстового блока. Рост значений может указывать на то, что пользователи дольше ждут появления контента.
timeseries LCP = percentile(dt.frontend.web.page.largest_contentful_paint, 75) //, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу
Чтобы определить, какие страницы имеют самый высокий показатель LCP, используйте следующий запрос.
fetch user.events
| filter characteristics.has_page_summary
// | filter frontend.name == "FRONTEND-NAME" // Необязательно: фильтрация по конкретному интерфейсу
| filter isNotNull(web_vitals.largest_contentful_paint)
| summarize LCP = percentile(web_vitals.largest_contentful_paint, 75), by: {page.name}
| sort LCP desc
Взаимодействие с Next Paint (INP)
INP измеряет задержку между взаимодействием пользователя — например, щелчком мыши, касанием или нажатием клавиши — и следующим визуальным обновлением. Высокие значения могут указывать на то, что пользовательский интерфейс работает медленно, даже если первоначальная загрузка страницы была быстрой.
timeseries INP = percentile(dt.frontend.web.page.interaction_to_next_paint, 75) //, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу
Чтобы определить, какие страницы имеют наихудшую отзывчивость при взаимодействии с пользователем, используйте следующий запрос.
fetch user.events
| filter characteristics.has_page_summary
// | filter frontend.name == "FRONTEND-NAME" // Необязательно: фильтрация по конкретному интерфейсу
| filter isNotNull(web_vitals.interaction_to_next_paint)
| summarize INP = percentile(web_vitals.interaction_to_next_paint, 75), by: {page.name}
| sort INP desc
Накопительное изменение компоновки (CLS)
Показатель CLS количественно оценивает, насколько неожиданно изменяется расположение элементов на странице в течение всего её жизненного цикла. Высокие значения означают, что элементы неожиданно меняют своё положение, что может привести к случайным кликам или дезориентирующему восприятию текста.
timeseries CLS = percentile(dt.frontend.web.page.cumulative_layout_shift, 75) //, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу | fieldsAdd CLS = CLS[] * 0.0001
Показатель CLS хранится в виде значения типа long, масштабированного на 10 000. Умножение на 0.0001 преобразует его обратно в стандартный балл от 0 до 1.
Чтобы определить, какие страницы обладают наихудшей визуальной стабильностью, используйте следующий запрос.
fetch user.events
| filter characteristics.has_page_summary
// | filter frontend.name == "FRONTEND-NAME" // Необязательно: фильтрация по конкретному интерфейсу
| filter isNotNull(web_vitals.cumulative_layout_shift)
| summarize CLS = percentile(web_vitals.cumulative_layout_shift, 75), by: {page.name}
| sort CLS desc
Производительность загрузки страницы
RUM собирает данные о времени загрузки страниц из API W3C Navigation Timing в виде встроенных метрик и полей событий навигации. Используйте приведенные ниже запросы для мониторинга общей продолжительности загрузки страницы и скорости отклика сервера на всех ваших фронтендах.
Время загрузки страницы
Показатель «Завершение события загрузки» измеряет время от начала навигации до завершения события загрузки браузера. Отслеживание значений во времени помогает выявлять регрессии, вызванные новыми развертываниями, сторонними скриптами или изменениями инфраструктуры.
timeseries load_event_end = percentile(dt.frontend.web.navigation.load_event_end, 75) //, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу
Чтобы определить, какие страницы загружаются дольше всего, используйте следующий запрос.
fetch user.events
| filter characteristics.has_w3c_navigation_timings
// | filter frontend.name == "FRONTEND-NAME" // Необязательно: фильтрация по конкретному интерфейсу
| summarize load_event_end = percentile(performance.load_event_end, 75), by: {page.name}
| sort load_event_end desc
Время до первого байта (TTFB)
Показатель TTFB отражает скорость ответа вашего сервера. Высокий TTFB часто указывает на проблемы на стороне сервера или CDN, не связанные с кодом вашего фронтенда.
timeseries TTFB = percentile(dt.frontend.web.navigation.time_to_first_byte, 75) //, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу
Чтобы определить, какие страницы имеют наибольшее время до первого байта (TTFB), используйте следующий запрос.
fetch user.events
| filter characteristics.has_w3c_navigation_timings
// | filter frontend.name == "FRONTEND-NAME" // Необязательно: фильтрация по конкретному интерфейсу
| filter isNotNull(web_vitals.time_to_first_byte)
| summarize TTFB = percentile(web_vitals.time_to_first_byte, 75), by: {page.name}
| sort TTFB desc
Производительность ресурсов и запросов
В событиях пользователя регистрируются запросы, включающие вызовы XHR и Fetch, выполняемые во время загрузки страницы и взаимодействия пользователя с ней. Следующие запросы помогут вам выявить медленные или неработающие запросы от сторонних и собственных сервисов.
Самые медленные запросы по продолжительности
Медленные запросы XHR и Fetch могут ухудшить воспринимаемую производительность даже после загрузки страницы. Отслеживание длительности запросов во времени помогает выявлять замедления работы бэкенда или сторонних сервисов до того, как они повлияют на пользовательский опыт.
timeseries request_duration = percentile(dt.frontend.request.duration, 75) //, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу
Чтобы определить, какие URL-адреса работают медленнее всего, используйте следующий запрос.
fetch user.events
| filter characteristics.has_request
// | filter frontend.name == "FRONTEND-NAME" // Необязательно: фильтрация по конкретному интерфейсу
| filter isNotNull(url.full)
| summarize {
request_count = count(),
duration_p75 = percentile(duration, 75),
error_count = countIf(http.response.status_code < 99 OR http.response.status_code >= 400)
}, by: {url.full}
| sort duration_p75 desc
| limit 20
Неудачные запросы по коду состояния
Приведенный ниже запрос создает временной ряд количества запросов с разбивкой по классам кодов состояния, что полезно для отслеживания тенденций частоты ошибок с течением времени.
timeseries {
requests_2xx = sum(dt.frontend.request.count, filter: http.response.status_code_class == "2xx"),
requests_4xx = sum(dt.frontend.request.count, filter: http.response.status_code_class == "4xx"),
requests_5xx = sum(dt.frontend.request.count, filter: http.response.status_code_class == "5xx")
}
//, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу
Чтобы определить, какие URL-адреса не работают, используйте следующий запрос.
fetch user.events
| filter characteristics.has_request
// | filter frontend.name == "FRONTEND-NAME" // Необязательно: фильтрация по конкретному интерфейсу
| filter http.response.status_code < 99 OR http.response.status_code >= 400
| summarize count = count(), by: {url.full, http.response.status_code}
| sort count desc
Анализ ошибок
RUM отслеживает несколько типов ошибок в веб-среде: исключения JavaScript, неудачные запросы (ответы 4xx и 5xx) и нарушения CSP. Приведенные ниже запросы помогут вам отслеживать тенденции ошибок и выявлять наиболее серьезные ошибки, которые следует исправлять в первую очередь.
Ошибки по типу
Отслеживание количества ошибок по типам помогает выявлять внезапные всплески, вызванные некорректными развертываниями, удаленными конечными точками API или вновь возникшими регрессиями.
timeseries errors = sum(dt.frontend.error.count), by: {error.type}
//, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу
Исключения JavaScript
Исключения JavaScript могут указывать на ошибки в коде вашего фронтенда или несовместимость с определенными браузерами. Отслеживание их во времени помогает сопоставить всплески исключений с развертываниями или обновлениями браузеров.
fetch user.events | filter characteristics.has_exception | filter dt.rum.agent.type == "javascript" // | filter frontend.name == "FRONTEND-NAME" // Необязательно: фильтрация по конкретному интерфейсу | makeTimeseries count = count()
Чтобы определить, какие исключения возникают чаще всего и на каких страницах, используйте следующий запрос.
fetch user.events
| filter characteristics.has_exception
| filter dt.rum.agent.type == "javascript"
// | filter frontend.name == "FRONTEND-NAME" // Необязательно: фильтрация по конкретному интерфейсу
| summarize count = count(), by: {exception.message, page.name}
| sort count desc
Связанные темы
- Встроенные метрики RUM
- Извлечение метрики из событий пользователя
- Анализ поведения пользователей с помощью DQL