JavaScript Tips | ログ・デバッグ・エラー処理:開発者向けエラー情報を生成する

JavaScript JavaScript
スポンサーリンク
スポンサーリンク

開発者向けエラー情報生成は「障害原因を最速で特定するための“深い技術情報”を整形して届ける技術」

ユーザー向けエラーメッセージは「分かりやすさ」が目的ですが、 開発者向けエラー情報は “原因を特定するための詳細情報” が目的 です。

業務システムでは、次のような場面で開発者向けエラー情報が必須になります。

  • 本番環境で障害が発生し、ログから原因を特定したい
  • 監視ツール(Sentry、Datadog、CloudWatch)に送信したい
  • API やバッチ処理の内部状態を確認したい
  • エラーコード・スタックトレース・追加情報をまとめて記録したい

初心者がやりがちなミスは次のとおりです。

  • Error をそのままログに出してしまう
  • スタックトレースが欠落する
  • 追加情報(APIレスポンス、入力値)が記録されない
  • ログ形式がバラバラで調査が難しい

ここでは、開発者向けエラー情報を 構造化 → 整形 → 出力 → 監視ツール連携 までステップバイステップで解説します。

開発者向けエラー情報の目的は「原因を最速で特定すること」

開発者向けエラー情報は、次のような情報を含むべきです。

  • エラーコード(分類のため)
  • エラーメッセージ(概要)
  • スタックトレース(どこで発生したか)
  • 追加情報(APIレスポンス、入力値、環境情報など)
  • 発生コンテキスト(どの処理で起きたか)
  • タイムスタンプ(いつ起きたか)

これらをまとめて構造化することで、 障害調査のスピードが劇的に向上します。

ステップ1:エラーコードを定義する(分類の基盤)

export const ErrorCodes = {
  API_TIMEOUT: "API-002",
  DB_QUERY_FAILED: "DB-002",
  AUTH_TOKEN_EXPIRED: "AUTH-001",
  SYS_UNKNOWN: "SYS-001",
};
JavaScript

ステップ2:開発者向けエラー情報を保持できる Error クラスを作る

class AppError extends Error {
  constructor(code, message, extra = {}) {
    super(message);
    this.code = code;
    Object.assign(this, extra);
  }
}
JavaScript

使用例

throw new AppError(ErrorCodes.API_TIMEOUT, "API timeout", {
  endpoint: "/api/user",
  retryCount: 3,
});
JavaScript

ステップ3:開発者向けエラー情報を整形する(最重要)

開発者向け情報は「構造化された JSON」が最も扱いやすいです。

function formatDevError(error, context = "") {
  return {
    timestamp: new Date().toISOString(),
    context,
    code: error.code || ErrorCodes.SYS_UNKNOWN,
    name: error.name,
    message: error.message,
    stack: error.stack,
    extra: Object.keys(error).reduce((acc, key) => {
      if (!["code", "name", "message", "stack"].includes(key)) {
        acc[key] = error[key];
      }
      return acc;
    }, {}),
  };
}
JavaScript

ステップ4:開発者向けエラー情報をログに出す

function logDevError(error, context = "") {
  const formatted = formatDevError(error, context);
  console.error("[DEV ERROR]", formatted);
}
JavaScript

ステップ5:開発者向けエラー情報を「レポート形式」にする(読みやすさ向上)

function buildDevErrorReport(error, context = "") {
  const f = formatDevError(error, context);

  return `
=== DEV ERROR REPORT ===
Timestamp: ${f.timestamp}
Context: ${f.context}
Code: ${f.code}
Name: ${f.name}
Message: ${f.message}

Extra:
${JSON.stringify(f.extra, null, 2)}

Stack:
${f.stack}
========================
  `.trim();
}
JavaScript

ステップ6:監視ツールに送信するための JSON を生成する

function toMonitoringPayload(error, context = "") {
  return formatDevError(error, context);
}
JavaScript

監視ツールは JSON を前提にしているため、 この形式が最も扱いやすいです。

ステップ7:業務で使える開発者向けエラー情報ユーティリティ(完成版)

export const DevErrorUtil = {
  format(error, context = "") {
    return {
      timestamp: new Date().toISOString(),
      context,
      code: error.code || ErrorCodes.SYS_UNKNOWN,
      name: error.name,
      message: error.message,
      stack: error.stack,
      extra: Object.keys(error).reduce((acc, key) => {
        if (!["code", "name", "message", "stack"].includes(key)) {
          acc[key] = error[key];
        }
        return acc;
      }, {}),
    };
  },

  log(error, context = "") {
    console.error("[DEV ERROR]", this.format(error, context));
  },

  report(error, context = "") {
    const f = this.format(error, context);
    return `
=== DEV ERROR REPORT ===
Timestamp: ${f.timestamp}
Context: ${f.context}
Code: ${f.code}
Name: ${f.name}
Message: ${f.message}

Extra:
${JSON.stringify(f.extra, null, 2)}

Stack:
${f.stack}
========================
    `.trim();
  },

  toMonitoringPayload(error, context = "") {
    return this.format(error, context);
  },
};
JavaScript

ステップ8:業務での活用例

API 呼び出しでの障害調査

try {
  await fetch("/api/user");
} catch (e) {
  const err = new AppError(ErrorCodes.API_TIMEOUT, "API timeout", {
    endpoint: "/api/user",
    retryCount: 2,
  });

  DevErrorUtil.log(err, "UserAPI");
}
JavaScript

DB エラーの詳細ログ

try {
  db.query("SELECT * FROM users");
} catch (e) {
  const err = new AppError(ErrorCodes.DB_QUERY_FAILED, "DB query failed", {
    query: "SELECT * FROM users",
  });

  console.error(DevErrorUtil.report(err, "DBQuery"));
}
JavaScript

監視ツールへの送信

sendToMonitoring(DevErrorUtil.toMonitoringPayload(err, "PaymentService"));
JavaScript

深掘り:開発者向けエラー情報が重要な理由

1. 障害調査のスピードが劇的に向上する

スタックトレース+追加情報が揃っていると、 原因特定が数分で終わることもあります。

2. 再現が難しい本番障害でも情報が残る

本番環境では再現できない障害が多いため、 詳細ログが唯一の手がかりになります。

3. 監視ツールとの連携が容易になる

JSON 形式ならそのまま送信できます。

4. チーム全体で統一されたログ形式になる

属人化を防ぎ、品質が向上します。

5. ユーザー向けメッセージと分離できる

ユーザーには簡潔なメッセージ、 開発者には詳細情報という設計が可能です。

まとめ:開発者向けエラー情報生成は「障害原因を最速で特定するための基盤技術」

開発者向けエラー情報を正しく扱うことで、次のメリットが得られます。

  • 原因特定が高速化する
  • 本番障害の調査が容易になる
  • ログ形式が統一される
  • 監視ツールとの連携が簡単になる
  • ユーザー向けメッセージと分離できる

エラーコード管理・エラー整形・JSON 化と組み合わせることで、 業務システムの品質が劇的に向上します。

タイトルとURLをコピーしました