Теги и контекст
И то, и другое прикрепляется к каждому событию, пойманному после установки, но задачи у них разные:
- Теги (
setTag(key, value)) — плоские парыkey: string, значение всегда приводится к строке. По ним в первую очередь ищет строка поиска панели в фильтреkey:value, напримерcheckout.step:paymentпрямо в поиске Исключений/Трейсов/Логов (см. Поиск). - Контекст (
setContext(key, value)) прикрепляет вложенный объект под пространством имён (setContext('order', { id, total })становитсяorder.id/order.totalв событии). Он для описательных данных, которые нужно видеть на странице события, и тоже участвует в поиске, если тега с тем же ключом нет.
Оба необязательны — для перехвата ошибки ничего из этого не нужно. Короткая версия — на странице Пользователи и контекст.
Задание тегов и контекста
ts
Buglapse.setTag('checkout.step', 'payment')
Buglapse.setTag('plan', 'pro')
Buglapse.setContext('order', { id: order.id, total: order.total, currency: 'USD' })После установки значение тега/контекста прикрепляется к каждому событию, пойманному дальше, — исключениям, логам, трейсам, спанам, — пока вы снова не вызовете setTag/setContext с тем же ключом. unset нет; перезапишите ключ новым значением.
setContext разворачивает вложенные объекты в ключи через точку под заданным префиксом, так что setContext('order', { customer: { id: 42 } }) даёт order.customer.id — так же разворачиваются контексты device.*/browser.* (см. Настройка). Массивы и простые значения внутри объекта сохраняются как есть под своим развёрнутым ключом.
Пользователи
setUser() — тонкая обёртка над setContext('user', ...), которая к тому же определяет, к какому пользователю относится событие, — карточка пользователя в событии, затронутые пользователи инцидента, фильтр поиска user::
ts
Buglapse.setUser({ id: user.id, email: user.email, username: user.username })Все поля необязательны, и повторный вызов дополняет уже известное, а не заменяет: вызовите один раз с одним id при входе, потом снова с email, когда он появится, — сохранится и то, и другое. Любые поля помимо id/email/username/name тоже сохраняются, просто не участвуют в порядке сопоставления id → email → IP, по которому панель различает пользователей проекта (без setUser используется IP запроса).
Временное наложение через withScope()
setTag/setContext меняют то, что прикрепляется глобально, с этого момента. withScope() вместо этого накладывает теги/контекст на один колбэк, не трогая заданное глобально:
ts
Buglapse.withScope((scope) => {
scope.setTag('checkout.step', 'payment')
scope.setContext('order', { id: order.id, total: order.total })
try {
chargeCard(order)
} catch (error) {
Buglapse.captureException(error)
}
})Любое событие, пойманное внутри колбэка, несёт наложение поверх глобальных тегов/контекста; всё, что поймано после возврата из withScope(), его не видит. scope.setUser() делает то же для пользователя — это областная версия setUser().
Наложение живёт только в синхронной части колбэка. У браузерного клиента нет AsyncLocalStorage, чтобы перенести его через await, поэтому:
ts
// ❌ теряет наложение — перехват после await
Buglapse.withScope(async (scope) => {
scope.setTag('checkout.step', 'payment')
await chargeCard(order) // к моменту продолжения область уже исчезла
Buglapse.captureException(error) // поймано без тега "checkout.step"
})
// ✅ ловите до await или задайте заново через setTag()/setContext() после него
Buglapse.withScope((scope) => {
scope.setTag('checkout.step', 'payment')
try {
chargeCardSync(order)
} catch (error) {
Buglapse.captureException(error) // ещё внутри синхронного наложения
}
})Если перехват должен случиться после await, задайте теги/контекст глобально через setTag()/setContext() (и очистите/перезапишите их, когда операция закончится), а не полагайтесь на withScope().
environment и release
Эти два задаются отдельно — опциями environment/release в init() или атрибутами data-environment/data-release у script-тега, а не через setTag/setContext, — потому что это простые значения, а не объекты для разворачивания, и потому что панель обращается с ними особо: по environment работают фильтр environment: в поиске и условия в выражении фильтра, а release позволяет раскодировать минифицированный стектрейс в исходный код, если загружены соответствующие source maps. См. Настройка и Source maps.
Автоматический контекст
Часть контекста заполняют подключаемые интеграции, а не ваш вызов setContext():
- DeviceIntegration один раз при подключении отправляет user agent браузера. Сервер разбирает его в
browser.name/browser.version,os.name/os.versionиdevice.type/device.manufacturer/device.model(последние три — только если user agent указывает конкретное устройство, например iPhone) в каждом событии — больше ничего о браузере посетителя (язык, часовой пояс, размер экрана, ...) не собирается и не хранится. - HttpContextIntegration заново проставляет
request.url/request.referrerв каждое событие, потому что в SPA адрес может смениться между перехватами без перезагрузки.
Обе подключаемые и включаются в Настройки → Скрипт загрузчика проекта — см. Интеграции.
Контекст в панели
Страница события группирует развёрнутый контекст обратно по префиксу (order.* под заголовком «Order» и т.д.), превращая ключи через точку в подписи, — разобранные browser.*, os.* и device.* появляются там группами Browser / OS / Device. trace.*, replay.* и user.* в этот общий список не входят, потому что у каждого есть свой интерфейс (панель трейса/записи, карточка пользователя). Нажатие на любую строку ищет именно эту пару key:value — тем же синтаксисом, что вы бы набрали вручную:
order.currency:"USD"