Her Şey Kayıt Altında! TypeScript ile Log İşlemi

Berkay Haberal
6 min readAug 26, 2023

--

To reach English version of this page

İnsanlık çok eski zamanlardan beri bir şeylerin kaydını tutmayı sever. Bu, Zigguratlara, depo olarak kullanılan binalara kadar uzanır, ancak hepimiz rahiplerin envanterlerini günlüğe kaydetmek için TypeScript kullanmadıklarını biliyoruz 😀. Günlük tutma konusunda değişen bir şey yok. Bulut üzerinde çalışacak yazılımlar geliştiriyoruz ve konsolda yazılanları görmek için kesinlikle bir kayıt tutmamız gerekiyor. Bu kadar sohbet yeter, hadi koda geçelim!

İlk önce bir projeye ve paketlere ihtiyacımız var! İhtiyacınız olan her paketi aşağıdaki kod ile bulabilirsiniz. İstekleri ve hataları günlüğe kaydedeceğiz, böylece hataları nasıl ele alacağımızı da öğreneceğiz!

npm i morgan @types/morgan winston-daily-rotate-file winston @types/winston express @types/express body-parser ts-node

Şimdi, mantığımızı kodlamamız gerekiyor, ardından günlüğe kaydetmeye dalabiliriz! İşte basit bir çalışan uygulaması.

employee-controller dosyamdaki her fonksiyona async anahtar kelimesini verdim çünkü gerçek projelerde veri çekmek için veritabanını kullanacağız. Ve çalıştırma sırasında oluşabilecek uncaugth hatalarını bu şekilde yakalayacağız. Şimdi büyük oyuncular oyuna giriyor. Morgan, Express’te kullanılan bir http request logger ara yazılımıdır. Hakkında daha fazla bilgiye buradan ulaşabilirsiniz. Morgan, Apache standart log çıktısına dayalı bir log cümlesi oluşturacaktır, ancak kullanmak için özel log cümlesi tanımlayabiliriz. Bunlardan bazıları burada:

combined: :remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"

common: :remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]

tiny: :method :url :status :res[content-length] - :response-time ms

Bunlar yerleşik cümle oluşturuculardır. Her kelime TOKEN olarak bilinir. Ve her belirtecin, yerini gerçek bilgilerle değiştirmek için özel bir işlevi vardır. Endişelenmeyin! Nasıl kullanıldığını göstermek için kendi belirtecimizi oluşturacağız. Ancak Morgan’ı özelleştirmeden önce, logger’ımızı oluşturmamız gerekiyor. Morgan bir logger değil, bir interceptor. Logger’ımızı Morgan fonksiyonlarına vereceğiz! Konsola ve dosyaya giriş yapacağız ve bu dosya ile bulut sunucu konsolunu okuyabileceğiz. Loglama konsolu eğer giriş yapmak istiyorsanız dev ortamı içindir. Winston bize gün gün dosya oluşturma yeteneği verir. Otomatik olarak biçimlendirecek ve bir günlük dosyası oluşturacaktır. Bu şekilde bir yıl öncesine gidebilecek logları baştan okumaktan kurtulacağız! Şimdi logger dosyasında satır satır ilerleyelim.

İlk olarak taşıma değişkenleri oluşturuyoruz. Bunlardan biri dosyaya, diğeri konsola loglar ve winston logger her ikisini de aynı anda yapabilir. Taşıma değişkenlerini oluşturduktan sonra, logger oluşturun ve dışa aktarın. Formatları entegre yöntemlerle birleştirebiliriz. 15. satırda zaman damgasını mesaja bağlıyoruz ve printf metodu ile cümlemizi oluşturuyoruz. Satır 15'te verilen zaman damgası, seviye mesaj parametresi gibi başka bir dosyada verilecektir. 6. satırda date Pattern ile gün bazlı log dosyaları oluşturmak istiyorsanız ‘YYYY-MM-DD’ olarak vermeniz önemlidir. Dakika bazlı ve hatta saniye bazlı oluşturabilirsiniz!!! Max size maksimum log dosyası boyutu end max files kaç dosya oluşturulacağı ve ne kadar süre tutulacağı anlamına gelir. Günlük dosyalarını haftalık olarak takip etmek için 7 gün verdim. Ve hepsi bu kadar.
Şimdi hata işleyicimizi geliştirmemiz gerekiyor.

Herhangi bir hata yakaladıktan sonra, morgan’da kullanmak için bazı özellikleri dolduruyoruz ve daha fazlası, kullanıcıya hata yığın izini göstermemek için yanıtı geçersiz kılıyoruz, ancak verilen id ile günlüklerde kolayca bulmak için geliştiriciye errorId veriyoruz. Yanıtı ayarladıktan sonra, şimdi morgan bu yanıtı kesecek ve söylediklerimizi yapacaktır. İşte morgan dosyası.

