Отчёты об ошибках
Адаптеры отчётности
Каждый адаптер — собственная точка входа exports, поэтому адаптер, который вы не импортируете, никогда не попадает в бандл.
import { createConsoleReporter } from 'vue-error-boundary-kit/adapters/console'
import { createHttpReporter } from 'vue-error-boundary-kit/adapters/http'
import { createSentryReporter } from 'vue-error-boundary-kit/adapters/sentry'
import { createBugsnagReporter } from 'vue-error-boundary-kit/adapters/bugsnag'
import { createLogRocketReporter } from 'vue-error-boundary-kit/adapters/logrocket'
import { createOtelReporter } from 'vue-error-boundary-kit/adapters/otel'adapters/console—createConsoleReporter({ logger?, prefix? }), плюс готовый экземплярconsoleReporter. По умолчанию логирует черезconsole.error; хороший вариант по умолчанию для разработки. Сообщения имеют префикс[vue-error-boundary-kit]— передайтеprefix: '[my-app]', чтобы сменить бренд, илиprefix: '', чтобы убрать его.adapters/http—createHttpReporter({ endpoint, batchInterval?, maxBatchSize?, headers?, serialize? }). Отправляет POST черезfetch(батчами, еслиbatchInterval > 0); слушательpagehideпринудительно сбрасывает любой ожидающий батч черезnavigator.sendBeacon, поскольку выполняющийсяfetchможет быть прерван при фактическом закрытии страницы.adapters/sentry—createSentryReporter({ client, tags? }).@sentry/vueэтим пакетом никогда не импортируется — передайте собственный уже инициализированный клиент Sentry (любой объект с методомcaptureException(error, hint?)); это остаётся тонкой, структурно типизированной обёрткой.adapters/bugsnag—createBugsnagReporter({ client, severity? }). ОборачиваетBugsnag.notify(error, onError), устанавливаяevent.context/event.severityи добавляя секцию метаданныхerrorBoundaryчерезevent.addMetadata(...).@bugsnag/jsникогда не импортируется — передайте собственный инициализированный клиент.adapters/logrocket—createLogRocketReporter({ client, tags? }). ОборачиваетLogRocket.captureException(error, { tags, extra }); поскольку LogRocket требует скалярных значений вextra, нескалярный контекст автоматически преобразуется черезJSON.stringify.logrocketникогда не импортируется — передайте собственный инициализированный клиент.adapters/otel—createOtelReporter({ tracer, spanName?, attributes? }). Запускает span на каждую ошибку через собственный уже инициализированный OTelTracer(например,trace.getTracer('my-app')), вызываетrecordException()+setStatus({ code: ERROR }), добавляет поляCapturedErrorкак атрибуты span, затем завершает span.@opentelemetry/apiникогда не импортируется — передайте собственный tracer. Хотите привязать ошибки к текущему span вместо нового? Передайте{ startSpan: () => trace.getActiveSpan() ?? realTracer.startSpan(name) }в качествеtracer.
Все шесть адаптеров назначения принимают CapturedError и куда-то его пересылают; вы можете передать репортер (или массив) в любой <ErrorBoundary>, в useErrorBoundary() или в useGlobalErrorCapture().
Ограничение частоты и дедупликация
adapters/rate-limit оборачивает любой репортер(ы), чтобы защитить их от шторма массовых сбоев — например, сломанный список, перерисовывающийся сотни раз в секунду, который иначе завалит Sentry/HTTP/и т.д. почти идентичными отчётами:
import { createRateLimitedReporter } from 'vue-error-boundary-kit/adapters/rate-limit'
const reporter = createRateLimitedReporter([sentryReporter, consoleReporter], {
maxPerWindow: 10, // не более 10 отчётов пересылается за окно (по умолчанию: 10)
windowMs: 10_000, // размер окна (по умолчанию: 10 с)
dedupWindowMs: 10_000, // подавлять идентичные повторы в этом окне (по умолчанию: windowMs)
onSuppressed: (error, { reason, count }) => {
// reason: 'dedup' | 'rate-limit'
},
internalErrorPrefix: '[vue-error-boundary-kit]', // страховочный лог, если onSuppressed/обёрнутый репортер выбрасывает ошибку; '' чтобы убрать
})«Идентичность» означает совпадение source + componentName + message. Это сам по себе ErrorReporter, поэтому он комбинируется со всем остальным — передавайте его туда же, куда и любой другой репортер.
Хлебные крошки
adapters/breadcrumbs — скользящее окно «того, что произошло до ошибки», автоматически прикрепляемое к отчётам. Ничего не инструментируется автоматически: вызывайте addBreadcrumb() сами оттуда, где у вас уже есть информация (хук роутера, обработчик клика, экшен стейт-менеджмента) — тот же opt-in дух, что и у useGlobalErrorCapture().
import { createBreadcrumbTrail, withBreadcrumbs } from 'vue-error-boundary-kit/adapters/breadcrumbs'
const trail = createBreadcrumbTrail({ limit: 20 })
router.afterEach((to) => {
trail.addBreadcrumb({ category: 'navigation', message: `→ ${to.fullPath}` })
})
const reporter = withBreadcrumbs(sentryReporter, { trail })<ErrorBoundary :reporter="[reporter, trail.record]">…</ErrorBoundary>createBreadcrumbTrail({ limit? })—entries(в хронологическом порядке, от старых к новым — в отличие отcreateErrorHistory(), где сначала самые новые, что соответствует тому, как хлебные крошки читаются как таймлайн в других местах),addBreadcrumb({ category, message, timestamp?, data? }),clear()иrecord— сам по себеErrorReporter, поэтому передача его вместе с настоящим репортером(ами) автоматически добавляет каждую перехваченную ошибку и в трейл тоже, а значит, хлебные крошки последующей ошибки включают более ранние.withBreadcrumbs(reporter, { trail, contextKey?, internalErrorPrefix? })— оборачивает любой репортер(ы) так, чтобыcontextкаждого вызоваreport()включал текущие записи трейла под ключомcontextKey(по умолчанию:'breadcrumbs').