EUM Browser агент

Proto OBP End User Monitoring Browser агент позволяет собирать данные о производительности веб-приложения напрямую с веб-клиентов, инструментируя браузеры конечных пользователей.

На этой странице:

Подключение и инициализация агента

Подключение файла JavaScript

Добавьте подключение файла JavaScript агента как можно раньше в теге head на каждой странице сайта, которые хотите отслеживать, например, в шаблон сайта.

Версия агента 7.2.0. Начиная с этой версии файл бандла называется protoobp-rum.js, а данные отправляются на ваш endpoint через опцию инициализации proxyне через site. Если опция proxy не задана, агент данные не отправляет. В примерах для версии 7.2.0 в качестве адреса прокси используется demo.proto.group. Настройка для предыдущих версий приведена на вкладке «Версии до 7.2.0».

  1. Асинхронное подключение. В данном варианте загрузка JavaScript файла агента происходит в асинхронном режиме. Это позволяет не блокировать загрузку основного контента страницы, но не позволяет агенту остлеживать ошибки и события, которые произошли до момента загрузки и инициализации агента.

    <script>
      (function (h, o, u, n, d) {
        h = h[d] = h[d] || {
          q: [],
          onReady: function (c) {
            h.q.push(c);
          },
        };
        d = o.createElement(u);
        d.async = 1;
        d.src = n;
        n = o.getElementsByTagName(u)[0];
        n.parentNode.insertBefore(d, n);
      })(window, document, "script", "/js/protoobp-rum.js", "POBP_RUM");
      POBP_RUM.onReady(function () {
        POBP_RUM.init({
          clientToken: "1", // обязательно, любое уникальное число
          applicationId: "1", //  обязательно, любое уникальное число
          // адрес прокси, на который агент отправляет данные.
          // В версии 7.2.0 для отправки на свой endpoint используется опция proxy (НЕ site).
          // Функция сохраняет оригинальные пути интейка (/api/v2/rum, /api/v2/logs, /api/v2/replay).
          proxy: function (options) {
            return "https://demo.proto.group" + options.path + "?" + options.parameters;
          },
          service: "web-front-end-async", // уникальное имя приложения для идентификации данных в интерфейсе Proto OBP
          env: "prod", // например, prod|test|dev|qa
          version: "1.0.0", // версия фронт-енд приложения, обязательно
          sessionSampleRate: 100, // процент сэмплирования, 100 - все клиенты, 10 - данные будут собираться только с 10% клиентов
          trackResources: true, // обязательно
          trackLongTasks: true, // обязательно
          trackUserInteractions: true, // обязательно
          trackFrustrations: true, // обязательно
          trackAnonymousUser: true, // отслеживать анонимного пользователя в рамках сайта (по умолчанию true)
          telemetrySampleRate: 0, // обязательно
          allowedTracingUrls: [
            "<https://api.example.com>",
            /https:\/\/.*\.my-api-domain\.com/,
            (url) => url.startsWith("<https://api.example.com>"),
          ],
          // список разрешенных для трейсинга URL, подробнее в документации ниже
        });
      });
    </script>
    
  2. Синхронное подключение. В данном случае загрузка JavaScript файла агента будет блокировать обработку страницы. Плюс такого метода в том, что агент при ранней инцииализации будет отслеживать вообще JavaScript ошибки и все загрузки ресурсов, с самого начала обработки страницы.

    <!-- подключения EUM агента Proto OBP-->
    <script src="/protoobp-rum.js" type="text/javascript"></script>
    <!-- инициализация EUM агента Proto OBP-->
    <script>
      window.POBP_RUM &&
        window.POBP_RUM.init({
          clientToken: "1", // обязательно, любое уникальное число
          applicationId: "1", //  обязательно, любое уникальное число
          // адрес прокси, на который агент отправляет данные.
          // В версии 7.2.0 для отправки на свой endpoint используется опция proxy (НЕ site).
          // Функция сохраняет оригинальные пути интейка (/api/v2/rum, /api/v2/logs, /api/v2/replay).
          proxy: function (options) {
            return "https://demo.proto.group" + options.path + "?" + options.parameters;
          },
          service: "web-front-end-async", // уникальное имя приложения для идентификации данных в интерфейсе Proto OBP
          env: "prod", // например, prod|test|dev|qa
          version: "1.0.0", // версия фронт-енд приложения, обязательно
          sessionSampleRate: 100, // процент сэмплирования, 100 - все клиенты, 10 - данные будут собираться только с 10% клиентов
          trackResources: true, // обязательно
          trackLongTasks: true, // обязательно
          trackUserInteractions: true, // обязательно
          trackFrustrations: true, // обязательно
          trackAnonymousUser: true, // отслеживать анонимного пользователя в рамках сайта (по умолчанию true)
          telemetrySampleRate: 0, // обязательно
          allowedTracingUrls: [
            "<https://api.example.com>",
            /https:\/\/.*\.my-api-domain\.com/,
            (url) => url.startsWith("<https://api.example.com>"),
          ],
          // список разрешенных для трейсинга URL, подробнее в документации ниже
        });
    </script>
    
  1. Асинхронное подключение. В данном варианте загрузка JavaScript файла агента происходит в асинхронном режиме. Это позволяет не блокировать загрузку основного контента страницы, но не позволяет агенту остлеживать ошибки и события, которые произошли до момента загрузки и инициализации агента.

    <script>
      (function (h, o, u, n, d) {
        h = h[d] = h[d] || {
          q: [],
          onReady: function (c) {
            h.q.push(c);
          },
        };
        d = o.createElement(u);
        d.async = 1;
        d.src = n;
        n = o.getElementsByTagName(u)[0];
        n.parentNode.insertBefore(d, n);
      })(window, document, "script", "/js/pobp-rum.js", "POBP_RUM");
      POBP_RUM.onReady(function () {
        POBP_RUM.init({
          clientToken: "1", // обязательно, любое уникальное число
          applicationId: "1", //  обязательно, любое уникальное число
          site: "https://eum.domain.ru:443", // адрес для отсылки данных, например, прокси сервер, который направляет данные на сервер Proto OBP
          service: "web-front-end-async", // уникальное имя приложения для идентификации данных в интерфейсе Proto OBP
          env: "prod", // например, prod|test|dev|qa
          version: "1.0.0", // версия фронт-енд приложения, обязательно
          sessionSampleRate: 100, // процент сэмплирования, 100 - все клиенты, 10 - данные будут собираться только с 10% клиентов
          trackResources: true, // обязательно
          trackLongTasks: true, // обязательно
          trackUserInteractions: true, // обязательно
          trackFrustrations: true, // обязательно
          trackAnonymousUser: true, // отслеживать анонимного пользователя в рамках сайта (по умолчанию true)
          telemetrySampleRate: 0, // обязательно
          allowedTracingUrls: [
            "<https://api.example.com>",
            /https:\/\/.*\.my-api-domain\.com/,
            (url) => url.startsWith("<https://api.example.com>"),
          ],
          // список разрешенных для трейсинга URL, подробнее в документации ниже
        });
      });
    </script>
    
  2. Синхронное подключение. В данном случае загрузка JavaScript файла агента будет блокировать обработку страницы. Плюс такого метода в том, что агент при ранней инцииализации будет отслеживать вообще JavaScript ошибки и все загрузки ресурсов, с самого начала обработки страницы.

    <!-- подключения EUM агента Proto OBP-->
    <script src="/pobp-rum.js" type="text/javascript"></script>
    <!-- инициализация EUM агента Proto OBP-->
    <script>
      window.POBP_RUM &&
        window.POBP_RUM.init({
          clientToken: "1", // обязательно, любое уникальное число
          applicationId: "1", //  обязательно, любое уникальное число
          site: "https://eum.company.ru:443", // адрес для отсылки данных, например, прокси сервер, который направляет данные на сервер Proto OBP
          service: "web-front-end-async", // уникальное имя приложения для идентификации данных в интерфейсе Proto OBP
          env: "prod", // например, prod|test|dev|qa
          version: "1.0.0", // версия фронт-енд приложения, обязательно
          sessionSampleRate: 100, // процент сэмплирования, 100 - все клиенты, 10 - данные будут собираться только с 10% клиентов
          trackResources: true, // обязательно
          trackLongTasks: true, // обязательно
          trackUserInteractions: true, // обязательно
          trackFrustrations: true, // обязательно
          trackAnonymousUser: true, // отслеживать анонимного пользователя в рамках сайта (по умолчанию true)
          telemetrySampleRate: 0, // обязательно
          allowedTracingUrls: [
            "<https://api.example.com>",
            /https:\/\/.*\.my-api-domain\.com/,
            (url) => url.startsWith("<https://api.example.com>"),
          ],
          // список разрешенных для трейсинга URL, подробнее в документации ниже
        });
    </script>
    

