İçeriğe geç
Node.js

Node.js Logging ve Monitoring: Winston ve Pino

Tarık Tunç
Node.js Logging ve Monitoring: Winston ve Pino

Node.js Logging ve Monitoring: Winston ve Pino

Logging, uygulamanızın davranışını anlamanın, hataları teşhis etmenin ve performansı izlemenin en temel yoludur. Node.js ekosisteminde Winston ve Pino, en yaygın kullanılan logging kütüphaneleridir. Bu rehberde her iki kütüphaneyi derinlemesine inceleyecek, yapılandırma, log seviyeleri, transport mekanizmaları ve production-ready monitoring stratejilerini ele alacağız.

1. Neden Profesyonel Logging?

console.log geliştirme ortamında yeterli olabilir ancak production uygulamalarında ciddi eksiklikler yaratır:

  • Log seviyeleri yok (debug, info, warn, error ayrımı)
  • Yapılandırılmış (structured) log formatı yok
  • Dosyaya veya harici servise yazma desteği yok
  • Log rotasyonu ve filtreleme imkanı yok
  • Performans sorunları yaratabilir

2. Winston ile Logging

Winston, Node.js'in en popüler ve en çok kullanılan logging kütüphanesidir. Zengin özellik seti ve esnekliği ile öne çıkar.

# Kurulum
npm install winston

Temel Yapılandırma

// logger.js
const winston = require('winston');

const logger = winston.createLogger({
  level: process.env.LOG_LEVEL || 'info',
  format: winston.format.combine(
    winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
    winston.format.errors({ stack: true }),
    winston.format.json()
  ),
  defaultMeta: { service: 'api-service' },
  transports: [
    // Hata loglarını ayrı dosyaya yaz
    new winston.transports.File({
      filename: 'logs/error.log',
      level: 'error',
      maxsize: 5242880, // 5MB
      maxFiles: 5,
    }),
    // Tüm logları combined dosyasına yaz
    new winston.transports.File({
      filename: 'logs/combined.log',
      maxsize: 5242880,
      maxFiles: 10,
    }),
  ],
});

// Development ortamında konsola da yaz
if (process.env.NODE_ENV !== 'production') {
  logger.add(new winston.transports.Console({
    format: winston.format.combine(
      winston.format.colorize(),
      winston.format.simple()
    ),
  }));
}

module.exports = logger;

Winston Kullanımı

const logger = require('./logger');

// Farklı log seviyeleri
logger.error('Veritabanı bağlantısı başarısız', { host: 'db.example.com', port: 5432 });
logger.warn('API rate limit yaklaşıyor', { remaining: 10 });
logger.info('Kullanıcı giriş yaptı', { userId: 123, ip: '192.168.1.1' });
logger.debug('SQL sorgusu çalıştırıldı', { query: 'SELECT * FROM users', duration: '45ms' });

// Hata objeleri ile
try {
  throw new Error('Bir şeyler ters gitti');
} catch (error) {
  logger.error('İşlem başarısız', { error: error.message, stack: error.stack });
}

Custom Format ve Transport

const winston = require('winston');

// Custom format
const customFormat = winston.format.printf(({ level, message, timestamp, ...meta }) => {
  const metaStr = Object.keys(meta).length ? JSON.stringify(meta) : '';
  return `${timestamp} [${level.toUpperCase()}]: ${message} ${metaStr}`;
});

// HTTP transport — harici servise gönderme
const httpTransport = new winston.transports.Http({
  host: 'log-server.example.com',
  port: 443,
  path: '/logs',
  ssl: true,
});

// Daily rotate file
const DailyRotateFile = require('winston-daily-rotate-file');
const dailyTransport = new DailyRotateFile({
  filename: 'logs/app-%DATE%.log',
  datePattern: 'YYYY-MM-DD',
  maxSize: '20m',
  maxFiles: '14d',
  zippedArchive: true,
});

3. Pino ile Logging

Pino, performans odaklı bir logging kütüphanesidir. Winston'a kıyasla 5-10 kat daha hızlıdır ve JSON formatında çıktı üretir.

# Kurulum
npm install pino pino-pretty

Temel Yapılandırma

// logger.js
const pino = require('pino');

const logger = pino({
  level: process.env.LOG_LEVEL || 'info',
  transport: process.env.NODE_ENV !== 'production'
    ? { target: 'pino-pretty', options: { colorize: true, translateTime: 'SYS:standard' } }
    : undefined,
  base: { service: 'api-service', env: process.env.NODE_ENV },
  timestamp: pino.stdTimeFunctions.isoTime,
  redact: ['req.headers.authorization', 'password', 'creditCard'],
});

module.exports = logger;

Pino Kullanımı

