🐾

NestJS から Rollbar に自動的にエラーを投げる

2024/02/01に公開

ライフイズテック株式会社 サービス開発部の山口 (@no_clock) です。塾プロダクトグループでソフトウェアエンジニアをしています。

今回は、 Node.js の Web アプリケーションフレームワーク NestJS でエラートラッキングサービス Rollbar を使うときの小ネタです。

Express 向けのエラー処理ミドルウェアは使えない

発生したエラーを自動的に Rollbar へ送信したいとき。 Rollbar のドキュメントには、 Express での設定方法が記載されています。

app.use(rollbar.errorHandler());

NestJS の Middleware のドキュメントには "equivalent to express middleware" とあり、これがそのまま使えそうに感じます。しかし、 NestJS には別途 Exception filters が用意されていて、残念ながら Express 向けのエラー処理ミドルウェアは機能しません。

Exception filter でエラーを投げる

NestJS では、先ほど出てきた Exception filters の仕組みを使用します。ポイントは 2 点です。

  • useGlobalFilters で全体に適用できる
  • HTTP ステータスコード 4xx 番台もキャッチされ流れてくるため、不要なものは除外する
    • @HttpCode アノテーションでは流れてきませんが、 Built-in HTTP exceptions を使うと流れてきます
rollbar-exception-filter.ts
import { ArgumentsHost, Catch, HttpServer } from '@nestjs/common'
import { BaseExceptionFilter } from '@nestjs/core'
import { ROLLBAR_ACCESS_TOKEN, ROLLBAR_ENVIRONMENT } from 'env'
import { Request, Response } from 'express'
import Rollbar from 'rollbar'

@Catch()
export class RollbarExceptionFilter extends BaseExceptionFilter {
  constructor(
    applicationRef: HttpServer,
    private rollbar: Rollbar,
  ) {
    super(applicationRef)
  }

  catch(error: Error, host: ArgumentsHost) {
    super.catch(error, host)

    const ctx = host.switchToHttp()
    const request = ctx.getRequest<Request>()
    const response = ctx.getResponse<Response>()

    if (response.statusCode === 401 || response.statusCode === 404) {
      return
    }

    this.rollbar.error(error, request)
  }
}

export const useRollbar = () => !!ROLLBAR_ACCESS_TOKEN && !!ROLLBAR_ENVIRONMENT

export const getRollbarExceptionFilter = (httpAdapter: HttpServer) => {
  const rollbar = new Rollbar({
    accessToken: ROLLBAR_ACCESS_TOKEN,
    environment: ROLLBAR_ENVIRONMENT,
  })

  return new RollbarExceptionFilter(httpAdapter, rollbar)
}
main.ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule)
  const { httpAdapter } = app.get(HttpAdapterHost)
  if (useRollbar()) {
    app.useGlobalFilters(generateRollbarExceptionFilter(httpAdapter))
  }
(以下略)

試す

適当な箇所に throw new Error() とか throw new ImATeapotException() とか書いて試すと、 Rollbar に送信されるか確認ができます。

Rollbar にキャッチされた  のエラー

参考


宣伝

ライフイズテック サービス開発部では、気軽にご参加いただけるカジュアルなイベントを実施しています。開催予定のイベントは、 connpass のライフイズテックグループからご確認ください!

Discussion