Как отслеживать производительность веб-приложения с JavaScript и Performance API

от автора

В сентябре этого года у меня была возможность присоединиться к Forest Admin, компании, которая выполняет всю тяжёлую работу по созданию панели администратора любого веб-приложения и предоставляет платформу на основе API, чтобы реализовать все ваши конкретные бизнес-процессы. Моей первой задачей было реализовать мониторинг времени загрузки приложения, а также мониторинг времени запросов, сделанных нашими клиентами в их административном бэкенде, который я разработал.

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



В зависимости от используемой среды разработки надстройки могут уже быть установлены. Если вы разработчик React, например, react-addons-per. должен позволить вам отслеживать то, что вы хотите. В Forest Admin мы используем Ember.js, и нет никакой надстройки, подобной React. Поэтому воспользуемся Performance API, который, согласно документации, должен позволить нам сделать именно то, что мы хотим сделать:

Стандарт High Resolution Time определяет интерфейс производительности, который поддерживает измерения задержки на стороне клиента в приложениях. Интерфейсы Performance считаются интерфейсами с высоким разрешением, поскольку имеют точность до тысячных долей миллисекунды (в зависимости от аппаратных или программных ограничений).

II. API Performance


Performance API использует множество разнообразных методов. Нам понадобится всего 5:

  • mark;
  • measure;
  • getEntriesByType;
  • clearMarks/clearMeasures.

1. mark


Метод mark позволяет разместить маркер времени. Чтобы сослаться на маркер, требуется только один аргумент (строка), этот метод ничего не возвращает. Позже он позволит рассчитать время.

performance.mark('start');

2. measure


Метод measure позволяет измерить разницу во времени между двумя маркерами. Он принимает 3 аргумента: имя созданного измерителя (строка), маркер начала (строка), маркер конца (строка). Этот метод возвращает объект со свойством duration, которое вычисляет разницу между двумя маркерами.

async function timeDuration() {     performance.mark('start');     await new Promise(resolve => setTimeout(resolve, 100))     performance.mark('end');        return performance.measure('time', 'start', 'end').duration;   }      timeDuration().then((result) => console.log(result));   // output: 100

3. getEntriesByType


Метод getEntriesByType позволяет получить доступ ко всем созданным объектам определённого типа. Он возвращает массив объектов и принимает в качестве аргумента тип входных значений (строку) из следующих: frame, navigation, resource, mark, measure, paint, longtask. Не волнуйтесь, нам понадобятся только mark и measure.

performance.getEntriesByType('measure');     // output: return an Array of Object containing all the measure

4. clearMarks/clearMeasures


Методы clearMarks/clearMeasures используются для удаления ранее добавленных маркеров и измерителей из кеша браузера. Эти методы ничего не возвращают и не принимают никаких аргументов.

III. Давайте углубимся в код

Теперь, когда мы знаем методы реализации функциональности, нам нужно интегрировать её в код. У нас есть два варианта: создать маркеры и проводить измерения прямо в нужных местах кода или создать сервис (time-tracker.js) и вставить его в код. Для наглядности выберем второй вариант.

performance.mark('start');     performance.mark('end');     performance.measure('time_duration', 'start', 'end');          console.log(performance.getEntriesByType('mark').length);     // output: 2     console.log(performance.getEntriesByType('measure').length);     // output: 1          performance.clearMarks();     performance.clearMeasures();     console.log(performance.getEntriesByType('mark').length);     // output: 0     console.log(performance.getEntriesByType('measure').length);     // output: 0

Всё просто, правда? Теперь нам нужно вызвать сервисные функции в тех местах кода, которые позволят нам отслеживать время загрузки запроса и интерфейса. Для интерфейса маркер timinginterfacestart должен вызываться в начале загрузки страницы. Первым вызывается метод model маршрута, который разместим здесь. Также возможно использовать методы в жизненных циклах компонента или любой другой функции, вызванной изначально. Однако следует соблюдать осторожность при размещении маркера. Если маркер не поставить в нужное место, последующее измерение будет неточным.

import { inject as service } from '@ember/service';      export default class RouteExample extends Route {       @service timeTracker;              model() {         this.timeTracker.startInterface();         // do something       }     }

Для маркера timinginterfacestop он должен вызываться, когда закончен рендеринг приложения. Что касается рендеринга нескольких компонентов, логичным способом является использование методов в жизненных циклах этих компонентов. Метод компонента didRender из ember кажется хорошим кандидатом. Затем идёт измерение общего времени загрузки интерфейса. Его можно разместить после маркера timinginterfacestop или в любом другом желаемом месте.

import { inject as service } from '@ember/service';      export default class RenderingTracker extends Component {       @service timeTracker;            didRender() {         this.timeTracker.stopInterface();       }       stopInterfaceTracking() {         return this.timeTracker.measureTimingInterface()       }     }

Для расчёта времени запроса на сервере пользователя достаточно окружить функцию, отвечающую за запрос сервера пользователя, маркерами timingrequeststart и Timingrequeststop. Затем можно измерить время запроса, вызвав метод measureTimingRequest() из нашего сервиса.

import { inject as service } from '@ember/service';      export default class RouteExample extends Route {       @service timeTracker;              model() {         this.timeTracker.startInterface();         // do something       }              async function fetchData(params) {         //do something                this.timeTracker.startRequest();         const records = await fetchRecords(params);         this.timingTracker.stopRequest();                  const timingRequest = this.timingTracker.measureTimingRequest()         // do something else            }     }

Заключение


Надеюсь, вам понравилась эта статья. Есть и другие возможности реализовать эту функцию. Я решил показать вам путь, который имеет для меня больше смысла. API Performance – мощный инструмент, чтобы получить информацию о производительности вашего приложения. Важно знать, сталкиваются ли пользователи с трудностями, когда просматривают ваше приложение. Более того, это позволяет вам заранее нацеливаться на проблемы, чтобы решать эти проблемы и улучшать взаимодействие с пользователем. Следующим шагом может быть интеграция дополнительного электронного письма для пользователей, время загрузки у которых превышает пороговое значение, чтобы эти пользователи могли выбрать определённые параметры оптимизации.


image

ссылка на оригинал статьи https://habr.com/ru/company/skillfactory/blog/538334/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *