言語を切り替える
テーマを切り替える

Next.js 本番環境モニタリング:エラー追跡、ログ、アラートの「守りの要」

「本番環境でエラーが出ているらしいですが、再現できません」
開発者として、これほど胃が痛くなる言葉はありません。

Next.js は「ブラウザ(Client)」「サーバー(Server)」「エッジ(Edge)」の3箇所でコードが動くため、従来よりもエラーの特定が困難です。サーバーサイドレンダリング(SSR)中に起きたエラーは、ユーザーには単なる「500 Internal Server Error」として表示され、ブラウザのコンソールには何も残りません。

私たちは盲目状態で戦うべきではありません。適切なモニタリングツールを導入すれば、「ユーザーがどのボタンを押した直後に、どんな変数の状態で、どの行でエラーが起きたか」が全て手に取るように分かります。

この記事では、私が本番環境で実際に採用している「Sentry + Pino + Slack」による鉄壁のモニタリング構成を紹介します。

なぜ Next.js の監視は特殊なのか?

従来の SPA(シングルページアプリケーション)なら、ブラウザのエラーさえ監視していれば9割はカバーできました。しかし Next.js は違います。

  1. サーバーサイドエラーの不可視性: getServerSideProps や Server Components、API Routes で起きたエラーはサーバー内で完結し、ブラウザには届きません。
  2. ハイドレーションエラー: サーバーとクライアントの HTML 不一致によるエラーは、Next.js 特有かつ頻発する問題です。
  3. Edge Runtime: Middleware などは Node.js ではなく Edge Runtime で動くため、一部のライブラリが動かず、特有のエラーを引き起こします。

これら全てを一元管理できるツールが必要です。そこでデファクトスタンダードとなっているのが Sentry です。

ステップ 1: Sentry の導入と設定

Sentry は Next.js 向けに専用の SDK を提供しており、導入は驚くほど簡単です。

npx @sentry/wizard@latest -i nextjs

このウィザードを実行すると、自動的に必要なファイル(sentry.client.config.ts, sentry.server.config.ts, sentry.edge.config.ts)を作成し、next.config.js を書き換えてソースマップのアップロード設定まで行ってくれます。

設定のポイント

ウィザード任せでも動きますが、本番運用のために以下の調整をお勧めします。

サンプリングレートの調整(コスト削減)
デフォルトでは全トランザクションを送信しますが、アクセス数が多いとすぐに無料枠を使い切ります。

// sentry.client.config.ts / server / edge 共通
Sentry.init({
  dsn: "YOUR_DSN",
  // 本番環境では 10% 程度に絞るのが一般的
  tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1.0,
  // エラーは全件送信(重要!)
  sampleRate: 1.0, 
});

機密情報の除外
ユーザーのパスワードや個人情報が誤って送信されないよう、サニタイズ設定を確認します。Sentry はデフォルトで優秀なフィルタリングを行いますが、念のため確認しましょう。

ステップ 2: 構造化ログ(Structured Logging)の導入

console.log("Error happened:", err) は卒業しましょう。テキスト形式のログは、集計も検索も困難です。
代わりに Pino を使って、JSON 形式でログを出力します。

npm install pino
// lib/logger.ts
import pino from 'pino';

export const logger = pino({
  level: process.env.LOG_LEVEL || 'info',
  // 開発時は読みやすい形式、本番はJSON
  transport: process.env.NODE_ENV !== 'production' 
    ? { target: 'pino-pretty' } 
    : undefined,
  base: {
    env: process.env.NODE_ENV,
  },
});

使い方:

import { logger } from '@/lib/logger';

export async function POST(req: Request) {
  try {
    // ...処理
    logger.info({ userId: user.id, action: 'create_post' }, '記事が作成されました');
  } catch (error) {
    logger.error({ err: error, userId: user.id }, '記事作成に失敗しました');
  }
}

これで、後から「userId: 123 のログだけ見たい」「エラーログだけ集計したい」といった操作が容易になります。Datadog や CloudWatch Logs と連携すれば完璧です。

Correlation ID(相関ID)でリクエストを追跡

マイクロサービスやサーバーレス環境では、1つのリクエストが複数の処理をまたぐため、ログを紐付ける魔法の鍵が必要です。それが Correlation ID です。

Middleware で生成し、ヘッダーに付与して引き回します。

// middleware.ts
import { NextResponse } from 'next/server';
import { v4 as uuidv4 } from 'uuid';

export function middleware(request: Request) {
  const requestHeaders = new Headers(request.headers);
  const correlationId = uuidv4();
  requestHeaders.set('x-correlation-id', correlationId);

  const response = NextResponse.next({
    request: { headers: requestHeaders },
  });
  response.headers.set('x-correlation-id', correlationId);
  return response;
}

ログ出力時にこの ID を含めれば、特定のリクエストの一連の流れ(Middleware → API → DB)を完全に追跡できます。

ステップ 3: アラート戦略(Slack 通知)

エラーを収集しても、気づかなければ意味がありません。しかし、全部通知すると「通知疲れ(Alert Fatigue)」で誰も見なくなります。

以下のような 区分け(Triage) を推奨します。

レベル内容通知先対応期限
P0 (Critical)サイトダウン、決済失敗、主要機能の停止Slack #incident + 電話即時
P1 (High)特定ユーザーで発生するエラー、重要でない機能の停止Slack #dev-alerts4時間以内
P2 (Medium)軽微な表示崩れ、稀なエッジケースメールレポート今週中
P3 (Low)警告、非推奨APIの使用通知なし(ダッシュボード確認)余裕があれば

Sentry の “Alert Rules” でこれらのルールを設定し、Slack の対応チャンネルに振り分けましょう。

まとめ:守りの要

モニタリングは、エンジニアにとっての「保険」であり「目」です。
これらを設定しておけば、ユーザーからの問い合わせが来たとき、「少々お待ちください」と言ってログを確認し、「ああ、決済サーバーがタイムアウトしていますね」と即座に回答できます。この信頼感は何物にも代えがたいものです。

  1. Sentry で全方位のエラーを捕捉する。
  2. Pino で検索可能なログを残す。
  3. Correlation ID で処理の流れを追う。
  4. Slack に適切な粒度で通知する。

この4ステップで、あなたの Next.js アプリケーションは「眠れる」システムになります。

Next.js 本番環境モニタリング構築フロー

Sentry の導入からログ設計、アラート設定までのステップバイステップガイド

⏱️ Estimated time: 30 min

  1. 1

    Step1: Sentry のセットアップ

    `npx @sentry/wizard@latest -i nextjs` を実行し、ウィザードに従ってプロジェクトを設定します。これによりクライアント、サーバー、エッジすべての環境監視が有効になります。
  2. 2

    Step2: ソースマップのアップロード確認

    ビルドプロセス(`next build`)で Sentry へのソースマップアップロードが成功しているか確認します。これがないと本番環境のエラーログが解読できません。
  3. 3

    Step3: 構造化ログライブラリの導入

    Pino 等のロガーを導入し、開発環境では読みやすく(pretty print)、本番環境では JSON 形式で出力するように `lib/logger.ts` を構成します。
  4. 4

    Step4: Correlation ID の実装

    Middleware でリクエスト毎に UUID を生成し、ヘッダーに付与します。ロガーにもこの ID を渡すことで、ログの追跡性を確保します。
  5. 5

    Step5: アラート通知ルールの設定

    Sentry の管理画面で、クリティカルなエラーのみを Slack 等に通知するルールを作成します。ノイズを減らすことが持続可能な運用の鍵です。

FAQ

Sentry のパフォーマンスへの影響はありますか?
バンドルサイズは若干増えますが(数十KB程度)、遅延ロードや非同期送信により、ユーザー体験への影響は最小限に抑えられています。気になる場合は `tracesSampleRate` を調整して送信量を減らすことができます。
console.log をそのまま使ってはいけませんか?
開発中は問題ありませんが、本番環境では推奨されません。標準出力されたテキストログは検索や解析が難しく、ログレベル(Info, Error等)の制御も柔軟にできないためです。
個人情報の扱いはどうすればいいですか?
Sentry の `beforeSend` フックや `Data Scrubber` 設定を使用して、メールアドレス、クレジットカード番号、パスワードなどの機密情報が送信される前にマスク(伏せ字化)する設定を必ず行ってください。
エラー通知が多すぎて困っています。
「既知のエラー」や「対応不要な警告」は Sentry 側で「Ignore(無視)」設定にするか、通知ルールの閾値(例:1時間に10回以上発生したら通知)を調整してください。

4 min read · 公開日: 2025年12月20日 · 更新日: 2026年1月22日

コメント

GitHubアカウントでログインしてコメントできます

関連記事