SvelteKit with Sentry

こんにちは、こんばんは、久保田です。

この記事ではSvelteKitにSentryを導入する方法を紹介します。

Sentryってなに?

詳細は割愛します。ざっくりいうとアプリケーションのエラーを集約するSaaSです。
詳しくはサイトなり別途解説された記事を参照ください。

Application Performance Monitoring & Error Tracking Software | Sentry

2023/07/18 更新

Sentryから公式にSvelteKitに対応するライブラリが提供されていました。
こちらの記事の内容は古くなっていますので以下の公式ライブラリでの利用を推奨します。
※弊社もこちらに切り替えました。

docs.sentry.io

SvelteKitにSentryを導入する

まず、SvelteKitでSentryを導入する際に気をつける点があります。
それは、「SSR時のエラーか、CSR時のエラーか」ということです。
SvelteKitはSSR(サーバーサイドレンダリング)できるフレームワークですので、サーバーでNode.jsによって実行されるランタイムがあります。
また、SSRされた後配信されたHTMLとJSによってブラウザで実行されるCSR(クライアントサイドレンダリング)のランタイムがあります。
ですので以下の状況のエラーを捕捉する必要があります。

  • サーバーでエラーが発生した場合
  • クライアントブラウザでエラーが発生した場合

それではそれぞれのエラーをSentryで捕捉できるようにしていきます。

導入

まずはSentryのライブラリを導入します。 導入するのは次の6つです

  • @sentry/browser
  • @sentry/integrations
  • @sentry/node
  • @sentry/svelte
  • @sentry/tracing
  • vite-plugin-sentry

npmの場合は以下のようにインストールしてください。

npm install -S @sentry/browser @sentry/integrations @sentry/node @sentry/svelte @sentry/tracing vite-plugin-sentry

ビルド時にSentryへmapファイルを送るためのViteプラグインが用意されているので設定します。

vite.config.(js|ts)

import viteSentry from 'vite-plugin-sentry'

// 略

plugins: [
    sveltekit(),
    viteSentry({
      url: 'https://sentry.io',
      authToken: process.env.SENTRY_AUTH_TOKEN,
      org: 'ma-cloud',
      project: 'yell-front',
      release: process.env.VITE_SENTRY_RELEASE,
      deploy: {
        env: env.mode
      },
      setCommits: {
        auto: true
      },
      sourceMaps: {
        include: ['./build/client/', './build/server/'],
        ignore: ['node_modules']
      }
    }),
],
// 略

サーバーエラーの捕捉

SvelteKitはサーバーで処理される際のミドルウェアのようにリクエスト処理とレスポンス処理を挟み込んだ処理を書くことができます。 それがhooksです。

Hooks • Docs • SvelteKit

hooks.server.(js|ts)を作成し、エラーハンドラでSentryのライブラリが起動されるように設定します。

import type { HandleServerError } from '@sveltejs/kit'
import * as Sentry from '@sentry/node'
import { RewriteFrames } from '@sentry/integrations'

if (import.meta.env.VITE_SENTRY_DSN) {
  Sentry.init({
    dsn: import.meta.env.VITE_SENTRY_DSN,
    tracesSampleRate: 0.01,
    environment: import.meta.env.VITE_ENVIRONMENT,
    release: import.meta.env.VITE_SENTRY_RELEASE,
    integrations: [new RewriteFrames({ root: '/var/www/yell-front/build/server/' })]
  })
}

export const handleError: HandleServerError = ({ error, event }) => {
  if (!(error instanceof Error)) {
    return
  }
  Sentry.captureException(error, {
    extra: { event: event },
    tags: { ssr: true, ip: event.getClientAddress(), errorId }
  })
  return {
    message: 'Whoops!' // 適宜変えてください
  }
}

クライアントエラーの捕捉

こちらもhooksが利用できます。 hooks.client.(js|ts)を利用することでクライアントブラウザでのエラーハンドラを利用することができます。

import type { HandleClientError } from '@sveltejs/kit'
import * as Sentry from '@sentry/svelte'
import { BrowserTracing } from '@sentry/tracing'

if (import.meta.env.VITE_SENTRY_DSN) {
  Sentry.init({
    dsn: import.meta.env.VITE_SENTRY_DSN,
    tracesSampleRate: 0.01,
    environment: import.meta.env.VITE_ENVIRONMENT,
    release: import.meta.env.VITE_SENTRY_RELEASE,
    integrations: [new BrowserTracing()]
  })
}

export const handleError: HandleClientError = ({ error, event }) => {
  Sentry.captureException(error, {
    extra: { event: event }
  })
  return {
    message: 'Whoops!' // 適宜変えてください
  }
}

サーバーもクライアントも共通してhandleErrorでエラーを捕捉することができるので同じような記述で対応することができます。
SvelteKitではどちらのエラーもhooksに集約できるので見通しよく管理ができて良いですね。