SCALE — Build Lab
開発パターン · CLOUDFLARE FUNCTION

クライアントエラー記録 API

CATEGORY開発パターン TYPECloudflare Function EFFORT30〜60分 DIFFICULTY
PRIMARY CODE
ts · scale-crm:functions/api/error.ts
// POST /api/error → クライアントエラー収集
import { corsResponse, corsError, handleOptions } from '../_lib/cors';

interface Env { DB: D1Database }

export const onRequestOptions = () => handleOptions();

export const onRequestPost: PagesFunction<Env> = async ({ request, env }) => {
  try {
    const body = await request.json().catch(() => ({})) as any;
    const user = (() => {
      const raw = request.headers.get('X-User') || body.user || 'unknown';
      try { return decodeURIComponent(raw); } catch { return raw; }
    })();
    const ua = request.headers.get('User-Agent') || '';
    await env.DB.prepare(
      'INSERT INTO error_log (occurred_at, user, url, message, stack, ua) VALUES (?, ?, ?, ?, ?, ?)'
    ).bind(
      new Date().toISOString(),
      user,
      String(body.url || '').slice(0, 500),
      String(body.message || 'unknown').slice(0, 1000),
      String(body.stack || '').slice(0, 4000),
      ua.slice(0, 300)
    ).run();
    return corsResponse({ ok: true });
  } catch (e: any) {
    return corsError(e.message);
  }
};

前提条件
Tailwind CSS v4TypeScript 5
USE CASES
  • 本番運用システム全般

クライアントエラー記録 API

:LiTarget: 用途

クライアント側で発生した JS エラーをサーバ側に記録。ユーザー環境のバグ把握に。

:LiSparkle: 特徴

  • POST /api/error
  • エラー文字列・スタック保存
  • タイムスタンプ
  • D1記録

:LiCode: 実コード(SCALE Base より自動抽出)

:LiInfo: scale-crm:functions/api/error.ts の中身そのもの。コピペ即可。

// POST /api/error → クライアントエラー収集
import { corsResponse, corsError, handleOptions } from '../_lib/cors';

interface Env { DB: D1Database }

export const onRequestOptions = () => handleOptions();

export const onRequestPost: PagesFunction<Env> = async ({ request, env }) => {
  try {
    const body = await request.json().catch(() => ({})) as any;
    const user = (() => {
      const raw = request.headers.get('X-User') || body.user || 'unknown';
      try { return decodeURIComponent(raw); } catch { return raw; }
    })();
    const ua = request.headers.get('User-Agent') || '';
    await env.DB.prepare(
      'INSERT INTO error_log (occurred_at, user, url, message, stack, ua) VALUES (?, ?, ?, ?, ?, ?)'
    ).bind(
      new Date().toISOString(),
      user,
      String(body.url || '').slice(0, 500),
      String(body.message || 'unknown').slice(0, 1000),
      String(body.stack || '').slice(0, 4000),
      ua.slice(0, 300)
    ).run();
    return corsResponse({ ok: true });
  } catch (e: any) {
    return corsError(e.message);
  }
};

:LiFolder: ソースファイルのパス

/Users/oogushiyuuki/株式会社SCALE/scale-lead/functions/api/error.ts

:LiHandPointer: 使い方

対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。

:LiAlertCircle: 注意事項

  • 依存パッケージを忘れず追加