Structured Logging
Structured logging adalah teknik menulis log dalam format yang terstruktur (biasanya JSON) agar mudah dicari, difilter, dan dianalisis — terutama saat ada ribuan log dari banyak server.
Masalah dengan console.log Biasa
// ❌ Unstructured log — susah di-parse dan dicari
console.log("User login failed for [email protected] at 2024-01-15 10:30");
console.log("Retry attempt 3 for request to /api/orders");
console.log("Payment processed: 150000 IDR");
Dengan log seperti ini, jika ingin mencari semua kegagalan login user tertentu di production dengan ribuan request — hampir mustahil.
Structured Log Format
// ✅ Structured log — mudah dicari dan dianalisis
{
"level": "warn",
"timestamp": "2024-01-15T10:30:00.000Z",
"context": "auth",
"message": "Login failed",
"userId": null,
"email": "[email protected]",
"reason": "invalid_password",
"attempt": 3,
"ip": "192.168.1.1"
}
Membuat Logger Sederhana
const LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3, fatal: 4 };
function createLogger(context, minLevel = "info") {
function log(level, message, meta = {}) {
if (LOG_LEVELS[level] < LOG_LEVELS[minLevel]) return;
const entry = {
level,
timestamp: new Date().toISOString(),
context,
message,
...meta,
};
// Output JSON ke console
const output = JSON.stringify(entry);
if (level === "error" || level === "fatal") {
console.error(output);
} else if (level === "warn") {
console.warn(output);
} else {
console.log(output);
}
}
return {
debug: (msg, meta) => log("debug", msg, meta),
info: (msg, meta) => log("info", msg, meta),
warn: (msg, meta) => log("warn", msg, meta),
error: (msg, meta) => log("error", msg, meta),
fatal: (msg, meta) => log("fatal", msg, meta),
};
}
// Penggunaan
const logger = createLogger("payment-service");
logger.info("Payment initiated", { userId: 42, amount: 150000 });
logger.warn("Retry attempt", { requestId: "abc123", attempt: 2 });
logger.error("Payment failed", { orderId: "ORD-001", reason: "insufficient_funds" });
Log Levels
Gunakan level yang tepat untuk setiap situasi:
| Level | Kapan Digunakan |
|---|---|
DEBUG |
Info detail untuk debugging (hanya di development) |
INFO |
Event normal yang penting (user login, order created) |
WARN |
Situasi tidak normal tapi tidak menyebabkan error |
ERROR |
Kesalahan yang perlu ditangani |
FATAL |
Kesalahan fatal — aplikasi tidak bisa lanjut |
Filtering Logs
function filterLogs(logs, minLevel) {
const minValue = LOG_LEVELS[minLevel] ?? 0;
return logs.filter(log => (LOG_LEVELS[log.level] ?? 0) >= minValue);
}
// Ambil hanya warn ke atas di production
const productionLogs = filterLogs(allLogs, "warn");
// Ambil semua log di development
const devLogs = filterLogs(allLogs, "debug");
Context dan Correlation ID
Untuk melacak satu request di banyak service:
function createRequestLogger(requestId, userId) {
const base = createLogger("api");
return {
info: (msg, meta) => base.info(msg, { requestId, userId, ...meta }),
error: (msg, meta) => base.error(msg, { requestId, userId, ...meta }),
warn: (msg, meta) => base.warn(msg, { requestId, userId, ...meta }),
};
}
// Di setiap request
app.use((req, res, next) => {
req.log = createRequestLogger(req.headers["x-request-id"] ?? crypto.randomUUID(), req.user?.id);
next();
});
Tips Structured Logging
- Selalu sertakan timestamp dalam ISO 8601
- Gunakan level yang tepat — jangan semua pakai
error - Sertakan context — modul atau service mana yang log ini
- Tambahkan request ID untuk tracing antar service
- Jangan log data sensitif — password, token, nomor kartu
- Gunakan library seperti
pinoatauwinstondi Node.js untuk production