Burada neler oluyor? İlk olarak, 5. satırda, morgan sentence creator’a vermek için bir token oluşturuyoruz ve id token’ı nasıl işleyeceğine dair bir fonksiyon sağlıyoruz. Daha sonra incomingMessage’ı custom sentencte olarak ve hangi tokenların yerleştirileceğini bildiriyoruz. Bundan sonra, seviye bilgisi vermek için akışları bildiriyoruz. Hatırlayın logger dosyasında winston log oluşturmak için seviye bilgisi istiyor. Morgan sadece winston için mesaj parametresi oluşturuyor. Sonra iki morgan nesnesi dışa aktarıyoruz, biri bilgi günlüğü için duruyor ve diğeri sadece hata günlüğü tutuyor. Bilgi günlüğünde daha fazla uzmanlaşmamıza gerek yok ve hemen günlüğe kaydedecektir. Bu size kalmış, durum kodunu ve yöntemin ne kadar sürdüğünü görmek için silebilirsiniz, ancak şimdi bunları göstermeyecektir çünkü dediğim gibi anında günlüğe kaydedecektir. Hata günlüğünde, cümleyi daha fazla ayarlamamız gerekiyor, hata işleyicide ayarlanan hata mesajını ve hata yığınını ekleyeceğiz. Ayrıca bu parametreler için iki token daha oluşturabilir ve fonksiyonlarla uğraşmayabiliriz ama ben yapmadım. Error morgan’da, başarı yanıtını hata olarak günlüğe kaydetmemek için atlama seçeneklerini etkinleştirebiliriz. Şimdi tek yapmamız gereken bunları ara yazılım olarak kaydetmek.

import express from 'express';
import bodyParser from "body-parser";
import {router} from "./routes";
import {errorHandler} from "./utils/error-handler";
import {errorMorgan, infoMorgan} from "./utils/morgan-middleware";
const app = express();app.use(errorMorgan);
app.use(infoMorgan);
app.use(bodyParser.json());app.use('/api', router);app.use(errorHandler);app.listen(8080, () => {
console.log('Server started at port 8080');
});

Denemeden önce, son tsconfig.json dosyası ve package.json dosyası aşağıdaki gibi görünmelidir.

{
"name": "loggerdemo",
"version": "1.0.0",
"dependencies": {
"@types/express": "^4.17.17",
"@types/morgan": "^1.9.5",
"@types/winston": "^2.4.4",
"body-parser": "^1.20.2",
"express": "^4.18.2",
"morgan": "^1.10.0",
"ts-node": "^10.9.1",
"winston": "^3.10.0",
"winston-daily-rotate-file": "^4.7.1"
},
"main": "dist/app.js",
"scripts": {
jjj "build": "tsc",
"prepublish": "npm run build",
"start": "node dist/app.js"
},
"description": "LoggerDemo",
"devDependencies": {},
"author": "Berkay Haberal",
"license": "MIT",
"bugs": {
"url": "https://github.com/berlaq/LoggerDemo/issues"
},
"homepage": "https://github.com/berlaq/LoggerDemo#readme"
}
{
"compilerOptions": {
"module": "commonjs",
"target": "es2015",
"sourceMap": true,
"esModuleInterop": true,
"outDir": "./dist"
},
"exclude": [
"node_modules"
],
"include": [
"src/**/*.ts"
],
"lib": [
"es2015"
],
"typeRoots": [
"node_modules/@types"
],
"types": [
"node",
"express"
]
}

npm run build ve ardından npm run start ile çalıştırın. Hata ayıklayıcı ile çalıştırmak için IntelliJ konfigürasyonlarını kullanabilirsiniz.

İlk api’yi deneyelim: /api/employee/getAllEmployees

Konsola bakın, işe yaradı! Peki ya dosya kaydı?

Saat farkı için endişelenmeyin, su içmem gerekiyordu 😀 ama işe yaradı!
İkinci API’yi mevcut olmayan kimlikle deneyin: http://localhost:8080/api/employee/getEmployee/4

Hata olarak günlüğe kaydetmedi çünkü bu bir hata değildi. Kodu tekrar kontrol edin. Herhangi bir hata atmadık. Bunun yerine sadece yanıtı değiştirdik ama atlama yöntemini nasıl geçti değil mi? Cevap hata ayıklama modunda.

Durum kodu 200 diyor ama başlıkta 404! Bu şekilde atlandı. İsterseniz bu hatayı ayarlayabilirsiniz. Hata attığımız durumlara ne dersiniz? Bunu yapmadan önce, async metotlarının doğası gereği, atılan hatalar işlemi hemen durdurmayacaktır. Bunun yerine, promise reddedildikten sonra etkileyecektir, bu yüzden kodumuzu bu şekilde değiştirmemiz gerekir.

employeeRouter.patch('/updateEmployee', async (req, res, next) => {
await updateEmployee(req, res, next).catch(err => next(err));
});

Hatayı yakaladıktan sonra, onu hata işleyici olan bir sonraki ara katmana aktarmamız gerekir. Sonra yanıtı düzenleyecek ve Morgan işini yapacaktır.

{
"id": 4,
"name": "Jack Doe"
}

Tam istediğimiz gibi. Hata yığın izi günlükte gösterilir ancak yanıtta gösterilmez. Loglarda errorId ile kolayca bulabilirsiniz!
Sonuna kadar okuduğunuz için teşekkür ederiz. Kodu burada bulabilirsiniz.

İyi kodlamalar!!!

--

--

Berkay Haberal

Hi everyone! I am a Backend Developer and a person who is eager to search and share software things from Turkiye!!