Next.js ile Kütüphane Kullanmadan Loglama Sistemi
Loglama, uygulamanın davranışlarını izlemek, hataları anlamak ve performansı ölçmek için kritik bir araçtır. Üç temel amaca hizmet eder:
- Debugging: Hataları bulmak ve çözmek,
- Monitoring: Uygulamanın nasıl çalıştığını gözlemlemek,
- Auditing: Kullanıcı aktivitelerini ve sistem olaylarını kayetmek.
Çoğu projede winston, pino, sentry gibi profesyonel paketler kullanılır. Ancak bazı durumlarda:
- Performans kontrolü tamamen sende olsun,
- Log formatı %100 sana özel olsun,
- Bağımlılık istemiyorum,
diyorsan bu makalemde yazdığım sistem sizlere mükemmel bir çözüm olacağını düşünüyorum.
Not: Bu loglama sisteminde veritabanına kayıt işlemi yapacağım için sequelize ORM aracını baz alarak yazmaya çalıştım.
1. Sequelize Modeli Tasarımı
/lib/models/log.ts
import {
Model,
DataTypes,
InferAttributes,
InferCreationAttributes,
CreationOptional
} from "sequelize";
import { sequelize } from "@/lib/sequelize";
export class Log extends Model<
InferAttributes<Log>,
InferCreationAttributes<Log>
> {
declare id: CreationOptional<number>;
declare level: "info" | "warn" | "error";
declare message: string;
declare method: string;
declare path: string;
declare ip: string | null;
declare userAgent: string | null;
declare requestBody: object | null;
declare responseStatus: number | null;
declare createdAt: CreationOptional<Date>;
}
Log.init(
{
id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true },
level: { type: DataTypes.STRING },
message: { type: DataTypes.TEXT },
method: { type: DataTypes.STRING },
path: { type: DataTypes.STRING },
ip: { type: DataTypes.STRING },
userAgent: { type: DataTypes.TEXT },
requestBody: { type: DataTypes.JSON },
responseStatus: { type: DataTypes.INTEGER },
createdAt: DataTypes.DATE
},
{
sequelize,
tableName: "logs",
updatedAt: false
}
);
2. Core Logger Fonksiyonu
Bu yapı, heryerden çağrılabilir bir yapıda olacaktır.
/lib/logger.ts
import { Log } from "@/lib/models/Log";
type LogLevel = "info" | "warn" | "error";
interface LoggerPayload {
level: LogLevel;
message: string;
method: string;
path: string;
ip?: string | null;
userAgent?: string | null;
requestBody?: object | null;
responseStatus?: number | null;
}
export async function logger(payload: LoggerPayload) {
try {
await Log.create({
level: payload.level,
message: payload.message,
method: payload.method,
path: payload.path,
ip: payload.ip ?? null,
userAgent: payload.userAgent ?? null,
requestBody: payload.requestBody ?? null,
responseStatus: payload.responseStatus ?? null
});
} catch (err) {
// Loglama hatası uygulamayı patlatmamalı
console.error("LOG ERROR:", err);
}
}
3. API Route İçinde Loglama İşlemi (App Router)
import { NextRequest, NextResponse } from "next/server";
import { logger } from "@/lib/logger";
export async function POST(req: NextRequest) {
const body = await req.json();
const userAgent = req.headers.get("user-agent");
const ip = req.headers.get("x-forwarded-for");
try {
// iş mantığı
if (!body.email) {
throw new Error("Email zorunlu");
}
await logger({
level: "info",
message: "Kullanıcı kayıt isteği başarılı",
method: "POST",
path: "/api/example",
ip,
userAgent,
requestBody: body,
responseStatus: 200
});
return NextResponse.json({ ok: true });
} catch (error: any) {
await logger({
level: "error",
message: error.message,
method: "POST",
path: "/api/example",
ip,
userAgent,
requestBody: body,
responseStatus: 400
});
return NextResponse.json(
{ error: error.message },
{ status: 400 }
);
}
}
4. Log Level Stratejisi
| Level | Ne Zaman |
|---|---|
| info | Başarılı durum |
| warn | Beklenmeyen ama hataya düşmeyen durum |
| error | Exception / Validation fail |
5. Bu Sistemin Avantajları
- Ek paket yok,
- Tümüyle kontrol sizde,
- Kolayca test edilebilir,
- Sequelize ile birebir uyumlu.
Sonuç
Bu makalemde, Next.js App Router ile hiçbir loglama paketi kullanmadan, Sequelize ORM uyumlu, profesyonel seviyede ve genişletilebilir loglama sistemi kurmuş olduk.