You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js+Supabase中记录API调用并存储到数据库?

在Supabase + Next.js中实现API调用记录功能

需求说明

需要将所有API调用按如下格式存储到Supabase数据库:

// api_path, called_at, called_by
"https://www.test.com/api/create_user",server.now(),"1"
"https://www.test.com/api/create_user",server.now(),"1"
"https://www.test.com/api/delete_user",server.now(),"1"
"https://www.test.com/api/analyze_user",server.now(),"1"

其中called_at为记录添加时的服务器时间,called_by为调用用户ID,比如示例中用户ID为1的用户多次调用不同API。

实现方案

1. 创建Supabase日志表

先在Supabase后台创建用于存储API调用记录的数据表,命名为api_call_logs:

CREATE TABLE api_call_logs (
  id SERIAL PRIMARY KEY,
  api_path TEXT NOT NULL,
  called_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  called_by TEXT NOT NULL
);

这里将called_at的默认值设为NOW(),插入数据时无需手动传值,数据库会自动填充服务器当前时间。

2. 封装通用日志记录函数

在Next.js项目中创建工具函数utils/logApiCall.js,统一处理日志写入逻辑:

import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL,
  process.env.SUPABASE_SERVICE_ROLE_KEY
);

export async function logApiCall(apiPath, userId) {
  try {
    await supabase
      .from('api_call_logs')
      .insert({ api_path: apiPath, called_by: userId });
  } catch (err) {
    console.error('API日志写入失败:', err);
  }
}

注意使用服务角色密钥(SUPABASE_SERVICE_ROLE_KEY)绕过Row Level Security(RLS)限制,确保日志能正常写入。

3. 在API路由中添加日志记录

在每个需要监控的API路由文件中,引入并调用日志函数。比如pages/api/create_user.js:

import { logApiCall } from '../../utils/logApiCall';

export default async function handler(req, res) {
  // 根据你的认证方式获取用户ID,示例从已认证的请求对象中获取
  const userId = req.user?.id;
  const apiPath = `${req.headers.origin}${req.url}`;

  // 异步记录日志,不阻塞业务逻辑
  logApiCall(apiPath, userId);

  // 处理你的核心业务逻辑
  // ...

  res.status(200).json({ success: true });
}

4. 用中间件统一拦截(可选)

如果不想逐个修改API路由,可以用Next.js中间件自动拦截所有API请求并记录日志,创建pages/_middleware.js:

import { NextResponse } from 'next/server';
import { logApiCall } from '../utils/logApiCall';

export async function middleware(req) {
  // 仅拦截/api开头的请求
  if (req.nextUrl.pathname.startsWith('/api/')) {
    // 根据你的认证方案获取用户ID,示例从Cookie中读取
    const userId = req.cookies.get('user_id')?.value || 'anonymous';
    const apiPath = `${req.nextUrl.origin}${req.nextUrl.pathname}`;

    // 异步执行日志记录,避免阻塞请求
    logApiCall(apiPath, userId).catch(err => console.error(err));
  }

  return NextResponse.next();
}

注意事项

  • 服务角色密钥仅能在服务器端使用,绝对不能暴露在客户端代码中。
  • 若存在未认证用户调用API的场景,可将called_by字段设为可选,或用anonymous作为默认值。
  • 日志记录逻辑建议异步执行,避免因数据库写入延迟影响API响应速度。

内容的提问来源于stack exchange,提问作者mmvergara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 06:20:47