Пример конфигурации прокси-сервера для проброса EUM трафика

Прокси-сервер принимает трафик от браузеров и передаёт его на ProtoOBP Backend во внутренней сети.

Рассмотрим пример:

  • адрес подключаемого сайта: www.company.ru,
  • для сбора EUM трафика используется прокси-сервер: demo.proto.group
  • адрес ProtoOBP Backend сервера во внутренней корпоративной сети: protoobp.company.local

Вариант 1 (рекомендуемый) — функция proxy. Агент сохраняет оригинальные пути интейка (/api/v2/rum, /api/v2/logs, /api/v2/replay), что позволяет маршрутизировать трафик на прокси по пути запроса:

...
proxy: function (options) {
  return "https://demo.proto.group" + options.path + "?" + options.parameters;
},
...

При такой настройке запросы уходят на https://demo.proto.group/api/v2/rum?..., https://demo.proto.group/api/v2/logs?... и т.д.

Вариант 2 — строка proxy. Агент отправляет все запросы на указанный URL, добавляя query-параметр ddforward с оригинальным путём и параметрами интейка (?ddforward=%2Fapi%2Fv2%2Frum%3F...). В этом случае прокси-сервер должен разбирать параметр ddforward для определения целевого пути:

...
proxy: "https://demo.proto.group",
...

