В современном вебе надёжная обработка ошибок критична для UX и бизнес‑аналитики. Если вы используете Vue 3 и Pinia, то можно создать глобальный error handler, который автоматически перехватывает любые исключения, сохраняет их в Pinia и отправляет в Sentry для дальнейшего анализа. Это решение обеспечивает единый поток ошибок, упрощает отладку и повышает надёжность приложения. В этой статье мы разберём, как реализовать такой механизм, шаг за шагом.

Разбор задачи

В Vue 3 ошибки могут возникнуть в шаблонах, хуках, методах компонентов, а также в асинхронных задачах. Если не обрабатывать их централизованно, то пользователь видит непонятные сообщения, а разработчик теряет контекст. Pinia удобно использовать как хранилище для ошибок, позволяя легко отобразить их в UI или экспортировать. Sentry, в свою очередь, обеспечивает мощный бекенд для агрегации, алёртов и трассировки. Комбинируя эти инструменты, мы получаем полноценную систему мониторинга.

Пошаговое решение

1. Создаём глобальный error handler в main.js, используя app.config.errorHandler. 2. Внутри обработчика сохраняем ошибку в Pinia store, добавляя поля: сообщение, стэк, метаданные и timestamp. 3. Далее, если Sentry подключён, отправляем событие через sentry.captureException. 4. Для отладки можно вывести ошибку в консоль и добавить пользовательский UI‑компонент, который читает store и показывает список ошибок в таблице. 5. Не забудьте настроить фильтрацию, чтобы не дублировать ошибки и не отправлять уже игнорируемые события. 6. Тестируем: генерируем ошибки в разных местах и проверяем, что они попадают в Pinia и Sentry. Это простая, но надёжная интеграция, которую можно масштабировать, добавляя роли пользователей, уровни логирования и периодическую очистку старых записей.

Рабочий код

import { createApp } from 'vue'
import { createPinia, defineStore } from 'pinia'
import * as Sentry from '@sentry/vue'
import { Integrations } from '@sentry/tracing'

// 1️⃣ Инициализируем Pinia
const pinia = createPinia()

// 2️⃣ Создаём store с глобальным обработчиком ошибок
const useErrorStore = defineStore('error', {
  state: () => ({ errors: [] }),
  actions: {
    addError(err) {
      this.errors.push(err)
      // Отправляем в Sentry
      Sentry.captureException(err)
    }
  }
})

// 3️⃣ Настраиваем глобальный обработчик ошибок Vue
const app = createApp(App)
app.use(pinia)
app.use(Sentry, {
  dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0',
  integrations: [new Integrations.BrowserTracing()],
  tracesSampleRate: 1.0,
  beforeSend(event, hint) {
    // Пример фильтрации незначительных ошибок
    if (hint.originalException?.message?.includes('Ignored')) {
      return null
    }
    return event
  }
})
app.config.errorHandler = (err, instance, info) => {
  const errorStore = useErrorStore()
  errorStore.addError({ message: err.message, info, instance })
}
app.mount('#app')

Типичные ошибки

  • Не подключён Pinia до создания store – приводит к ошибке «pinia is not installed».
  • Синтаксическая ошибка в beforeSend: возвращён null без проверки, может блокировать отправку.
  • Отсутствует обработка асинхронных ошибок из промисов – они попадают в глобальный handler только при .catch.

FAQ

В чем разница между app.config.errorHandler и Vue.config.errorHandler?

app.config.errorHandler применяет только к текущему приложению, Vue.config.errorHandler глобален для всех инстанций Vue.

Можно ли отключить Sentry для определённого store?

Да, просто не вызывать Sentry.captureException в нужных действиях или использовать условие внутри addError.

Как отлавливать ошибки из async/await?

Оберните async функции в try/catch и передавайте err в global handler либо в store. Vue 3 автоматически ловит ошибки из render‑функций, но async/await нужно обрабатывать вручную.

Заключение и чек‑лист

  • Pinia подключена до создания store.
  • Глобальный errorHandler определён после use(Sentry).
  • Sentry настроен с DSN и beforeSend.
  • Store содержит метод addError, который записывает и отправляет в Sentry.
  • Проверены типичные ошибки: синтаксис, async‑помехи, фильтрация.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *