Initial commit
This commit is contained in:
98
lib/middleware/api-logger.ts
Normal file
98
lib/middleware/api-logger.ts
Normal file
@ -0,0 +1,98 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { logger } from "../utils/logger";
|
||||
|
||||
export interface ApiLoggerOptions {
|
||||
logRequests?: boolean;
|
||||
logResponses?: boolean;
|
||||
logErrors?: boolean;
|
||||
excludePaths?: string[];
|
||||
}
|
||||
|
||||
export class ApiLogger {
|
||||
static async logRequest(
|
||||
request: NextRequest,
|
||||
response: NextResponse,
|
||||
duration: number,
|
||||
options: ApiLoggerOptions = {}
|
||||
): Promise<void> {
|
||||
const {
|
||||
logRequests = true,
|
||||
logResponses = true,
|
||||
logErrors = true,
|
||||
excludePaths = [],
|
||||
} = options;
|
||||
|
||||
const url = new URL(request.url);
|
||||
const path = url.pathname;
|
||||
|
||||
// 跳过排除的路径
|
||||
if (excludePaths.some((excludePath) => path.startsWith(excludePath))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const method = request.method;
|
||||
const statusCode = response.status;
|
||||
const userAgent = request.headers.get("user-agent") || "Unknown";
|
||||
const ip =
|
||||
request.headers.get("x-forwarded-for") ||
|
||||
request.headers.get("x-real-ip") ||
|
||||
"Unknown";
|
||||
|
||||
// 记录请求
|
||||
if (logRequests) {
|
||||
logger.logApiRequest(method, path, statusCode, duration);
|
||||
}
|
||||
|
||||
// 记录错误
|
||||
if (logErrors && statusCode >= 400) {
|
||||
logger.error("API Error", {
|
||||
method,
|
||||
path,
|
||||
statusCode,
|
||||
duration,
|
||||
userAgent,
|
||||
ip,
|
||||
});
|
||||
}
|
||||
|
||||
// 记录响应统计
|
||||
if (logResponses) {
|
||||
logger.info("API Response", {
|
||||
method,
|
||||
path,
|
||||
statusCode,
|
||||
duration,
|
||||
userAgent,
|
||||
ip,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static createMiddleware(options: ApiLoggerOptions = {}) {
|
||||
return async (
|
||||
request: NextRequest,
|
||||
handler: () => Promise<NextResponse>
|
||||
) => {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
const response = await handler();
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
await this.logRequest(request, response, duration, options);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
const errorResponse = NextResponse.json(
|
||||
{ error: "Internal Server Error" },
|
||||
{ status: 500 }
|
||||
);
|
||||
|
||||
await this.logRequest(request, errorResponse, duration, options);
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user