Express Projelerinizde Morgan Middleware’ini Etkin Kullanım Rehberi
Web uygulamalarının geliştirilmesi, dağıtımı ve bakımı süreçlerinde, uygulamanın davranışlarını izlemek ve potansiyel sorunları tespit etmek kritik öneme sahiptir. Sunucu tarafında gerçekleşen her HTTP isteğinin ve yanıtının kaydedilmesi, uygulamanın performansı, güvenliği ve kararlılığı hakkında paha biçilmez bilgiler sunar. Node.js ve Express.js ekosisteminde, bu tür bir istek günlüğü (request logging) için en popüler, esnek ve etkili araçlardan biri Morgan middleware’idir.
Morgan, Express uygulamalarınıza gelen her HTTP isteğini konsola veya bir dosyaya kolayca kaydetmenizi sağlayan, hafif ve kullanımı basit bir araçtır. Geliştirme ortamında hızlı hata ayıklama için konsola çıktı vermek, üretim ortamında ise detaylı logları bir dosyaya yazarak daha sonra analiz etmek için idealdir. Bu makalede, Morgan’ın Express projelerinizde nasıl kurulacağından, temel kullanımından ileri seviye özelleştirmelerine ve diğer loglama kütüphaneleriyle entegrasyonuna kadar tüm yönlerini detaylı bir şekilde inceleyeceğiz.
Morgan Nedir ve Neden Önemlidir?
Morgan, Express.js için özel olarak tasarlanmış bir HTTP istek logger middleware’idir. Temel amacı, sunucuya gelen her isteğin metot (GET, POST), URL, HTTP durumu (200, 404, 500), yanıt süresi, uzak IP adresi gibi çeşitli bilgilerini kaydetmektir. Bu bilgiler, aşağıdaki nedenlerle son derece önemlidir:
* Hata Ayıklama ve Sorun Giderme: Uygulamanızda bir sorun oluştuğunda, loglar sorunun ne zaman ve hangi istekler sırasında meydana geldiğini anlamanıza yardımcı olur. Hata kodları (örn. 500 Internal Server Error) ile birlikte gelen istek detayları, hatanın kök nedenini bulmak için ilk adımdır.
* Performans İzleme: Her isteğin ne kadar sürede yanıtlandığını gösteren response-time gibi metrikler, uygulamanızın performans darboğazlarını belirlemenize yardımcı olabilir. Yavaş yanıt veren endpoint’leri tespit ederek optimizasyon yapabilirsiniz.
* Güvenlik Analizi: Şüpheli istek kalıplarını (örn. sürekli başarısız giriş denemeleri, alışılmadık URL erişimleri) izleyerek potansiyel güvenlik tehditlerini erken aşamada fark edebilirsiniz.
* Kullanım Analizi: Hangi URL’lerin daha sık ziyaret edildiği, hangi HTTP metotlarının kullanıldığı gibi bilgiler, uygulamanızın kullanım kalıplarını anlamanıza ve gelecekteki geliştirmeler için yol haritası çıkarmanıza yardımcı olur.
* Denetim ve Uyumluluk: Bazı sektörlerde veya uygulamalarda, yasal veya düzenleyici uyumluluk gereklilikleri nedeniyle tüm isteklerin kaydedilmesi zorunlu olabilir.
Morgan, bu bilgileri esnek bir şekilde sunarak geliştiricilere ve operasyon ekiplerine güçlü bir araç sağlar.
Ön Koşullar
Morgan’ı Express projenizde kullanmaya başlamadan önce aşağıdaki temel bilgilere ve araçlara sahip olduğunuzdan emin olun:
* Node.js ve npm/yarn: Sisteminizde Node.js kurulu olmalıdır. npm (Node Package Manager) veya yarn gibi bir paket yöneticisi de otomatik olarak Node.js ile birlikte gelir.
* Express.js Temelleri: Express.js framework’ünün nasıl kurulduğunu ve temel bir sunucu uygulamasının nasıl oluşturulduğunu bilmelisiniz. Middleware kavramına aşina olmanız önemlidir.
* Terminal/Komut İstemi: Komut satırı arayüzünü kullanarak paketleri yükleyebilmeli ve Node.js uygulamalarını çalıştırabilmelisiniz.
Kurulum
Morgan’ı Express projenize eklemek oldukça basittir. Projenizin ana dizininde bir terminal açarak aşağıdaki komutlardan birini çalıştırın:
npm ile:
npm install morgan
yarn ile:
yarn add morgan
Bu komut, Morgan paketini projenizin node_modules dizinine indirecek ve package.json dosyanızdaki dependencies bölümüne ekleyecektir.
Temel Kullanım
Morgan’ı Express uygulamanızda bir middleware olarak kullanırsınız. Uygulamanıza gelen her isteği yakalar ve belirttiğiniz formata göre loglama yapar.
İlk olarak, index.js veya ana uygulama dosyanızda Morgan’ı içe aktarmanız gerekir:
const express = require('express');
const morgan = require('morgan'); // Morgan'ı içe aktarın
const app = express();
const port = 3000;
// Morgan'ı bir middleware olarak kullanın
app.use(morgan('dev'));
// Basit bir route
app.get('/', (req, res) => {
res.send('Merhaba Express!');
});
// Başka bir route
app.get('/api/users', (req, res) => {
res.json([{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]);
});
app.listen(port, () => {
console.log(Sunucu http://localhost:${port} adresinde çalışıyor.);
});
Yukarıdaki örnekte, app.use(morgan('dev')); satırı Morgan’ı uygulamanıza entegre eder. 'dev' burada Morgan’ın önceden tanımlanmış log formatlarından biridir.
Morgan, geliştiricilerin ihtiyaçlarına göre farklı detay seviyelerinde loglama yapabilmesi için çeşitli önceden tanımlanmış formatlar sunar:
* dev: Geliştirme ortamı için uygun, renkli ve özlü bir format. İstek metodu, URL, durum kodu, yanıt süresi ve içerik uzunluğunu gösterir. Hata durumlarında (4xx, 5xx) kırmızı renkte görünür.
GET / 200 12.000 ms - 17
* tiny: Minimum bilgi içeren çok kısa bir format. Metot, URL, durum kodu, içerik uzunluğu ve yanıt süresi.
GET / 200 17 - 12.000 ms
* short: tiny‘den biraz daha fazla bilgi içerir. Metot, URL, IP adresi, durum kodu, içerik uzunluğu ve yanıt süresi.
::1 - GET / HTTP/1.1 200 17 - 12.000 ms
* common: Apache ortak log formatına benzer. Uzak IP adresi, uzak kullanıcı (varsa), tarih/saat, metot, URL, HTTP versiyonu, durum kodu, içerik uzunluğu.
::1 - - [01/Jan/2024:12:00:00 +0000] "GET / HTTP/1.1" 200 17
* combined: Apache birleşik log formatına benzer. common formatına ek olarak referrer ve user-agent bilgilerini de içerir. Üretim ortamları için genellikle tercih edilir.
::1 - - [01/Jan/2024:12:00:00 +0000] "GET / HTTP/1.1" 200 17 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/..."
Bu formatları kullanarak uygulamanızın loglama çıktısını kolayca değiştirebilirsiniz. Örneğin, üretim ortamında daha detaylı loglar için combined formatını tercih edebilirsiniz:
// Üretim ortamı için
// app.use(morgan('combined'));
// Geliştirme ortamı için
app.use(morgan('dev'));
Özel Formatlar Oluşturma
Morgan’ın önceden tanımlanmış formatları çoğu zaman yeterli olsa da, bazen uygulamanızın veya işletmenizin özel ihtiyaçlarına göre daha spesifik veya farklı bir log formatına ihtiyacınız olabilir. Morgan, bu durumu ele almak için kendi formatınızı belirlemenize olanak tanıyan esnek bir token sistemi sunar.
Özel bir format oluşturmak için, Morgan’a bir string parametre olarak istediğiniz token’ları ve statik metinleri içeren bir şablon verirsiniz. Morgan, bu token’ları her istek için ilgili değerlerle değiştirir.
İşte en sık kullanılan bazı token’lar:
* :method: HTTP isteği metodu (GET, POST, PUT, DELETE vb.).
* :url: İsteğin URL’si.
* :status: Yanıtın durum kodu (200, 404, 500 vb.).
* :response-time: Yanıtın gönderilmesi için geçen süre (milisaniye cinsinden).
* :remote-addr: İsteği yapan istemcinin IP adresi.
* :remote-user: İsteği yapan uzak kullanıcı (varsa).
* :http-version: HTTP protokol versiyonu (1.0, 1.1, 2.0).
* :user-agent: İstemcinin User-Agent başlığı.
* :referrer: İsteğin geldiği referrer URL.
* :date[format]: İsteğin yapıldığı tarih ve saat. format parametresi clf (Common Log Format), iso (ISO 8601), web (RFC 1123) veya özel bir moment.js formatı olabilir. Örneğin, :date[iso].
* :req[header-name]: Belirli bir istek başlığının değeri. Örneğin, :req[Content-Type] veya :req[Authorization].
* :res[header-name]: Belirli bir yanıt başlığının değeri. Örneğin, :res[Content-Length].
* :total-time: İsteğin başlamasından yanıtın tamamen gönderilmesine kadar geçen toplam süre.
* :pid: Sunucu sürecinin Process ID’si.
Örnek Özel Format:
Diyelim ki, her istek için IP adresi, tarih, metot, URL, durum kodu, yanıt süresi, referans URL’si ve user-agent bilgilerini içeren daha detaylı bir log çıktısı istiyorsunuz:
app.use(morgan(':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"'));
Bu format, combined formatına benzer ancak tam kontrol size aittir. Çıktı şöyle görünebilir:
::1 - - [01/Jan/2024:12:00:00 +0000] "GET / HTTP/1.1" 200 17 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/..."
Kendi Özel Token’ınızı Tanımlama:
Morgan, mevcut token’ların ötesinde kendi özel token’larınızı tanımlamanıza da olanak tanır. Bu, uygulamanıza özgü bilgileri (örneğin, oturum kimliği, kullanıcı ID’si) loglara eklemek istediğinizde çok kullanışlıdır.
morgan.token() metodunu kullanarak yeni bir token tanımlayabilirsiniz:
morgan.token('id', function getId(req) {
return req.id; // Express'in req.id özelliği varsa onu kullanır
});
// Eğer req.id yoksa veya farklı bir yerden geliyorsa
morgan.token('user-id', (req, res) => {
// Örneğin, bir kimlik doğrulama middleware'i kullanıcı ID'sini req.user.id'ye eklemiş olabilir.
return req.user ? req.user.id : 'misafir';
});
// Özel token'ı format string'inizde kullanın
app.use(morgan(':id :method :url :status :response-time ms'));
// veya
app.use(morgan(':user-id :method :url :status :response-time ms'));
Bu örnekte, id veya user-id adında yeni bir token tanımladık. Bu token’lar, istek nesnesinden (req) veya yanıt nesnesinden (res) bilgi alabilir. Bu şekilde, uygulamanızın iş mantığına özgü verileri loglara dahil edebilirsiniz.
Logları Bir Dosyaya Yazma
Geliştirme ortamında logları konsola yazdırmak kullanışlı olsa da, üretim ortamında logları bir dosyaya kaydetmek çok daha önemlidir. Dosya logları:
* Kalıcıdır: Sunucu yeniden başlatılsa bile loglar kaybolmaz.
* Merkezi Analiz: Log toplama araçları (ELK Stack, Splunk vb.) tarafından kolayca işlenebilir ve analiz edilebilir.
* Performans: Konsola yazmaktan ziyade dosyaya yazmak, özellikle yüksek trafikli uygulamalarda daha verimli olabilir.
Morgan, logları bir dosyaya yazmak için Node.js’in fs (file system) modülü ile birlikte kullanılabilir. fs.createWriteStream() metodunu kullanarak bir yazma akışı (write stream) oluşturur ve bunu Morgan’ın stream seçeneğine geçirirsiniz.
const express = require('express');
const morgan = require('morgan');
const fs = require('fs');
const path = require('path');
const app = express();
const port = 3000;
// Logların yazılacağı dizini oluşturun (eğer yoksa)
const logDirectory = path.join(__dirname, 'log');
fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory);
// Bir yazma akışı oluşturun (append mode)
const accessLogStream = fs.createWriteStream(path.join(logDirectory, 'access.log'), { flags: 'a' });
// Morgan'ı 'combined' formatında ve oluşturduğumuz stream'e yazacak şekilde kullanın
app.use(morgan('combined', { stream: accessLogStream }));
// Ayrıca geliştirme ortamında konsola da yazdırmak isteyebilirsiniz
// app.use(morgan('dev')); // Bu satırı yorumdan çıkarırsanız hem dosyaya hem konsola yazar
app.get('/', (req, res) => {
res.send('Ana Sayfa');
});
app.get('/api/data', (req, res) => {
res.json({ message: 'Verileriniz burada.' });
});
app.listen(port, () => {
console.log(Sunucu http://localhost:${port} adresinde çalışıyor.);
});
Bu örnekte:
1. log dizini oluşturulur (eğer yoksa).
2. fs.createWriteStream() kullanarak access.log dosyasına yazacak bir akış oluşturulur. flags: 'a' seçeneği, dosyanın sonuna ekleme yapılmasını sağlar (append mode), böylece her sunucu yeniden başlatıldığında eski loglar silinmez.
3. morgan('combined', { stream: accessLogStream }) satırı, Morgan’ı combined formatında çıktı vermesi ve bu çıktıyı accessLogStream‘e yönlendirmesi için yapılandırır.
Log Rotasyonu (Log Rotation):
Üretim ortamında, log dosyaları zamanla çok büyük boyutlara ulaşabilir. Bu durum, disk alanını tüketebilir ve logların okunmasını/işlenmesini zorlaştırabilir. Bu sorunu çözmek için “log rotasyonu” kullanılır. Log rotasyonu, belirli bir boyuta veya zamana ulaştığında mevcut log dosyasını arşivleyip yeni bir log dosyası oluşturma işlemidir.
Morgan’ın kendisi yerleşik bir log rotasyonu özelliği sunmaz. Bunun için aşağıdaki yaklaşımları kullanabilirsiniz:
* İşletim Sistemi Araçları: Linux sistemlerinde logrotate gibi araçlar, log dosyalarını otomatik olarak döndürmek, sıkıştırmak ve temizlemek için kullanılabilir. Bu, sunucu düzeyinde yapılandırılır.
* Üçüncü Parti Node.js Kütüphaneleri: rotating-file-stream veya winston-daily-rotate-file gibi kütüphaneler, Node.js uygulamanız içinde programatik olarak log rotasyonu yapmanıza olanak tanır. Bu kütüphaneler, Morgan’ın stream seçeneğiyle entegre edilebilir.
Örneğin, rotating-file-stream ile basit bir entegrasyon:
const rfs = require('rotating-file-stream'); // npm install rotating-file-stream
// ... diğer kodlar ...
const accessLogStream = rfs.createStream('access.log', {
interval: '1d', // her gün döndür
path: logDirectory,
compress: 'gzip' // eski logları sıkıştır
});
app.use(morgan('combined', { stream: accessLogStream }));
Bu şekilde, log dosyalarınızın yönetimi daha düzenli hale gelir.
Koşullu Loglama (Conditional Logging)
Bazen uygulamanızdaki belirli istekleri loglamak istemeyebilirsiniz. Örneğin:
* Sağlık Kontrolü (Health Check) Endpoint’leri: Sık sık sorgulanan /health veya /status gibi endpoint’ler, gerçek uygulama trafiği hakkında bilgi vermediği için logları gereksiz yere şişirebilir.
* Statik Dosyalar: Resimler, CSS veya JavaScript dosyaları gibi statik varlıklara yapılan istekler genellikle loglanmaya değer değildir.
* Hata Durumları: Yalnızca belirli bir HTTP durum koduna sahip istekleri (örneğin, sadece 4xx veya 5xx hatalarını) loglamak isteyebilirsiniz.
Morgan, skip seçeneği aracılığıyla koşullu loglama yapmanıza olanak tanır. skip seçeneği, bir istek ve yanıt nesnesi (req, res) alan ve loglama yapılıp yapılmayacağını belirten bir boolean değer döndüren bir fonksiyondur. Eğer fonksiyon true döndürürse, istek loglanmaz; false döndürürse loglanır.
const express = require('express');
const morgan = require('morgan');
const app = express();
const port = 3000;
// Sadece 400 ve üzeri durum kodlarına sahip istekleri logla
app.use(morgan('dev', {
skip: function (req, res) { return res.statusCode < 400 }
}));
// Sağlık kontrolü endpoint'ini loglama
// app.use(morgan('dev', {
// skip: function (req, res) { return req.url === '/health' }
// }));
app.get('/', (req, res) => {
res.send('Ana Sayfa');
});
app.get('/health', (req, res) => {
res.status(200).send('OK'); // Bu istek loglanmayacak (eğer skip aktifse)
});
app.get('/error', (req, res) => {
res.status(500).send('Bir hata oluştu!'); // Bu istek loglanacak
});
app.listen(port, () => {
console.log(Sunucu http://localhost:${port} adresinde çalışıyor.);
});
Bu örnekte, skip fonksiyonu, yanıtın durum kodu 400’den küçükse true döndürür (yani loglama yapmaz). Bu sayede sadece istemci veya sunucu hatalarına yol açan istekler loglanır.
Birden fazla koşulu birleştirmek için mantıksal operatörler kullanabilirsiniz:
app.use(morgan('dev', {
skip: function (req, res) {
return req.url === '/health' || req.url.startsWith('/static/') || res.statusCode < 400;
}
}));
app.use(express.static('public')); // Örnek statik dosya sunumu
Bu yapılandırma ile /health URL'sine gelen istekler, /static/ ile başlayan URL'lere gelen istekler ve 400'den düşük durum koduna sahip yanıtlar loglanmayacaktır.
Diğer Loglama Kütüphaneleriyle Entegrasyon
Morgan, HTTP istek loglamasında mükemmel olsa da, genel uygulama loglaması (hata logları, bilgi logları, uyarılar vb.) için daha gelişmiş özellikler sunan Winston veya Pino gibi kütüphanelerle birlikte kullanmak isteyebilirsiniz. Bu kütüphaneler genellikle:
* Farklı log seviyeleri (debug, info, warn, error).
* Çeşitli taşıyıcılar (konsol, dosya, veritabanı, uzak servisler).
* Yapısal loglama (JSON formatında loglar) gibi özellikler sunar.
Morgan'ın çıktısını bu gelişmiş loglama kütüphanelerine yönlendirmek mümkündür. Bunun için yine Morgan'ın stream seçeneğini kullanırız, ancak bu sefer bir fs.createWriteStream yerine, diğer loglama kütüphanesinin write metodunu kullanan bir nesne sağlarız.
Winston ile Entegrasyon Örneği:
Önce Winston'ı kurun: npm install winston
const express = require('express');
const morgan = require('morgan');
const winston = require('winston'); // Winston'ı içe aktarın
const app = express();
const port = 3000;
// Winston logger'ı yapılandırın
const logger = winston.createLogger({
level: 'info', // Hangi seviyeden itibaren loglama yapılacağını belirler
format: winston.format.json(), // Logları JSON formatında çıktı ver
transports: [
new winston.transports.Console(), // Konsola yaz
new winston.transports.File({ filename: 'combined.log' }) // Dosyaya yaz
]
});
// Morgan'ın çıktısını Winston'a yönlendirmek için bir stream nesnesi oluşturun
// Winston'ın bir "stream" özelliği yoktur, ancak bir "write" metodu olan herhangi bir nesneyi kabul eder.
const morganStream = {
write: (message) => {
logger.info(message.trim()); // Morgan'dan gelen mesajı Winston ile 'info' seviyesinde logla
},
};
// Morgan'ı 'combined' formatında ve oluşturduğumuz stream'e yazacak şekilde kullanın
app.use(morgan('combined', { stream: morganStream }));
// Uygulama genelinde hata loglaması için Winston'ı kullanabilirsiniz
app.use((req, res, next) => {
req.logger = logger; // İsteğe logger nesnesini ekleyebiliriz
next();
});
app.get('/', (req, res) => {
req.logger.info('Ana sayfaya istek geldi.'); // Uygulama logu
res.send('Merhaba Express!');
});
app.get('/error-test', (req, res, next) => {
const err = new Error('Bu bir test hatasıdır!');
err.status = 500;
next(err); // Hata işleme middleware'ine yönlendir
});
// Hata işleme middleware'i
app.use((err, req, res, next) => {
logger.error(${err.status || 500} - ${err.message} - ${req.originalUrl} - ${req.method} - ${req.ip});
res.status(err.status || 500).send('Sunucu hatası');
});
app.listen(port, () => {
logger.info(Sunucu http://localhost:${port} adresinde çalışıyor.);
});
Bu kurulumda, Morgan sadece HTTP istek loglarını yakalar ve bunları Winston'ın info seviyesinde işlemesini sağlar. Uygulama içindeki diğer loglar (örneğin, /error-test route'undaki hata) doğrudan Winston tarafından yönetilir. Bu, loglarınızın tutarlı bir formatta ve tek bir merkezi loglama sisteminde toplanmasını sağlar.
Hata Loglaması ve Express Hata İşleme
Morgan, HTTP isteklerinin durumunu (başarılı, istemci hatası, sunucu hatası) gösteren durum kodlarını loglar. Örneğin, 500 Internal Server Error durum koduyla sonuçlanan bir isteği Morgan çıktısında görebilirsiniz. Ancak Morgan'ın kendisi, bu hatanın nedenini (örneğin, stack trace) veya uygulama içindeki hata nesnesinin detaylarını loglamaz.
Uygulama içindeki hataları (istisnalar, veritabanı hataları vb.) yakalamak ve detaylı bir şekilde loglamak için Express'in kendi hata işleme middleware'ini ve Winston veya Pino gibi daha gelişmiş bir loglama kütüphanesini kullanmanız gerekir.
Express Hata İşleme Örneği:
const express = require('express');
const morgan = require('morgan');
const winston = require('winston');
const app = express();
const port = 3000;
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'app-errors.log', level: 'error' }) // Sadece 'error' seviyesindeki logları buraya yaz
]
});
// Morgan, tüm istekleri loglar, hatalı olanlar dahil
app.use(morgan('dev'));
app.get('/', (req, res) => {
res.send('Ana Sayfa');
});
app.get('/cause-error', (req, res, next) => {
try {
throw new Error('Uygulama içinde beklenmedik bir hata oluştu!');
} catch (error) {
next(error); // Hatayı hata işleme middleware'ine gönder
}
});
// Hata işleme middleware'i - 4 parametreli olmalı (err, req, res, next)
app.use((err, req, res, next) => {
logger.error({
message: err.message,
stack: err.stack, // Hatanın detaylı izini logla
url: req.originalUrl,
method: req.method,
ip: req.ip,
timestamp: new Date().toISOString()
});
res.status(500).send('Sunucu hatası oluştu. Lütfen daha sonra tekrar deneyin.');
});
app.listen(port, () => {
logger.info(Sunucu http://localhost:${port} adresinde çalışıyor.);
});
Bu senaryoda:
1. /cause-error endpoint'ine yapılan bir istek, morgan('dev') tarafından loglanır ve muhtemelen GET /cause-error 500 ... gibi bir çıktı verir.
2. try...catch bloğundaki hata, next(error) ile hata işleme middleware'ine iletilir.
3. Hata işleme middleware'i, Winston logger.error() metodunu kullanarak hatanın mesajını, stack trace'ini ve istekle ilgili diğer detayları app-errors.log dosyasına (veya konsola) yazar.
Bu yaklaşım, hem HTTP istek loglarını (Morgan ile) hem de uygulama içindeki detaylı hata loglarını (Winston veya Pino ile) ayrı ayrı ve etkili bir şekilde yönetmenizi sağlar. Morgan'ın çıktısı, bir isteğin neden 500 hatası döndürdüğünü gösterir; Winston'ın çıktısı ise bu 500 hatasının iç detaylarını açıklar.
Performans Değerlendirmeleri
Loglama, uygulamanızın performansına hafif de olsa bir yük getirecektir. Her istek için log kaydı oluşturmak, CPU döngüleri ve G/Ç (Input/Output) işlemleri gerektirir. Yüksek trafikli uygulamalarda bu etki göz ardı edilmemelidir.
Morgan'ı kullanırken performans göz önünde bulundurularak şunlara dikkat edilmelidir:
* Format Seçimi: Üretim ortamında dev gibi çok detaylı ve renkli formatlardan kaçının. combined veya özel olarak oluşturulmuş, sadece gerekli bilgileri içeren formatlar daha az işlem yükü getirir. Aşırı token kullanımı, her isteğin işlenmesi gereken veri miktarını artırır.
* Koşullu Loglama: Gereksiz istekleri (sağlık kontrolleri, statik dosyalar) skip seçeneği ile loglamayarak performansı artırabilirsiniz.
* Dosyaya Yazma: Dosyaya yazma işlemleri genellikle asenkrondur, bu da uygulamanın ana iş parçacığını engellemez. Ancak, çok sık ve büyük log dosyalarına yazmak, disk G/Ç'sini zorlayabilir. Log rotasyonu bu yükü hafifletmeye yardımcı olur.
* Diğer Loglama Kütüphaneleri: Winston veya Pino gibi kütüphaneler genellikle logları tamponlama (buffering) veya farklı iş parçacıklarında işleme gibi optimizasyonlar sunar. Morgan'ı bu tür kütüphanelerle entegre etmek, loglama performansını genel olarak artırabilir.
* Hassas Veriler: Performansın yanı sıra, hassas verileri (şifreler, API anahtarları, kişisel bilgiler) loglamaktan kaçınmak güvenlik açısından da kritik öneme sahiptir. Özel token'lar oluştururken veya formatları belirlerken bu konuya dikkat edin.
En İyi Uygulamalar
Morgan'ı Express projelerinizde en verimli ve güvenli şekilde kullanmak için aşağıdaki en iyi uygulamaları göz önünde bulundurun:
1. Ortama Göre Format Seçimi: Geliştirme ortamında dev gibi renkli ve özlü formatları kullanırken, üretim ortamında combined veya kendi oluşturduğunuz, daha az detaylı ancak kritik bilgileri içeren formatları tercih edin.
2. Üretimde Dosya Loglama: Canlı sistemlerde logları konsola değil, her zaman bir dosyaya yazın. Bu, logların kalıcılığını ve merkezi olarak toplanabilirliğini sağlar.
3. Log Rotasyonu Kullanın: Log dosyalarının boyutunu yönetmek için işletim sistemi araçlarını (logrotate) veya Node.js kütüphanelerini (rotating-file-stream) kullanarak log rotasyonunu uygulayın.
4. Hassas Verileri Loglamayın: Şifreler, kimlik bilgileri, kredi kartı numaraları veya diğer kişisel tanımlayıcı bilgileri içeren istek başlıklarını veya gövdelerini loglamaktan kaçının. Özel formatlar oluştururken bu token'ları dahil etmeyin.
5. Yapısal Loglama İçin Entegre Edin: Daha gelişmiş analiz, filtreleme ve arama yetenekleri için Morgan'ı Winston veya Pino gibi yapısal loglama kütüphaneleriyle entegre edin. Bu, loglarınızı JSON gibi makine tarafından okunabilir bir formatta tutmanızı sağlar.
6. Merkezi Log Yönetimi: Büyük ölçekli uygulamalarda, logları merkezi bir log toplama sistemine (ELK Stack, Grafana Loki, Splunk, Datadog vb.) gönderin. Bu, birden fazla sunucudan gelen logları tek bir yerden izlemenizi ve analiz etmenizi kolaylaştırır.
7. Hata İşleme ile Birlikte Kullanın: Morgan, HTTP istek hatalarını gösterse de, uygulama içindeki detaylı hata logları için Express'in hata işleme middleware'i ve ayrı bir loglama kütüphanesi kullanın.
8. skip Seçeneğini Akıllıca Kullanın: Gereksiz log gürültüsünü azaltmak ve performansı artırmak için sağlık kontrolü endpoint'leri veya statik dosyalar gibi önemsiz istekleri loglamayı atlayın.
Sonuç
Morgan, Express.js uygulamaları için vazgeçilmez bir HTTP istek logger middleware'idir. Basit kurulumu, esnek format seçenekleri ve güçlü özelleştirme yetenekleri sayesinde, uygulamanızın geliştirme, hata ayıklama ve üretim süreçlerinde kritik bir rol oynar. İster hızlı bir geliştirme çıktısı, ister detaylı bir üretim logu arıyor olun, Morgan ihtiyaçlarınıza uygun bir çözüm sunar.
Bu makalede Morgan'ın temel kullanımından, özel formatlar oluşturmaya, logları dosyalara yazmaya, koşullu loglama yapmaya ve diğer gelişmiş loglama kütüphaneleriyle entegrasyona kadar birçok yönünü ele aldık. Morgan'ı en iyi uygulamalara uygun şekilde kullanarak, Express uygulamanızın izlenebilirliğini, güvenliğini ve kararlılığını önemli ölçüde artırabilirsiniz. Uygulamanızın ne yaptığını anlamak ve gerektiğinde sorunları hızla çözmek için loglama, her zaman öncelikli bir konu olmalıdır ve Morgan bu sürecin temel taşlarından biridir.