|
|
| Строка 1: |
Строка 1: |
| = Отслеживание производительности веб-сайта с помощью DQL =
| |
|
| |
|
| '''DQL''' предоставляет прямой доступ к пользовательским событиям и встроенным метрикам, которые собирает '''RUM'''. Используйте его, когда вам нужно выйти за рамки того, что показывают '''Ключевые показатели опыта''' и '''Инспектор ошибок''' по умолчанию — например, чтобы сегментировать '''Core Web Vitals''' по пользовательскому параметру, отслеживать тенденции загрузки страниц в разных развертываниях или исследовать медленные запросы на всех ваших фронтендах.
| |
|
| |
| Выполните приведенные ниже запросы в блокнотах для оперативного анализа и создания дашбордов, или преобразуйте любой из них в пользовательскую метрику с помощью '''OpenPipeline'''.
| |
|
| |
| == Основные показатели веб-технологий ==
| |
|
| |
| '''RUM''' собирает основные веб-данные как на страницах, так и в представлениях. '''Google''' рекомендует анализировать их на 75-м процентиле данных поля, чтобы оценить, соответствуют ли ваши страницы пороговым значениям «Хорошо», «Требует улучшения» или «Плохо». Приведенные ниже запросы используют сводные данные страниц, которые соответствуют спецификации '''Google''' для страниц и встроенным метрикам.
| |
|
| |
| === Largest Contentful Paint (LCP) ===
| |
|
| |
| Показатель '''LCP''' измеряет время, необходимое для отображения самого крупного видимого элемента контента — например, главного изображения, заголовка или текстового блока. Рост значений может указывать на то, что пользователи дольше ждут появления контента.
| |
|
| |
| <pre>
| |
| timeseries LCP = percentile(dt.frontend.web.page.largest_contentful_paint, 75)
| |
| //, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу
| |
| </pre>
| |
|
| |
| Чтобы определить, какие страницы имеют самый высокий показатель '''LCP''', используйте следующий запрос.
| |
|
| |
| <pre>
| |
| 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
| |
| </pre>
| |
|
| |
| === Взаимодействие с Next Paint (INP) ===
| |
|
| |
| '''INP''' измеряет задержку между взаимодействием пользователя — например, щелчком мыши, касанием или нажатием клавиши — и следующим визуальным обновлением. Высокие значения могут указывать на то, что пользовательский интерфейс работает медленно, даже если первоначальная загрузка страницы была быстрой.
| |
|
| |
| <pre>
| |
| timeseries INP = percentile(dt.frontend.web.page.interaction_to_next_paint, 75)
| |
| //, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу
| |
| </pre>
| |
|
| |
| Чтобы определить, какие страницы имеют наихудшую отзывчивость при взаимодействии с пользователем, используйте следующий запрос.
| |
|
| |
| <pre>
| |
| 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
| |
| </pre>
| |
|
| |
| === Накопительное изменение компоновки (CLS) ===
| |
|
| |
| Показатель '''CLS''' количественно оценивает, насколько неожиданно изменяется расположение элементов на странице в течение всего её жизненного цикла. Высокие значения означают, что элементы неожиданно меняют своё положение, что может привести к случайным кликам или дезориентирующему восприятию текста.
| |
|
| |
| <pre>
| |
| timeseries CLS = percentile(dt.frontend.web.page.cumulative_layout_shift, 75)
| |
| //, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу
| |
| | fieldsAdd CLS = CLS[] * 0.0001
| |
| </pre>
| |
|
| |
| Показатель '''CLS''' хранится в виде значения типа <code>long</code>, масштабированного на 10 000. Умножение на <code>0.0001</code> преобразует его обратно в стандартный балл от 0 до 1.
| |
|
| |
| Чтобы определить, какие страницы обладают наихудшей визуальной стабильностью, используйте следующий запрос.
| |
|
| |
| <pre>
| |
| 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
| |
| </pre>
| |
|
| |
| == Производительность загрузки страницы ==
| |
|
| |
| '''RUM''' собирает данные о времени загрузки страниц из API '''W3C Navigation Timing''' в виде встроенных метрик и полей событий навигации. Используйте приведенные ниже запросы для мониторинга общей продолжительности загрузки страницы и скорости отклика сервера на всех ваших фронтендах.
| |
|
| |
| === Время загрузки страницы ===
| |
|
| |
| Показатель «Завершение события загрузки» измеряет время от начала навигации до завершения события загрузки браузера. Отслеживание значений во времени помогает выявлять регрессии, вызванные новыми развертываниями, сторонними скриптами или изменениями инфраструктуры.
| |
|
| |
| <pre>
| |
| timeseries load_event_end = percentile(dt.frontend.web.navigation.load_event_end, 75)
| |
| //, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу
| |
| </pre>
| |
|
| |
| Чтобы определить, какие страницы загружаются дольше всего, используйте следующий запрос.
| |
|
| |
| <pre>
| |
| 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
| |
| </pre>
| |
|
| |
| === Время до первого байта (TTFB) ===
| |
|
| |
| Показатель '''TTFB''' отражает скорость ответа вашего сервера. Высокий '''TTFB''' часто указывает на проблемы на стороне сервера или '''CDN''', не связанные с кодом вашего фронтенда.
| |
|
| |
| <pre>
| |
| timeseries TTFB = percentile(dt.frontend.web.navigation.time_to_first_byte, 75)
| |
| //, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу
| |
| </pre>
| |
|
| |
| Чтобы определить, какие страницы имеют наибольшее время до первого байта ('''TTFB'''), используйте следующий запрос.
| |
|
| |
| <pre>
| |
| 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
| |
| </pre>
| |
|
| |
| == Производительность ресурсов и запросов ==
| |
|
| |
| В событиях пользователя регистрируются запросы, включающие вызовы '''XHR''' и '''Fetch''', выполняемые во время загрузки страницы и взаимодействия пользователя с ней. Следующие запросы помогут вам выявить медленные или неработающие запросы от сторонних и собственных сервисов.
| |
|
| |
| === Самые медленные запросы по продолжительности ===
| |
|
| |
| Медленные запросы '''XHR''' и '''Fetch''' могут ухудшить воспринимаемую производительность даже после загрузки страницы. Отслеживание длительности запросов во времени помогает выявлять замедления работы бэкенда или сторонних сервисов до того, как они повлияют на пользовательский опыт.
| |
|
| |
| <pre>
| |
| timeseries request_duration = percentile(dt.frontend.request.duration, 75)
| |
| //, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу
| |
| </pre>
| |
|
| |
| Чтобы определить, какие '''URL'''-адреса работают медленнее всего, используйте следующий запрос.
| |
|
| |
| <pre>
| |
| 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
| |
| </pre>
| |
|
| |
| === Неудачные запросы по коду состояния ===
| |
|
| |
| Приведенный ниже запрос создает временной ряд количества запросов с разбивкой по классам кодов состояния, что полезно для отслеживания тенденций частоты ошибок с течением времени.
| |
|
| |
| <pre>
| |
| 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" // Необязательно: фильтр по конкретному интерфейсу
| |
| </pre>
| |
|
| |
| Чтобы определить, какие '''URL'''-адреса не работают, используйте следующий запрос.
| |
|
| |
| <pre>
| |
| 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
| |
| </pre>
| |
|
| |
| == Анализ ошибок ==
| |
|
| |
| '''RUM''' отслеживает несколько типов ошибок в веб-среде: исключения '''JavaScript''', неудачные запросы (ответы 4xx и 5xx) и нарушения '''CSP'''. Приведенные ниже запросы помогут вам отслеживать тенденции ошибок и выявлять наиболее серьезные ошибки, которые следует исправлять в первую очередь.
| |
|
| |
| === Ошибки по типу ===
| |
|
| |
| Отслеживание количества ошибок по типам помогает выявлять внезапные всплески, вызванные некорректными развертываниями, удаленными конечными точками API или вновь возникшими регрессиями.
| |
|
| |
| <pre>
| |
| timeseries errors = sum(dt.frontend.error.count), by: {error.type}
| |
| //, filter: frontend.name == "FRONTEND-NAME" // Необязательно: фильтр по конкретному интерфейсу
| |
| </pre>
| |
|
| |
| === Исключения JavaScript ===
| |
|
| |
| Исключения '''JavaScript''' могут указывать на ошибки в коде вашего фронтенда или несовместимость с определенными браузерами. Отслеживание их во времени помогает сопоставить всплески исключений с развертываниями или обновлениями браузеров.
| |
|
| |
| <pre>
| |
| fetch user.events
| |
| | filter characteristics.has_exception
| |
| | filter dt.rum.agent.type == "javascript"
| |
| // | filter frontend.name == "FRONTEND-NAME" // Необязательно: фильтрация по конкретному интерфейсу
| |
| | makeTimeseries count = count()
| |
| </pre>
| |
|
| |
| Чтобы определить, какие исключения возникают чаще всего и на каких страницах, используйте следующий запрос.
| |
|
| |
| <pre>
| |
| 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
| |
| </pre>
| |
|
| |
| == Связанные темы ==
| |
|
| |
| * Встроенные метрики '''RUM'''
| |
| * Извлечение метрики из событий пользователя
| |
| * Анализ поведения пользователей с помощью '''DQL'''
| |