Трейсер собирает необработанные ошибки приложения (CRASH) и позволяет вручную регистрировать некритические ошибки (NON_FATAL). Например, вы можете отправить в сервис ошибку, которую приложение уже обработало. За сбор отвечает initTracerError, за отправку — initTracerErrorUploader. Пример подключения приведён в быстром старте.
Срок хранения событий зависит от настроек сервера и квот проекта; значение по умолчанию в серверной конфигурации — 90 дней.
Для работы со сбоями приложения вам понадобятся следующие модули Tracer JS SDK:
| Модуль | Описание |
|---|---|
initTracerError | Отвечает за сбор глобальных событий и ручную регистрацию ошибок в проекте. |
initTracerErrorAsyncStack | Дополняет стеки ошибок цепочкой асинхронных вызовов. Для регистрации ошибок нужен initTracerError. |
initTracerErrorUploader | Отвечает за отправку данных о событиях в сервис. |
initTracerSessionUploader | Отвечает за отправку данных о состоянии сессий приложения в сервис. |
Чтобы Tracer генерировал человекочитаемые стектрейсы, необходимо загрузить отладочную информацию (source maps). Подробнее о минификации JS-приложений читайте на странице Минификация (Source Maps)
Для начала установите SDK – введите в терминале команду:
npm install @apptracer/sdk --save
Проинициализировать SDK в проекте можно двумя способами:
В вашем app.js:
import { initTracerError, initTracerErrorUploader, initTracerSessionUploader } from '@apptracer/sdk'; initTracerError(); const config = { versionName: BUILD_VERSION_NAME, // строка с версией приложения из вашей сборки appToken: 'appToken из настроек в Трейсере', }; initTracerErrorUploader(config); initTracerSessionUploader(config);
По умолчанию модуль собирает необработанные ошибки: error и unhandledrejection в браузере, uncaughtException и unhandledRejection в Node.js. Для отправки нужен initTracerErrorUploader. Настройки ниже позволяют изменить сбор; особенности завершения Node.js-процесса описаны в быстром старте.
Подключайте модуль один раз. Настройки задаются при первом вызове initTracerError(), а повторный вызов вызывает исключение. Для доступа к уже подключённому модулю используйте getTracerModules().error.
| Параметр | Тип | Описание |
|---|---|---|
disableUnhandledErrorsListeners | boolean | Отключает автоматическую подписку на необработанные ошибки, на случай, если хочется обрабатывать их самостоятельно. |
filterError | (error: Error, errorInfo: ITracerErrorInfo) => boolean | void | Возврат false исключает ошибку из сбора, в том числе при ручной регистрации. |
handleOtherErrorDataType | boolean | Включает сбор необработанных значений, не являющихся Error; по умолчанию выключен. Значение сохраняется как cause созданной ошибки. Для ручного error(value) этот флаг не требуется. |
stackTraceLimit | number | Задаёт Error.stackTraceLimit — число кадров стека в средах, которые поддерживают эту настройку. По умолчанию SDK устанавливает 50. |
stringifyErrorDataObject | boolean | Включает JSON-представление объекта cause в causeSimpleValue (при отправке — до 100 символов, в filterError и хуках — до этого сокращения); по умолчанию используется обозначение типа объекта. Не ограничивает общий JSON-контекст или сообщение ошибки. |
maxContextValueLength | number | Максимальная длина каждого строкового значения контекста, включая отметку сокращения. По умолчанию 750. Правила и серверные ограничения. |
maxContextArrayLength | number | Максимальное число сохраняемых элементов каждого массива в контексте. По умолчанию 100. Правила и серверные ограничения. |
maxContextDepth | number | Число раскрываемых уровней контекста, включая корень. По умолчанию 5; более глубокие объекты и массивы заменяются маркерами. Правила. |
Подробнее о копировании контекста и его лимитах — в разделе JSON-контекст.
Пример функции фильтрации ошибок на основе message зарегистрированной ошибки:
import { initTracerError } from '@apptracer/sdk'; initTracerError({ filterError: (error) => { if (error.message.indexOf('ignore error with this text') !== -1) { return false; } } }); // ошибка не будет отправлена в Трейсер throw new Error('ignore error with this text');
Вы можете зарегистрировать обработанную ошибку в Tracer в качестве NON_FATAL – для этого воспользуйтесь методом error() у экземпляра, возвращённого initTracerError():
| Параметр | Тип | Описание |
|---|---|---|
value | unknown | Объект ошибки, которую вы хотите зарегистрировать. Если она не является инстансом Error, будет соз дана ошибка, а переданное значение будет использовано как cause. |
data? | ITracerErrorData | Дополнительная информация об ошибке (подробнее см. ниже) |
import { initTracerError } from '@apptracer/sdk'; const tracerError = initTracerError(); try { JSON.parse('wrong json data'); } catch (error) { tracerError.error(error); }
Для глобальной ошибки браузера без стектрейса доступная информация доп олнительно берётся из ErrorEvent
Стандартный набор информации об ошибке содержит следующие данные:
| Параметр | Тип |
|---|---|
error | Error |
errorEventType | ErrorEventType |
timestamp | number |
log | string | undefined |
errorStack | string |
causeSimpleValue? | string |
properties | ITracerErrorProperties |
В ITracerErrorInfo также входят дополнительные данные из таблицы ниже. Поле context содержит JSON-копию контекста с типом TracerJsonObject. В браузере состояние видимости страницы доступно в properties.documentVisibilityState.
Вместе с ошибкой вы можете передать дополнительную информацию о ней в качестве параметров:
| Параметр | Тип | Описание |
|---|---|---|
context | TracerErrorContext | Контекст конкретного экземпляра события: вложенные объекты, массивы, строки, числа, boolean и null. Поля верхнего уровня переопределяют общий контекст. Подробнее. |
keys | Record<string, string | number | boolean> | Ключи только для этой ошибки. Дополняют общие ключи и заменяют их значения при совпадении имён. Ограничения сервера. |
userId | string | number | ID пользователя (только для данной ошибки). |
issueKey | string | Специальный ключ, влияющий на группировку событий в общем списке (подробнее см. ниже). |
crashIdSource | string | Строка, которая используется вместо стектрейса как основа группировки. Сервер дополнительно учитывает компонент и важность ошибки. Не включайте динамические данные, например userId: иначе одна ошибка разделится на группы по пользователям. |
component | string | Используйте этот параметр, если ваше приложение состоит из множества самостоятельных компонентов (распространённая ситуация для web). Сбои, зафиксированные внутри компонента, будут выделены в отдельную группу. Версии приложения также будут сгруппированы по компоненту. |
severity | string | Уровень логирования (серьезности) ошибки, используется для классификации ошибок. Доступные значения: fatal (влияет на crash-free),error,warning,notice,debug |
versionName | string | Переопределяет значение из настроек аплоадера. Может быть полезно в сочетании с component. |
versionCode | number | Переопределяет значение из настроек аплоадера. Может быть полезно в сочетании с component. |
Эти данные добавляются в информацию об ошибке автоматически:
| Флаг | Тип | Описание |
|---|---|---|
asyncModuleEnabled? | boolean | Указывает на то, был ли включен модуль асинхронных стектрейсов при регистрации ошибки |
asyncModuleDataAdded? | boolean | true, если с ошибкой или операцией её регистрации связан async-контекст. Не гарантирует сохранение всех кадров после применения лимитов. Без контекста поле отсутствует. |
asyncMaxChainDepth? | number | Фактическая максимальная глубина async-цепочки: от 1 до 256, по умолчанию 32. |
asyncCollapseRepeats? | string | Фактический режим повторов: never, onError или onRegistration. |
asyncChainTruncated? | boolean | Часть ранних переходов потеряна из-за ограничения глубины цепочки. |
asyncStackTruncated? | boolean | Текст сокращён из-за общего бюджета стека. |
modifiedByPlugins? | string | Информация об ошибках, модифицированных с помощью плагина. Подробнее здесь |
asyncMaxChainDepth и asyncCollapseRepeats показывают фактические значения настроек maxChainDepth и collapseRepeats модуля initTracerErrorAsyncStack(). Подробнее о режимах и их влиянии на стек и затраты SDK — в разделе «Глубина async-цепочки и повторы».
По умолчанию сбои группируются по стектрейсу. Чтобы объединить NON_FATAL одного вида независимо от места регистрации, передайте одинаковый issueKey. Он также отображается в названии события.
crash-free показывает процент пользователей, у которых за выбранный период не было сбоев. Для расчёта этой метрики подключите initTracerSessionUploader.
Рассчитывается метрика как (1 - (Пользователи со сбоем / Все пользователи)) * 100%. При этом важно понимать, что использование приложения на разных устройствах одного пользователя или переустановка приложения на текущем устройстве будут обозначены как самостоятельные единицы при расчётах. Отчёты о полученных Трейсером сбоях и графики по событиям можно найти в разделе «Сбои».
initTracerSessionUploader автоматически создаёт сессию и отправляет её активность. Отдельно вызывать initTracerSession() не нужно. Для учёта сбоев и crash-free подключите initTracerError, а для отправки самих ошибок — initTracerErrorUploader.
В браузере сессия сохраняется, пока веб-приложение остаётся в памяти вкладки. В Node.js она заканчивается вместе с процессом. Смена пользователя, пауза SDK и возвращение в видимую вкладку не меняют UUID сессии.
SDK периодически отправляет сведения об активности сессии, в том числе после сбоя.
В скрытой вкладке отправка сведений об активности приостанавливается, а сбор и отправка ошибок продолжаются. При возвраще нии во вкладку отправка активности возобновляется.
Параметры initTracerSession():
| Параметр | Тип | Описание |
|---|---|---|
sampled | boolean | Признак выборки сессии. Пока не поддерживается. |
import { initTracerError, initTracerErrorUploader, initTracerSessionUploader } from '@apptracer/sdk'; initTracerError(); initTracerErrorUploader({ versionName: BUILD_VERSION_NAME, // строка с версией приложения из вашей сборки appToken: 'appToken', // appToken из настроек проекта в Tracer }); initTracerSessionUploader({ versionName: BUILD_VERSION_NAME, // строка с версией приложения из вашей сборки appToken: 'appToken из настроек в Трейсере' });
Подробнее о параметрах конфигурации Uploader-а ищите в Быстрый старт
Сервер может временно запретить отправку сбоев. На время запрета SDK отбрасывает неотправленные и новые сбои, отменяет повторные отправки. После снятия запрета новые ошибки снова отправляются; отброшенные данные не восстанавливаются.
Модуль доступен в основной браузерной версии SDK.
По стеку ошибки в асинхронном коде не всегда понятно, какая операция привела к сбою. Например, в нём может быть виден обработчик ответа, но не место, откуда был отправлен запрос. initTracerErrorAsyncStack добавляет к стеку сохранённую цепочку асинхронных вызовов.
Для временной паузы используйте disableTracerModules(), а для продолжения работы — enableTracerModules().
Если сбор асинхронных стеков больше не нужен, вызовите destroy() у объекта, возвращённого initTracerErrorAsyncStack(). Для повторного подключения после удаления снова вызовите initTracerErrorAsyncStack(); enableTracerModules() удалённый модуль не восстанавливает.
По умолчанию сохраняются 32 ближайших асинхронных перехода, а соседние одинаковые переходы объединяются при подготовке ошибки:
initTracerErrorAsyncStack({ maxChainDepth: 32, collapseRepeats: 'onError' });
maxChainDepth задаёт число сохраняемых async-переходов — от 1 до 256. Большая глубина даёт больше контекста, но увеличивает расход памяти и время обработки ошибки. При превышении лимита отбрасывается начало цепочки и добавляется отметка [Async chain truncated].
collapseRepeats определяет, когда объединять соседние одинаковые переходы:
| Значение | Что даёт | Влияние на работу |
|---|---|---|
never | Каждый переход виден отдельно. Повторы занимают место, поэтому начало цепочки теряется раньше. | Нет затрат на сравнение повторов, но итоговый стек может быть длиннее. |
onError — по умолчанию | Повторы объединяются при подготовке ошибки. | Меньше работы до ошибки; сравнение выполняется при её обработке. Уже отброшенные переходы не восстанавливаются. |
onRegistration | Повторы объединяются сразу и занимают одну запись. В длинной повторяющейся цепочке сохраняется больше раннего контекста. | Больше работы при обычном выполнении. Полезно для углублённой диагностики выбранной группы пользователей. |
При подключённом initTracerErrorAsyncStack весь отправляемый стек ограничен 256000 единицами UTF-16. При превышении SDK сокращает стек. Отдельной настройки этого лимита нет.
Флаг asyncChainTruncated означает сокращение цепочки по глубине, а asyncStackTruncated — сокращение текста стека.
Настройки задаются при инициализации. Например, приложение может выбирать более подробный сбор для отдельных пользователей:
// appConfig — пример конфигурации вашего приложения, не часть SDK. const detailed = appConfig.detailedAsyncDiagnostics; initTracerErrorAsyncStack({ maxChainDepth: detailed ? 256 : 32, collapseRepeats: detailed ? 'onRegistration' : 'onError' });
detailedAsyncDiagnostics — условный флаг для этого примера. Его значение задаёт приложение. Он влияет на подробность стека, а не на долю отправляемых ошибок.
Пр и параллельном выполнении нативных async/await-обработчиков контекст после await может теряться или смешиваться, особенно при ручном вызове error(). Настройки глубины и объединения повторов на это ограничение не влияют.
В средах без WeakRef обработчики addEventListener(..., { signal }) продолжают работать, но регистрируются без сбора async-контекста и его переноса OpenTelemetry. Для остальных подписок WeakRef не требуется. Если связь с трассировкой нужна такому обработчику, привяжите её явно через context.bind(...).
| Параметр | Тип | Описание |
|---|---|---|
maxChainDepth | number | Максимальная глубина сохраняемой async-цепочки: целое число от 1 до 256, по умолчанию 32. Влияние настройки. |
collapseRepeats | 'never' | 'onError' | 'onRegistration' | Когда объединять соседние одинаковые переходы: никогда, при ошибке или при регистрации. По умолчанию onError. Различия между режимами описаны выше. |
patchResizeObserver | boolean | Включает сбор контекста ResizeObserver; по умолчанию выключен. |
disableStackCleanup | boolean | Отключает удаление частей стектрейса из дополнительных функций-обёрток, необходимых для работы модуля. |
disablePatchPromise | boolean | Значение true отключает соответствующий патч; по умолчанию патч включён (флаг false). |
disablePatchQueueMicrotask | boolean | Значение true отключает соответствующий патч; по умолчанию патч включён (флаг false). |
disablePatchSetTimeout | boolean | Значение true отключает соответствующий патч; по умолчанию патч включён (флаг false). |
disablePatchSetInterval | boolean | Значение true отключает соответствующий патч; по умолчанию патч включён (флаг false). |
disablePatchEventTarget | boolean | Значение true отключает соответствующий па тч; по умолчанию патч включён (флаг false). |
Недопустимые значения maxChainDepth и collapseRepeats вызывают исключение при инициализации. Изменение исходного объекта конфигурации после инициализации не меняет настройки модуля.
Пример асинхронного стектрейса в небольшом демо: https://apptracer.ru/async-demo/
В вашем app.js:
import { initTracerError, initTracerErrorUploader, initTracerErrorAsyncStack } from '@apptracer/sdk'; initTracerErrorAsyncStack(); initTracerError(); initTracerErrorUploader({ versionName: BUILD_VERSION_NAME, // строка с версией приложения из вашей сборки appToken: 'appToken из настроек в Трейсере' }); (function main() { setTimeout(function onTime() { Promise.resolve('wrong_json').then(data => { JSON.parse(data); }); }); })();
В результате получаем ошибку с полной информацией о цепочке вызовов:
SyntaxError: Unexpected token 'w', "wrong_json" is not valid JSON at JSON.parse (<anonymous>) at https://apptracer.ru/async-demo/index.js:1:9543 (Promise.then onFulfilled) at https://apptracer.ru/async-demo/index.js:1:9529 (setTimeout) at HTMLButtonElement.main (https://apptracer.ru/async-demo/index.js:1:9476)