NodeJS de Winston Kullanarak Loglama Nasıl Yapılır?

Şerifhan Işıklı
lTunes Tribe
Published in
7 min readAug 28, 2022
winston-nodejs-logging

Herkese tekrardan merhabalar ve iyi çalışmalar. Bu yazımız da nodejs üzerinde hata ve kullanıcı işlemleri için nasıl loglama yaparız bunu anlatmaya çalışacağım. Biraz karmaşık ve orta seviye nodejs üzerinde bilginiz olması gerekebilir. Kafanızın karışması da muhtemeldir. Ufak tanımlardan başlayarak konunun derinine inmeye başlayalım.

Loglama nedir?

Loglama log kayıtları aracılığı ile dijital hareketlerin saklanması işlemine denir. Log tutma anlamına da gelmektedir. Yani ben kayıt olduğumda websitesi üzerinden kayıt olma isteğini yapmam, başarılı veya başarısız bunların tutulmasına loglama denir.

Winston nedir ?

Winston, çoklu aktarımları destekleyen yani birden fazla yere kayıt yapabılmesını sağlayan, basit ve evrensel bir kayıt kütüphanesi olacak şekilde tasarlanmıştır bir kütüphanedir. NPM paket yöneticisi üzerinden indirip projelerimize dahil edip kullanabileceğimiz bir yapıdır.

Yavaş yavaş konumuza girelim ….

Milyonlarca günlük kullanıcısı olan ve binlerce dolar/tl kazanan bir üretim ortamında çalışan bir uygulamanız olduğunu varsayalım. Bir uygulamanın hata vermesinin çeşitli nedenleri vardır ve bir geliştirici olarak nedenini bulup düzeltmeniz gerekir. Hiç kimse buggy olan bir uygulamayı kullanmak istemez ve hataları düzeltmek zaman ve paraya mal olabilir.

Bu sorunu nasıl çözebiliriz? Belki de koda geri dönerek ve her kod satırının beklendiği gibi çalışıp çalışmadığını kontrol ederek. Bu, küçük bir uygulamada daha kolaydır, ancak o zaman bile, bir kullanıcıyla aynı türde bir hatayı tetiklemeye çalışmak zor olabilir. Bunun büyük bir uygulamada ne kadar zor olacağını hayal edin.

Uygulamanın bazı kullanıcı bilgilerini topladığı ve bunları bir veritabanına kaydettiği bir örnek olduğunu varsayalım.

Uygulama başarısız olursa, sunucu son kullanıcıya bir sistem hatası verir. Bu örnekleri yakalayıp bu hataları çözerseniz iyi olur. Böyle bir durumda, a kullanıcısının veya b kullanıcısının bireysel bir sistem hatasıyla karşılaştığını nasıl anlarsınız? Bu hatalar koddaki bir hata, bozuk dosya kurgusu, yanlış yazılmış olan kod yani algoritma hataları veya veri türü uyuşmazlığı nedeniyle oluşabilir. Düşünsenize bir algoritma yazdınız her şey mükemmel gözüküyor fakat production ortamına çıktığınızda hatalarınız sürekli devam ediyor. Çözüyorsunuz ama farklı nedenlerden hata almaya devam ediyorsunuz.

Bu tür kötü durumlardan kaçınmanız gerekiyorsa, loglamadan kaçınamazsınız. Bir programcı olarak, hataları ve özellikle bir sunucudan gelen olayların akışını izlemek için ilk bakılacak yer bir log dosyasıdır. Log dosyası, bir uygulama çalışırken ve kullanıcılarınızla etkileşim kurduğunda ne olduğunu söyler. Örneğin, sisteminizde bir hata varsa ve bunun oluşmasına yol açan adımları anlamak istiyorsanız, log kaydı için harika bir kullanım örneği olabilir.

Logging , uygulama etkinlikleri tarafından oluşturulan bilgileri log dosyalarına kaydetme işlemidir.

Log dosyasına kaydetme işlemi ile neden uğraşıyoruz?

  • Production sırasaında bir şeylerin ters gittiğini anlamanın tek yolu loglama oluşturmaktır. Bir şey yanlışsa veya bir şey çalışmıyorsa, logging size söyleyecektir.
  • Sistem aktivitelerinizi takip edin. Loglar, bir işlemin ne zaman gerçekleştiğini ve loglama sistemini neyin tetiklediğinin kayıdını çok detaylı tutabilecek kadar güçlüdür.
  • Hata izleme
  • Hata ayıklama
  • Uygulama performansı

NodeJS Log sistemlerini kim kullanıyor?

Loggerlar bir yazılım geliştirme projesindeki tüm aktörler için gerçekten önemlidir.

Yazılım Geliştiriciler ve DevOps Mühendisleri

Kod hatalarını ayıklamak için loggerları kullanırlar. Günlük girişleri, yetersiz bellek veya belirli bir veri parçasının alınamaması gibi uygulamadaki olağandışı durumlar konusunda loggerlardan faydalanırlar.

Teknik pazarlamacılar