Пример базовой конфигурации Nginx для прокси demo.proto.group (Вариант 1, маршрутизация по пути):

http {
    server {
        listen 443 ssl;
        server_name demo.proto.group;

        # действительный путь к вашему SSL сертификату и ключу
        ssl_certificate     /etc/nginx/ssl/demo.proto.group.crt;
        ssl_certificate_key /etc/nginx/ssl/demo.proto.group.key;

        # все эндпоинты интейка: /api/v2/rum, /api/v2/logs, /api/v2/replay
        location /api/v2/ {
            proxy_pass https://protoobp.company.local;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
        location / {
          return 404;
        }
    }
}

Рассмотрим пример:

  • адрес подключаемого сайта: www.company.ru,
  • для сбора EUM трафика используется домен: eum.company.ru
  • настройка инициализации POBP_RUM:
    ...
    site: "https://eum.company.ru:443"
    ...
    
  • адрес ProtoOBP Backend сервера во внутренней корпоративной сети: protoobp.company.local
  • пример базовой конфигурации Nginx для домена eum.company.ru:
    http {
        server {
            listen 443 ssl;
            server_name eum.company.ru;
    
            # действительный путь к вашему SSL сертификату и ключу
            ssl_certificate     /etc/nginx/ssl/eum.company.ru.crt;
            ssl_certificate_key /etc/nginx/ssl/eum.company.ru.key;
    
            location /api/v2/rum {
                proxy_pass https://protoobp.company.local;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
            }
            location / {
              return 404;
            }
        }
    }
    

Поддерживаемые переменные инциализации

clientToken
      Обязательное
      Тип: строка
      Пример значения: '1111'
      Комментарий: Любое уникальное число.

applicationId
      Обязательное
      Тип: строка
      Пример значения: '2222'
      Комментарий: Любое уникальное число.

proxy
      Обязательное (для отправки данных на свой endpoint)
      Тип: строка или функция
      Пример значения: function (options) { return "https://demo.proto.group" + options.path + "?" + options.parameters }
      Комментарий: Адрес прокси-сервера, на который агент отправляет данные. В версии 7.2.0 это основной способ маршрутизации данных на собственный endpoint. Если задана функция — агент сохраняет оригинальные пути интейка (/api/v2/rum, /api/v2/logs, /api/v2/replay). Если задана строка — агент шлёт все запросы на указанный URL с query-параметром ddforward, содержащим оригинальный путь и параметры интейка.

site
      Обязательное (для версий до 7.2.0)
      Тип: строка
      Пример значения: 'https://eum.site.ru', 'https://site.ru/eum'
      Комментарий: Адрес для отсылки данных (прокси-сервер, который направляет данные на сервер Proto OBP). Используется в версиях до 7.2.0. В версии 7.2.0 для отправки данных на свой endpoint используйте опцию proxy.

telemetrySampleRate
      Обязательное
      Тип: число
      Пример значения: 0
      Комментарий: Указать значение 0.

service
      Обязательное
      Тип: строка
      Пример значения: 'web-frontend'
      Комментарий: Уникальное имя приложения для идентификации данных в интерфейсе Proto OBP.

env
      Опциональное
      Тип: строка
      Пример значения: 'prod'
      Комментарий: Например, prod|test|dev|qa

version
      Опциональное
      Тип: строка
      Пример значения: '1.0.0'
      Комментарий: Версия фронт-енд приложения. По каждой версии в Proto OBP доступна отдельная аналитика.

sessionSampleRate
      Обязательное
      Тип: число
      Пример значения: 100
      Комментарий: Процент сэмплирования пользователей для сбора данных EUM. Значение 100 - все клиенты, 10 - данные будут собираться только с 10% клиентов.

trackUserInteractions
      Обязательное
      Тип: булево
      Пример значения: true
      Комментарий: Указать значение true. Отвечает за сбор действий пользователей, таких как click и scroll.

trackFrustrations
      Обязательное
      Тип: булево
      Пример значения: true
      Комментарий: Указать значение true. Отвечает за сбор сигналов фрустрации пользователей - rage clicks, dead clicks, error clicks.

trackAnonymousUser
      Опциональное
      Тип: булево
      Пример значения: true
      Комментарий: Отслеживание анонимного пользователя в рамках одного сайта между сессиями (продлевает срок действия cookie, что позволяет связывать сессии одного посетителя). Значение по умолчанию — true.

allowedTracingUrls
      Опциональное
      Тип: список
      Пример значения: ["<https://api.example.com>", /https:\/\/.*\.my-api-domain\.com/, (url) => url.startsWith("<https://api.example.com>")]
      Комментарий: Список разрешенных для трейсинга URL. При отсылке запросов из браузера к этим URL агент будет инжектировать http заголовки, которые позволят связать трейс транзакции на бэкенде с просмотром страницы или запросом на фронтенде. Обязательно указать список URL с корректной схемой, номером порта (если в приложении при отсылке запросов используется нестандартный порт).

Работа агента c SPA фреймворками

Введение

Для Single Page Apllications (SPA) агент различает навигацию initial_load и route_change с помощью атрибута loading_type. Если клик на странице ведет к новой странице без полного обновления страницы, агент генерирует новый просмотр страницы атрибутом load_type:route_change.

Proto OBP предоставляет уникальную метрику производительности loading_time, которая рассчитывает время, необходимое для загрузки страницы. Эта метрика работает как для первичной загрузки страницы (initial_load), так и для изменения роута (route_change).

Для учета современных веб-приложений время загрузки учитывает сетевые запросы и мутации DOM:

  • Первичная загрузка: loading_time равно, в зависимости от того, что больше:
    • Разница между navigationStart и loadEventEnd.
    • Разница между navigationStart и первым временем отсутствия активности на странице.
  • Изменение роута SPA: Время загрузки равно разнице между кликом пользователя и первым моментом отсутствия активности на странице.

Настройка работы с SPA

  1. В коде инициализации агента добавить параметр:

    trackViewsManually: true,
    
  2. В коде вашего SPA приложения самотоятельно запускать создание view (startView) для каждой загрузки новой страницы или изменения роута. Опционально, можно изменить имя, сервис и версию.

    • view: по умолчанию равно пути в URL.
    • service: по умолчанию равно указанному значению при инициализации агента.
    • version: по умолчанию равно указаному значению при инициализации агента.

    Пример, в файле приложения добавить ручное создание view (startView) при смене роута:

    // агент может быть не инициализирован, поэтому нужно проверить объект POBP_RUM
    $rootScope.$on("$routeChangeSuccess", (event, next, current) => {
      if (typeof window.POBP_RUM !== "undefined") {
        window.POBP_RUM &&
          window.POBP_RUM.startView(
            next.loadedTemplateUrl,
            "web-front-end",
            "1.0.0"
          );
      }
    });
    

Добавление информации о пользователях

Эта опциональная информация поможет идентифицировать пользователя и связать транзакции и просмотры страниц

  1. В режиме асинхронного подключения:

    POBP_RUM.onReady(function() {
        POBP_RUM.setUser({
            id: '1234',             // внутренний идентификатор пользователя
            name: 'John Doe',       // внутреннее имя пользователя
            email: 'john@doe.com',  // email пользователя
           ...
         })
      })
    
  2. В режиме синхронного подключения:

    window.POBP_RUM && window.POBP_RUM.setUser({
        POBP_RUM.setUser({
            id: '1234',             // внутренний идентификатор пользователя
            name: 'John Doe',       // внутреннее имя пользователя
            email: 'john@doe.com',  // email пользователя
           ...
         })
      })
    

Добавление пользовательского контекста к событиям

Агент поддерживает два способа добавления пользовательского контекста:

  • Глобальный контекст — прикрепляется автоматически ко всем последующим RUM-событиям (views, actions, errors, resources).
  • Контекст отдельного события — прикрепляется только к конкретному вызову addAction или addError.

Глобальный контекст

Глобальный контекст позволяет добавить произвольные данные, которые будут автоматически прикреплены ко всем RUM-событиям, отправляемым агентом.

Доступные методы:

МетодОписание
POBP_RUM.setGlobalContextProperty(key, value)Добавить или обновить одно свойство глобального контекста
POBP_RUM.removeGlobalContextProperty(key)Удалить свойство из глобального контекста
POBP_RUM.getGlobalContext()Получить весь глобальный контекст
POBP_RUM.setGlobalContext(object)Заменить весь глобальный контекст целиком
POBP_RUM.clearGlobalContext()Очистить весь глобальный контекст

Пример:

// Добавить свойство в глобальный контекст
POBP_RUM.setGlobalContextProperty('frontEndInfo', {
  serverName: 'front-01'
});

// Добавить несколько свойств
POBP_RUM.setGlobalContextProperty('feature', 'checkout-v2');
POBP_RUM.setGlobalContextProperty('abTest', 'variant-B');

// Получить текущий глобальный контекст
console.log(POBP_RUM.getGlobalContext());

// Заменить весь контекст целиком
POBP_RUM.setGlobalContext({
  environment: 'staging',
  region: 'eu-west'
});

// Удалить одно свойство
POBP_RUM.removeGlobalContextProperty('abTest');

// Очистить весь глобальный контекст
POBP_RUM.clearGlobalContext();

Контекст отдельного события

Методы addAction и addError поддерживают передачу произвольного контекста в виде JSON-объекта. Контекст прикрепляется только к данному событию и становится доступен в виде тегов для поиска и анализа в интерфейсе Proto OBP.

Сигнатура:

POBP_RUM.addAction(name: string, context?: object)
POBP_RUM.addError(error: Error, context?: object)

Пример использования addAction с контекстом:

POBP_RUM.addAction('checkout', {
  cart: { items: 3, total: 99.99 },
  userId: 'abc123',
  plan: 'premium'
})

Пример использования addError с контекстом:

POBP_RUM.addError(new Error('Payment failed'), {
  orderId: 'order-456',
  paymentMethod: 'card'
})

Формат тегов контекста

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

POBP_RUM.addAction('checkout', {
  cart: { items: 3, total: 99.99 },
  userId: 'abc123',
  plan: 'premium'
})

в тегах трейса будут доступны следующие значения:

ТегЗначение
context.cart.items3
context.cart.total99.99
context.userIdabc123
context.planpremium

Переданный объект проходит через deepClone, поэтому можно безопасно мутировать оригинальный объект после вызова метода.

Исключение определенных JavaScript ошибок

В случае, если небходимо исключить из сбора какие-то JavaScript ошибки, необходимо добавить к коду инициализации агента следующий снипет:


    POBP_RUM.init({
    ...,
    beforeSend: (event, context) => {
        // отключение передачи ошибок с текстом сообщениея 'ignored error'
        if (event.type === 'error' && event.error.message.includes('ignored error')) {
            return false
        }
    },
    ...
    });

Запись сессий пользователя

Для включения функционала записи сессий, необходимо добавить к коду инициализации агента следующий снипет:


  POBP_RUM.init({
    ...
     sessionSampleRate: 50, // процент сэмплирования, 100 - все сессии, 10 - данные будут собираться только с 10% сессий
  )},
  POBP_RUM.startSessionReplayRecording(); // включение функционала заиписи сессий

Настройка EUM в корпоративной сети

Content Security Policy (CSP)

Добавьте директиву с адресом вашего прокси-сервера, чтобы браузер разрешил отправку данных EUM:

connect-src https://demo.proto.group

Поддерживаемые версии браузеров

Поддерживаются все современные браузеры.

ВозможностиChromeFirefoxSafariEdgeChrome AndroidSafari iOSIE11< IE11Opera
сбор ошибок
трейсинг
смена роута SPA
время загрузки
resource timing223
navigation timing
web vitals111
FCP
  1. только First Input Delay
  2. без информации о размере ресурса
  3. только firstByte и загрузка

Какие данные собирает агент

Помимо метрик производительности, агент также собирает следующую информацию, которая доступна для просмотра и анализа трейсов транзакций и просмотров страниц - данные добавляются в теги трейсов:

ua.string
      заголовок User-Agent
      пример значения: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36

device.type
      тип устройства
      варианты значений:
         desktop - компьютер или ноутбук
         mobile - мобильное устройство
         table - плашет
         bot - бот (синтетический клиент)

os.name
      тип операционной системы
      примеры значений: windows, macos, linux, iOS, android и тд

os.version
      версия операционной системы
      пример значения: 10.15.7

ua.name
      название браузера
      пример значения: Chrome

ua.version
      версия браузера
      пример значения: 104.0.0.0

geo.ip
      IP адрес пользователя
      пример значения: 45.241.11.200

geo.country_iso_code
      страна пользователя
      пример значения: RU

geo.country_subdivision
      регион пользователя
      пример значения: Moskva

geo.city
      город пользователя
      пример значения: Rublevo

В случае необходимости отключения логгирования IP адреса пользователя добавьте в конфигурацию ProtoOBP Backend переменную (с версии 178):

POBP_TRACE_PROCESSOR_COLLECT_EUM_IP: false

Устранение неисправностей

Нет данных

  1. Поздняя инициализация. Если вы не видите части запросов, таких как XHR, то следует инициализировать агента как можно раньше. Например, инициализировать агента до того, как происходит инициализации другой библиотеки, с помощью которой отсылаются XHR запросы с клиентов.

Проверка инициализации агента

Выполните window.POBP_RUM.getInternalContext() в консоли браузера и убедитесь, что возвращаются данные, как на примере ниже.

../../images/eum-browser-check.png

Настройка CORS для передачи заголовков ProtoOBP

В случае, если от Браузера пользователя уходят запросы на сервер с инструментированным приложением трейсером ProtoOBP необходимо на стороне веб-сервера разрешать передачу следующих заголовков, добавив их в Access-Control-Allow-Headers:

x-protoobp-origin
x-protoobp-parent-id
x-protoobp-sampling-priority
x-protoobp-trace-id

Подробнее о настройке CORS: Документация

А также, необходимо разрешить Preflight запросы с методом OPTIONS. Документация