const logger = require('./logger');

// Temel kullanım
logger.info('Sunucu başlatıldı');
logger.info({ port: 3000 }, 'Sunucu dinleniyor');
logger.error({ err: new Error('DB bağlantı hatası') }, 'Veritabanı hatası');

// Child logger — bağlam ekleme
const requestLogger = logger.child({ requestId: 'req-123', userId: 456 });
requestLogger.info('İstek alındı');
requestLogger.info('Veritabanı sorgusu tamamlandı');
// Her log otomatik olarak requestId ve userId içerir

Express ile Pino

# Kurulum
npm install pino-http
const express = require('express');
const pinoHttp = require('pino-http');
const logger = require('./logger');

const app = express();

app.use(pinoHttp({
  logger,
  customLogLevel: function (req, res, err) {
    if (res.statusCode >= 500) return 'error';
    if (res.statusCode >= 400) return 'warn';
    return 'info';
  },
  customSuccessMessage: function (req, res) {
    return `${req.method} ${req.url} tamamlandı`;
  },
  serializers: {
    req: (req) => ({
      method: req.method,
      url: req.url,
      query: req.query,
    }),
    res: (res) => ({
      statusCode: res.statusCode,
    }),
  },
}));

app.get('/api/users', (req, res) => {
  req.log.info('Kullanıcı listesi istendi');
  res.json([]);
});

4. Winston vs Pino Karşılaştırma

ÖzellikWinstonPino
PerformansOrtaÇok yüksek (5-10x)
FormatEsnek (JSON, text, custom)JSON-first
TransportDahili (file, http, console)Harici worker thread
Öğrenme eğrisiKolayKolay
EkosistemGenişBüyüyen
RedactionManuelDahili
İpucu: Yüksek trafikli API'lerde Pino tercih edin. Esnek format ve transport ihtiyaçlarında Winston daha uygun olabilir.

5. Structured Logging Best Practices

// KÖTÜ — yapısız log
logger.info('Kullanıcı 123 sipariş 456 oluşturdu, toplam: 99.99 TL');

// İYİ — yapılandırılmış log
logger.info({
  event: 'order_created',
  userId: 123,
  orderId: 456,
  total: 99.99,
  currency: 'TRY',
}, 'Sipariş oluşturuldu');

// Request context ile middleware
function requestContext(req, res, next) {
  const requestId = req.headers['x-request-id'] || crypto.randomUUID();
  req.log = logger.child({ requestId, method: req.method, path: req.path });
  res.setHeader('x-request-id', requestId);
  next();
}

6. Monitoring ve Alerting

Logları toplamak ve analiz etmek için popüler araçlar ve entegrasyonlar:

// Pino ile Elasticsearch entegrasyonu
// npm install pino-elasticsearch
const transport = pino.transport({
  target: 'pino-elasticsearch',
  options: {
    index: 'app-logs',
    node: 'http://localhost:9200',
    flushBytes: 1000,
  },
});

const logger = pino(transport);

// Winston ile Datadog
// npm install winston-datadog
const DatadogTransport = require('winston-datadog');

logger.add(new DatadogTransport({
  apiKey: process.env.DATADOG_API_KEY,
  hostname: 'my-app',
  service: 'api-service',
}));

Healthcheck Endpoint

app.get('/health', async (req, res) => {
  const health = {
    status: 'ok',
    timestamp: new Date().toISOString(),
    uptime: process.uptime(),
    memory: process.memoryUsage(),
    checks: {},
  };

  try {
    await db.ping();
    health.checks.database = 'ok';
  } catch (err) {
    health.status = 'degraded';
    health.checks.database = 'fail';
    logger.error({ err }, 'Healthcheck: DB bağlantı hatası');
  }

  const statusCode = health.status === 'ok' ? 200 : 503;
  res.status(statusCode).json(health);
});
Uyarı: Hassas verileri (şifre, kredi kartı, token) loglara yazmayın. Pino'nun redact veya Winston'ın custom format özelliğini kullanarak bu verileri maskeleyeyin.

Sonuç

Profesyonel logging, production uygulamalarının olmazsa olmazıdır. Winston esnek ve zengin özellik setiyle genel amaçlı projelere, Pino ise üstün performansıyla yüksek trafikli uygulamalara uygundur. Yapılandırılmış log formatı, log seviyeleri, context ekleme ve hassas veri maskeleme gibi pratikleri uygulamak hata ayıklama sürecinizi dramatik şekilde hızlandıracaktır. Loglarınızı Elasticsearch, Datadog veya benzeri platformlarla merkezileştirerek monitoring ve alerting altyapınızı kurmayı ihmal etmeyin.

Kaynaklar

İlgili Yazılar