Yazılımlarının performansını izlemek için log verilerini kullanabilirler. Biraz daha bilgisi olanlar, kendi özel kampanyalarını bile oluşturabilir, olayları kaydedebilir ve daha fazla işleme ve analiz için verileri üçüncü taraf bir araca gönderebilir.

Neden loglama işlemi önümüze çok çıkmıyor?

Bu başlık yanlış anlaşılmasın büyük ve kurumsal firmaların projeler üzerinde değişiklik göstersede bu loglama sistemleri genelde kullanılıyor. Fakat öğrenme sürecinde uğraştığınız örnekler ya da izlediğiniz eğitim videolarında çok fazla önemsenmediğini ya da bir bootcamp sırasında yapılan projelerde bile çok önemsenmediğini görürüz. Loglama genelde bahsettiğim şirketler bünyesinde bir proje yaparken zorunda kaldığınız durumda ortaya çıkıyor. Ve bu durum aslında üzücü. Gerektiğinden az takdir aldığını düşündüğüm sistem aslında çok fazla hayat kurtarıcı olabiliyor. Siz bunları öğrenin ve bir projeye baslarken sistemi bunun üzerine kurun. Daha sonrasında işin içinden çıktığınızda çok güzel bir özellik kazandığınızı hissedeceksiniz. Tabi bu sistemi hep kullananlara saygım sonsuz ve umarım daha çok yayılır.

Log oluşturma ve kaydetme için neden Winston’ı seçtik?

Winston, en iyi log ara katman yazılımlarından biridir ve haftalık yaklaşık 4.000.000 indirmeye sahiptir. Aşağıdaki özellikler, Winston’ı genel bir evrensel log kaydı ara yazılımı yapıyor. Sırasıyla;

  • Kullanımı basit ve yapılandırılabilir.
  • Log kaydetme kanalları (transporting). İyi bir logger, günlük çıktı hedefinizi seçmenin farklı bir yoluna sahiptir. Winston ile dosyalar, veritabanları, e-postalar ve konsol gibi farklı yollarla log gönderebilir ve kaydedebilirsiniz.
  • Log biçimleri. Winston size birkaç log formatı sağlar. Örneğin, bir Mongo veritabanına bir log kaydedilirken log formatının JSON formatında olması gerekir. Winston kendi başına loglama formatını JSON olarak verebiliyor.

Winston’ı kullanma

Winston paketini npm install winston komutunu kullanarak kurun.

— Winston modülünü bir require() işleviyle ekleyin.

  • Winston yapılandırma nesnesi oluşturma. Winston, bir logger oluşturmak için en az bir aktarım(transporting attribute’i ) gerektirir. Bir taşıma, log’un kaydedildiği yerdir.

createLogger ile bir logger oluşturun ve configuration olarak tanımladığımız nesneyi buna iletin.

Mesajınızı Logger’a kaydedin.

Yukarıdaki örnek, konsol içerisinde nasıl loglamanın göstereceğini göstermektedir. Görmek istiyorsanız bir dosya olusturun ismi logger.js olsun. Yukarıda kodları oraya koyun ve terminalden node logger.js yazarak dosyayı çalıştırın.
Daha sonrasında konsolda aşağıda ki gibi bir çıktı alacaksınız.

Winston Transporter Objeleri

Winston’ın özelliklerinden biri, dosya aktarımı gibi çeşitli aktarımları desteklemesidir. Bu, oluşturulan bir log mesajını bir log dosyasına kaydeder. Dosya, sisteminizde belirtilir. Uygulama ilk log örneğini oluşturursa dosya otomatik olarak oluşturulur.

Bunu yapmak için, log yapılandırma nesnesinin bir dosyaya (dosya taşıyıcısı) işaret etmesi gerekir.

Daha sonrasında bunu yukarıda bulunan .transports.Console() ile yer değiştirmemiz gerekiyor. Sonuç olarak configuration nesnesi böyle olacaktır.

Uygulamayı tekrar çalıştırdığınız da ve olusturdugunuz example.log dosyasına gittiğinizde, ki oluşturmanıza da gerek yok. Eğer olusturmadıysanız kendisi oluşturacak. Aşağıda ki gibi bir sonuç görürsünüz ;

Şimdi sunu dediğinizi duyar gibiyim; Ben bir tane seçmek zorunda mıyım? İlla dosya, veritabanı veya consoledan biri mi olmak zorunda?…
Bunun cevabı Hayır. Çünkü;

Winston, birden çok log aktarımı gerçekleştirmenize olanak tanır, yani bir log bir dosyaya, konsola veya veritabanına kaydedilebilir.

Aşağıda paylaşacağımız bir configuration dosyası ile hem konsola hem de dosyaya log aktarımı yapabiliriz. Configuration da yukarıda değişiklik yaptımız yer de artık bir dizi oluşturup içerisine koyacağız. Daha sonrasında veritabanına nasıl kaydedeceğimizi de değineceğiz. Şimdi konfigurasyon dosyasına bakalım ;

