Обзор
Лог — одна строка текста с уровнем и, по желанию, набором структурированных атрибутов — данных «ключ — значение», которые иначе пришлось бы вставлять в сообщение. Логи видны в разделе Логи проекта, их можно искать по сообщению, уровню и атрибутам.
Отправлять их можно двумя способами:
- Явно, через
Buglapse.log.info()/warn()/error()/ ... — рекомендуемый способ: вы сами выбираете, что стоит отправлять, и можете прикрепить атрибуты. - Автоматически, включив интеграцию консоли, которая пересылает каждый вызов
console.log(),console.info(),console.warn(),console.error()иconsole.debug().
Логи — не ошибки: Buglapse.log.error() записывает строку уровня error, но инцидент не создаёт. Чтобы сообщить об исключении со стектрейсом, используйте captureException() (см. Ошибки).
Отправка логов
У объекта log по методу на уровень — log, debug, info, warn, error, — каждый принимает сообщение и необязательный объект атрибутов (есть и trace и fatal: сохраняются как debug и error):
ts
Buglapse.log.info('User signed in')
Buglapse.log.warn('Payment retry', { orderId: 1042, attempt: 2 })
Buglapse.log.error('Checkout failed', { orderId: 1042, reason: 'card_declined' })ts
import { log } from '@buglapse/browser'
log.debug('Cart recalculated', { items: 3, total: 59.9 })Вызовы до init() — например, пока скрипт с CDN ещё грузится, — встают в очередь и отправляются, когда клиент готов, так что логировать рано безопасно.
Как и любое событие, каждый лог собирается в пачку транспортом (см. Транспорты) и получает текущие теги, контекст, пользователя, environment и release (см. Контекст).
Атрибуты
Держите сообщение неизменной читаемой строкой, а переменные части кладите в атрибуты:
ts
// Хорошо — одно сообщение, поля для поиска
Buglapse.log.info('Order placed', { orderId: order.id, total: order.total, currency: 'EUR' })
// Не стоит — каждый вызов даёт новое сообщение, фильтровать не по чему
Buglapse.log.info(`Order ${order.id} placed for ${order.total} EUR`)Атрибуты хранятся в логе как есть, и каждый ключ верхнего уровня становится фильтром поиска в панели (orderId:1042). Предпочитайте плоские объекты со строками, числами и булевыми значениями — вложенные объекты сохраняются и показываются в логе, но как фильтры не предлагаются.
Атрибуты относятся к одной строке лога; теги и контекст (setTag(), setContext()) — ко всему, что отправлено после их установки. Атрибуты — для «что произошло в этом вызове», теги/контекст — для «кто и где».
Шаблоны через fmt
Когда переменные части лучше читаются внутри сообщения, пишите его с тегом fmt вместо обычного шаблонного литерала:
ts
import { fmt, log } from '@buglapse/browser' // или Buglapse.fmt со скриптом с CDN
log.error(fmt`Order ${order.id} failed for ${user.email}`)Сообщение отправляется как обычно — Order 1042 failed for ann@example.com — вместе с шаблоном и значениями в атрибутах: message.template (Order %s failed for %s) и message.parameter.0, message.parameter.1, …. Повторы одного шаблона с другими значениями схлопываются в одну строку ×N в разделе Логи, а message.template:"Order %s failed for %s" находит их все.
Значения сохраняются как строки, числа и булевы (всё остальное — текстом), первые 20; ваш собственный атрибут с тем же ключом важнее. fmt работает и с captureMessage() — см. Ошибки.
Перехват вызовов console
Интеграция консоли подключаемая. Со script-тегом включите Перехват консоли в Настройки → Скрипт загрузчика проекта — это вступит в силу при следующей загрузке страницы вашего сайта без изменения подключения.
С npm-пакетом добавьте интеграцию сами:
ts
import { init } from '@buglapse/browser'
import { consoleIntegration } from '@buglapse/browser/integrations'
init({
dsn: '{dsn}',
integrations: [consoleIntegration()],
})После регистрации она оборачивает console.log, console.info, console.warn, console.error и console.debug. Исходный метод выполняется первым, так что вывод в DevTools не меняется; затем вызов пересылается логом того же уровня (console.log → log, console.warn → warn, ...).
Аргументы разбираются так же, как у явного вызова Buglapse.log:
- последний простой объект становится атрибутами лога;
- всё перед ним склеивается через пробел в сообщение — строки как есть, остальное через
JSON.stringify; - первый аргумент в стиле
printf(%s,%d,%i,%f,%o,%O,%j) форматируется с аргументами, которые он забирает, и становится шаблоном лога, как сfmt.
ts
console.warn('Slow response', { url: '/api/cart', ms: 1840 })
// → level: warn, message: "Slow response", attributes: { url: "/api/cart", ms: 1840 }
console.log('Order %s failed after %d tries', 'A-1042', 3)
// → message: "Order A-1042 failed after 3 tries", шаблон "Order %s failed after %s tries"
console.log('items', [1, 2, 3], 42)
// → level: log, message: 'items [1,2,3] 42', без атрибутовЧто стоит помнить:
JSON.stringifyпревращаетErrorв{}, так чтоconsole.error(error)не несёт полезного сообщения и стека. Об исключениях сообщайте черезcaptureException().- Другие методы
console(table,trace,group, ...) не пересылаются. - Все сторонние скрипты страницы пишут в тот же
console, так что перехват может прислать много шума. После включения следите за квотой логов или отбрасывайте ненужное (ниже).
Чтобы выключить во время работы, отключите интеграцию по имени:
ts
Buglapse.disable('console')Интеграция консоли не зависит от хлебных крошек консоли: крошки записывают вызовы консоли только как контекст к последующей ошибке, а эта интеграция отправляет каждый вызов отдельным логом. См. Хлебные крошки.
Связь логов с трейсами
Каждый лог получает текущий trace.id — трейс активного спана или трейс страницы, если спана нет, — и span.id, если спан активен:
ts
await Buglapse.asyncSpan('checkout', async () => {
Buglapse.log.info('Starting checkout') // связан со спаном "checkout"
await submitOrder()
})В панели лог с id трейса ссылается на этот трейс. См. Связь других событий с активным спаном.
Отбрасывание и очистка логов
Логи проходят через тот же конвейер препроцессоров, что и все события, так что их можно отбросить или переписать до того, как они покинут браузер, — например, пропускать логи debug в продакшене или убирать чувствительный атрибут:
ts
Buglapse.addPreprocessor((event) => {
if (event.type !== 'log') return event
if (event.payload.level === 'debug') return null
delete event.payload.attributes?.email
return event
})Фильтры и квота
На сервере логи проходят через Настройки → Фильтры проекта, как и все события: фильтр краулеров и выражение фильтра (например, "{{event.message}}" ~ "heartbeat"). См. Фильтрация шума.
Каждый сохранённый лог расходует месячную квоту логов организации. Когда она исчерпана, логи отклоняются до следующего месяца; на ошибки и трейсы это не влияет.
Где смотреть
Откройте Логи в боковом меню проекта. Список показывает новые логи первыми — с уровнем, сообщением и временем; нажмите на лог, чтобы увидеть его атрибуты, теги и контекст, а также ссылки на определённого пользователя и трейс, в котором он пойман.
Строка поиска ищет свободный текст по сообщению и поддерживает фильтры (полный синтаксис — операторы вроде != и ~, кавычки — на странице Поиск):
level:— уровень лога:log,debug,info,warnилиerror;environment:—environment, переданный вinit(), напримерenvironment:production(см.environmentиrelease);user:— определённый пользователь (задаётся черезBuglapse.setUser(), см. Пользователи);browser:/os:/device:— браузер, ОС и модель устройства посетителя, напримерbrowser:Safari;- любой ключ атрибута, тега или контекста — например,
orderId:1042,release:1.4.0.
Например: checkout level:error environment:production browser:Safari.