Konsolda loglar gözükecektir. Example.log dosyasında ise sadece error tag’i altında ki loglar dosyada gözükecektir.

Ayrıca winston da kendi istediğiniz doğrultusunda log kayıt formatı oluşturabilirsiniz. Örneğin, JSON formatında log girişi istediğimizi varsayalım, bunu Winston.format ile belirtebiliriz ve sonrasında log örnekleri JSON formatında kaydedilecektir.

format içerisinde neleri yapabiliyoruz inceleyelim.

ms() — son logun kaydedilmesinden bu yana geçen milisaniye cinsinden süre.

label() — log dosyasına kaydedilen mesaja bir etiket ekler.

timestamp() — log mesajının alındığı zamanı temsil eder.

splat() — dize enterpolasyonu sağlar.

Bunu loglarınıza uygulamak için aşağıdaki örnekte olduğu gibi format.combine kullanmanız gerekir.

const logConfiguration = {
transports: [
new winston.transports.Console()
],
format: winston.format.combine(
winston.format.label({
label: `Label🏷️`
}),
winston.format.timestamp({
format: 'MMM-DD-YYYY HH:mm:ss'
}),
winston.format.printf(info => `${info.level}: ${info.label}: ${[info.timestamp]}: ${info.message}`),
)
};

const logger = winston.createLogger(logConfiguration);

// Log a message
logger.info("Hello, Winston logger, some info!");

Çıktı;
info: Label🏷️: Aug-28-2022 12:10:44: Hello, Winston logger, some info!

şeklinde olacaktır.

Winston ile Logları Veritabanına(MongoDB) kaydedelim

MongoDB Community Server’ı indirin ve kurun.

Ortam değişkenlerinizi açın(Windows kullanıcıları için), kullanıcı değişkenleri altında Yol → Düzenle → Yeni’yi seçin, C:\Program Files\MongoDB\Server\4.X\bin’i ekleyin (4.X, bilgisayarınızda kurulu MongoDB sürümüne bağlı olarak değişebilir) .

Bir komut istemi açın ve mongo yazın. Bu, MongoDB’yi başarıyla kurup kurmadığınızı kontrol eder. MongoDB shell sürümü terminalinizde yazdırılacaktır, bu da kurulumunuzun başarılı olduğu anlamına gelir.

Veritabanı log oluşturmak için kullanım sırasında kı loglarınzı girin.

Veritabanı için bir koleksiyon oluşturmak db.createCollection(“server_logs”) methodu ile yapılır.

Bahsettiğimiz teorik ve anlamlandırılması zor olan cümleleri biraz kod sisteminde görelim.

Yukarıda olusturdugumuz bir isim verdiğimiz benimde logger.js oldugum dosya dizinine aşağıda verilen kodu kopyalayıp direk mongodb için baglantı yapabiliriz. Ekstra olarak npm i winston-mongodb yapmayı unutmayınız

const { createLogger, format, transports } = require('winston');

// Import mongodb
require('winston-mongodb');

module.exports = createLogger({
transports:[

// File transport
new transports.File({
filename: 'logs/server.log',
format:format.combine(
format.timestamp({format: 'MMM-DD-YYYY HH:mm:ss'}),
format.align(),
format.printf(info => `${info.level}: ${[info.timestamp]}: ${info.message}`),
)}),

// MongoDB transport
new transports.MongoDB({
level: 'error',
//mongo database connection link
db : 'mongodb://localhost:27017/logs',
options: {
useUnifiedTopology: true
},
// A collection to save json formatted logs
collection: 'server_logs',
format: format.combine(
format.timestamp(),
// Convert logs to a json format
format.json())
})]
});

Sunucuyu başlatmak için javascript dosyasının calıstırılması gerekiyor node app.js’yi çalıştırın ve sunucu yanıtlarını ve isteklerini tetiklemek için aşağıdaki URL’lere erişin.

Yukarıda belirttiğimiz filename sayesinde loglar server.log dosyasına kaydedılecektir. new transport.MongoDb olarak olusturdugumuz mongodb bağlantısı sayesinde error logları mongodbye kaydedilecektir.

Logları görüntülemek için db.server_logs.find() yazmanız yeterli olacaktır.

En altta koydugumuz;

format.json())

sayesinde mongodb ye kayıt işlemi yapabiliyoruz. MongoDb datalarını ve indexlerini bir JSON nesnesi gibi tutuyor bunu unutmayınız.

Yazımızın sonuna geldik.. NodeJs için bir çok farklı log sistemleri(Log4js,Bunyan, Morgan …) mevcut bunlarada göz atabilirsiniz. Çoğunun çalışma mekanızması birbirine benziyor. Bu yüzden nasıl ve hangi sistemlere entegre edileceğini öğrendikten sonra gerisi ufak bir google işlemi ve araştırmaya dönüyor. Loglamaya özen göstermeyi unutmayınız.

Herkese iyi çalışmalar..

--

--

Şerifhan Işıklı
lTunes Tribe

Senior Software Engineer @Dogus Teknoloji. (Fitness & cycling)