Logging tizimi


ULASHISH

Nima uchun ro‘yxatga olish muhim

Samarali ro‘yxatga olish bir necha sabablarga ko‘ra zarur:

  • Nosozliklarni tuzatish: Ilovangiz ichida nima sodir bo‘layotganini tushuning
  • Muammolarni bartaraf etish: Ishlab chiqarish muhitidagi muammolarni tashxislash
  • Monitoring: Ilovaning holati va ishlashini kuzatib boring
  • Audit: Muvofiqlik va xavfsizlik uchun muhim voqealarni yozib oling
  • Tahlil: Ilovadan foydalanish va xatti-harakatlari haqida ma’lumot to‘plang

Konsol yordamida asosiy jurnallar

Node.js asosiy jurnallar uchun o‘rnatilgan konsol usullarini taqdim etadi:

// Basic logging
console.log('Info message');
console.error('Error message');
console.warn('Warning message');
console.debug('Debug message');

// Log objects
const user = { id: 1, name: 'John', roles: ['admin', 'user'] };
console.log('User object:', user);

// Table output for arrays or objects
console.table([
  { name: 'John', age: 30, role: 'admin' },
  { name: 'Jane', age: 25, role: 'user' },
  { name: 'Bob', age: 40, role: 'guest' }
]);

// Timing operations
console.time('operation');
// Perform some operations...
for (let i = 0; i < 1000000; i++) {
  // Do something
}
console.timeEnd('operation'); // Outputs: operation: 4.269ms

// Grouping related logs
console.group('User Processing');
console.log('Loading user data...');
console.log('Validating user...');
console.log('Updating user profile...');
console.groupEnd();

// Stack trace
console.trace('Trace message');

Konsol cheklovlari

Konsol qulay bo‘lsa-da, ishlab chiqarishda foydalanish uchun sezilarli cheklovlar mavjud:

  • Filtrlash uchun o‘rnatilgan jurnal darajalari yo‘q
  • Jurnalni aylantirish yoki faylni boshqarish yo‘q
  • JSON kabi tuzilgan chiqish formatlari yo‘q
  • Monitoring tizimlari bilan cheklangan integratsiya

Eslatma: Konsol usullari terminallarga/fayllarga chiqishda sinxron bo‘ladi va ishlab chiqarishda tez-tez ishlatilsa, unumdorlikka ta’sir qilishi mumkin.



Strukturaviy ro‘yxatga olish

Tuzilmali loglash log xabarlarini oddiy matn o‘rniga ma’lumot obyektlari (odatda JSON) ko‘rinishida formatlaydi, bu esa ularni tahlil qilish (parse), qidirish va o‘rganishni osonlashtiradi.

Strukturaviy ro‘yxatga olishning afzalliklari

  • Mashinani o‘qish uchun izchil format
  • Yaxshiroq qidiruv va filtrlash
  • Jurnallarni yig‘ish vositalari bilan soddalashtirilgan integratsiya
  • Metama’lumotlar bilan yaxshilangan kontekst

Tuzilmali log yozuvi misoli (JSON)

{
  "timestamp": "2023-11-28T15:24:39.123Z",
  "level": "error",
  "message": "Failed to connect to database",
  "service": "user-service",
  "context": {
    "requestId": "req-123-456",
    "userId": "user-789",
    "databaseHost": "db.example.com"
  },
  "error": {
    "name": "ConnectionError",
    "message": "Connection refused",
    "stack": "..."
  }
}

Node.js jurnalining mashhur kutubxonalari

Uinston

Uinston ko‘p qirrali jurnallar kutubxonasi bo‘lib, bir nechta transportlarni (chiqishlarni) qo‘llab-quvvatlaydi:

Winston-ni asosiy sozlash

const winston = require('winston');

// Create a logger
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  defaultMeta: { service: 'user-service' },
  transports: [
    // Write logs to a file
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' }),
  ],
});

// If not in production, also log to the console
if (process.env.NODE_ENV !== 'production') {
  logger.add(new winston.transports.Console({
    format: winston.format.simple(),
  }));
}

// Usage
logger.log('info', 'Hello distributed log files!');
logger.info('Hello again distributed logs');
logger.error('Something went wrong', { additionalInfo: 'error details' });

Maxsus Winston formatlari

const winston = require('winston');
const { format } = winston;
const { combine, timestamp, label, printf } = format;

// Custom format
const myFormat = printf(({ level, message, label, timestamp }) => {
  return `${timestamp} [${label}] ${level}: ${message}`;
});

const logger = winston.createLogger({
  format: combine(
    label({ label: 'API Service' }),
    timestamp(),
    myFormat
  ),
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

logger.info('Application started');

Pino

Pino optimal ishlashga ega bo‘lgan kam xarajatli logger bo‘lishi uchun mo‘ljallangan:

Asosiy Pino sozlamalari

const pino = require('pino');

// Create a logger
const logger = pino({
  level: 'info',
  timestamp: pino.stdTimeFunctions.isoTime,
  base: { pid: process.pid, hostname: require('os').hostname() }
});

// Usage
logger.info('Application started');
logger.info({ user: 'john' }, 'User logged in');
logger.error({ err: new Error('Connection failed') }, 'Database connection error');

Ekspress bilan Pino

const express = require('express');
const pino = require('pino');
const pinoHttp = require('pino-http');

const app = express();
const logger = pino();
const httpLogger = pinoHttp({ logger });

// Add request logging middleware
app.use(httpLogger);

app.get('/', (req, res) => {
  req.log.info('User accessed homepage');
  res.send('Hello World!');
});

app.get('/error', (req, res) => {
  req.log.error('Something went wrong');
  res.status(500).send('Error!');
});

app.listen(8080, () => {
  logger.info('Server started on port 8080');
});

Bunyan

Bunyan - jurnallarni ko‘rish uchun CLI bilan tuzilgan tizimli jurnal kutubxonasi:

Bunyanning asosiy sozlamalari

const bunyan = require('bunyan');

// Create a logger
const logger = bunyan.createLogger({
  name: 'myapp',
  streams: [
    {
      level: 'info',
      stream: process.stdout
    },
    {
      level: 'error',
      path: 'error.log'
    }
  ],
  serializers: bunyan.stdSerializers
});

// Usage
logger.info('Application started');
logger.info({ user: 'john' }, 'User logged in');
logger.error({ err: new Error('Connection failed') }, 'Database connection error');

Ilovalarni ro‘yxatga olishning eng yaxshi amaliyotlari

Jurnal darajalari

Jurnal xabarlarining muhimligi va dolzarbligini tasniflash uchun tegishli jurnal darajalaridan foydalaning:

  • xato: Ish vaqti xatolari, istisnolar va e’tibor talab qiladigan nosozliklar
  • ogohlantirish: Ilovani to‘xtatmaydigan, ammo yuzaga kelishi mumkin bo‘lgan muammolarni ko‘rsatadigan ogohlantirish shartlari
  • ma’lumot: Ilova voqealari va bosqichlari haqida axborot xabarlari
  • debug: Ishlab chiqish jarayonida foydali bo‘lgan batafsil diagnostika ma’lumotlari
  • trace: Nosozliklarni tuzatish haqida juda batafsil ma’lumot (usul kiritish/chiqish, o‘zgaruvchan qiymatlar)

Nimani qayd qilish kerak

JIDIRGA OLISH:

  • Ilovani ishga tushirish/yopish hodisalari
  • Autentifikatsiya va avtorizatsiya hodisalari
  • API so‘rovlari va javoblari
  • Ma’lumotlar bazasi operatsiyalari va ishlash ko‘rsatkichlari
  • Kontekstdagi xatolar va istisnolar
  • Resurslardan foydalanish va ishlash ko‘rsatkichlari
  • Konfiguratsiya o‘zgarishlari

ROZDAN KEMANG:

  • Parollar, tokenlar, API kalitlari yoki boshqa hisobga olish ma’lumotlari
  • Personally identifiable information (PII) without proper safeguards
  • Kredit karta raqamlari, ijtimoiy xavfsizlik raqamlari yoki boshqa nozik ma’lumotlar
  • Seans identifikatorlari yoki cookie fayllari
  • Shifrlash kalitlari

Kontekstli jurnal

Muammolarni bartaraf etishni osonlashtirish uchun har bir jurnalga tegishli kontekstni qo‘shing:

const winston = require('winston');

// Create a base logger
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [new winston.transports.Console()]
});

// Create a child logger with request context
function createRequestLogger(req) {
  return logger.child({
    requestId: req.id,
    method: req.method,
    url: req.url,
    ip: req.ip,
    userId: req.user ? req.user.id : 'anonymous'
  });
}

// Usage in Express middleware
app.use((req, res, next) => {
  req.id = generateRequestId();
  req.logger = createRequestLogger(req);
  req.logger.info('Request received');

  const start = Date.now();

  res.on('finish', () => {
    const duration = Date.now() - start;
    req.logger.info({
      statusCode: res.statusCode,
      duration: duration
    }, 'Request completed');
  });

  next();
});

function generateRequestId() {
  return Date.now().toString(36) + Math.random().toString(36).substring(2);
}

Jurnallarni boshqarish va tahlil qilish

Jurnalni aylantirish

Jurnal aylanishini amalga oshirish orqali jurnal fayllari haddan tashqari kattalashishini oldini oling:

Uinston aylanadigan fayllarni tashish bilan

const winston = require('winston');
require('winston-daily-rotate-file');

const transport = new winston.transports.DailyRotateFile({
  filename: 'application-%DATE%.log',
  datePattern: 'YYYY-MM-DD',
  zippedArchive: true,
  maxSize: '20m',
  maxFiles: '14d'
});

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    transport,
    new winston.transports.Console()// Optional console transport
  ]
});

logger.info('Hello rotated logs');

Markazlashtirilgan ro‘yxatga olish

Bir nechta serverlar yoki konteynerlarda ishlaydigan ilovalar uchun tahlil qilish osonroq bo‘lishi uchun jurnallaringizni markazlashtiring:

Uinston Elasticsearch transporti bilan

const winston = require('winston');
require('winston-elasticsearch');

const esTransportOpts = {
  level: 'info',
  clientOpts: {
    node: 'http://localhost:9200'
  },
  indexPrefix: 'app-logs'
};

const logger = winston.createLogger({
  transports: [
    new winston.transports.Elasticsearch(esTransportOpts),
    new winston.transports.Console()// Optional console transport
  ]
});

logger.info('This log will go to Elasticsearch');

Mashhur jurnallarni boshqarish tizimlari

  • ELK Stack (Elasticsearch, Logstash, Kibana): Keng qamrovli jurnallar to‘plami
  • Graylog: Xavfsizlikka qaratilgan markazlashtirilgan jurnallarni boshqarish
  • Fluentd/Fluent Bit: Jurnallarni yig‘ish va uzatish
  • Loki: Yengil og‘irlikdagi jurnallarni yig‘ish tizimi
  • Tijorat imkoniyatlari: Datadog, New Relic, Splunk, LogDNA, Loggly

Ishlab chiqarishga kirish

Ishlash bo‘yicha mulohazalar

  • Voqealar siklini blokirovka qilmaslik uchun Asinxron jurnaldan foydalaning
  • Yaxshiroq ishlash uchun Buffer jurnallari
  • Ishlab chiqarish hajmini kamaytirish uchun Jurnal darajalarini sozlang
  • Har bir hodisani qayd qilish o‘rniga, Yuqori hajmli jurnallardan namuna oling

Xavfsizlik masalalari

  • Jurnalga kirishdan oldin maxfiy ma’lumotlarni tozalang
  • Jurnal fayllarini tegishli ruxsatnomalar bilan himoyalang
  • Jurnallarni uzatishda shifrlashdan foydalaning
  • Jurnal ma’lumotlarini saqlash siyosatini amalga oshiring
  • Tegishli me’yoriy talablarga (GDPR, HIPAA va boshqalar) muvofiqlikni tekshiring

Ma’lumotlarni tozalash misoli

const winston = require('winston');

// Custom format to sanitize sensitive data
const sanitizeFormat = winston.format((info) => {
  if (info.user && info.user.password) {
    info.user.password = '[REDACTED]';
  }

  if (info.user && info.user.creditCard) {
    info.user.creditCard = '[REDACTED]';
  }

  if (info.headers && info.headers.authorization) {
    info.headers.authorization = '[REDACTED]';
  }

  return info;
});

const logger = winston.createLogger({
  format: winston.format.combine(
    sanitizeFormat(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console()
  ]
});

// This sensitive data will be sanitized in the logs
logger.info({
  message: 'User registered',
  user: {
    name: 'John',
    email: 'john@example.com',
    password: 'secret123',
    creditCard: '4111-1111-1111-1111'
  },
  headers: {
    authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
  }
});

Jurnallar yordamida debug

Nosozliklarni tuzatish moduli

debug moduli shartli debug jurnalini kiritishning yengil usulini taqdim etadi:

const debug = require('debug');

// Create named debuggers
const dbDebug = debug('app:db');
const apiDebug = debug('app:api');
const authDebug = debug('app:auth');

// Usage
dbDebug('Connected to database');
apiDebug('API request received at /users');
authDebug('User authenticated: %o', { id: 123, roles: ['admin'] });

// Enable with environment variable:
// DEBUG=app:* node app.js
// or
// DEBUG=app:db,app:auth node app.js

Korrelyatsiya identifikatorlari

Korrelyatsiya identifikatorlari yordamida bir nechta xizmatlar bo‘ylab so‘rovlarni kuzatib boring:

const express = require('express');
const { v4: uuidv4 } = require('uuid');
const winston = require('winston');
const app = express();

// Create a logger
const logger = winston.createLogger({
  transports: [new winston.transports.Console()],
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  )
});

// Correlation ID middleware
app.use((req, res, next) => {
  // Extract correlation ID from the request header or generate a new one
  const correlationId = req.headers['x-correlation-id'] || uuidv4();

  // Add it to the response headers
  res.setHeader('x-correlation-id', correlationId);

  // Add it to the request object
  req.correlationId = correlationId;

  // Create a request-specific logger
  req.logger = logger.child({ correlationId });

  req.logger.info({
    message: 'Request received',
    method: req.method,
    url: req.url
  });

  next();
});

// Routes
app.get('/', (req, res) => {
  req.logger.info('Processing home request');
  res.send('Hello World');
});

app.get('/error', (req, res) => {
  req.logger.error('Error occurred in request');
  res.status(500).send('Error');
});

app.listen(8080, () => {
  logger.info('Server started on port 8080');
});

Xulosa

  • Node.js ilovalarini debug qilish, monitoring qilish va nosozliklarni bartaraf etish uchun samarali ro‘yxatga olish juda muhimdir
  • Yaxshiroq qidirish va tahlil qilish uchun JSON formati bilan tuzilgan jurnallardan foydalaning
  • Ehtiyojlaringizga qarab Winston, Pino yoki Bunyan kabi tegishli jurnal kutubxonalarini tanlang
  • Eng yaxshi amaliyotlarni qo‘llang: tegishli jurnal darajalaridan foydalaning, kontekstni qo‘shing va nozik ma’lumotlarni himoya qiling
  • Ishlab chiqarish muhiti uchun jurnalni aylantirish va markazlashtirilgan jurnalni amalga oshirish
  • Hisoblash strategiyangizni ishlab chiqishda ishlash va xavfsizlik oqibatlarini hisobga oling
  • Tarqalgan tizimlar orqali so‘rovlarni kuzatish uchun korrelyatsiya identifikatorlaridan foydalaning



W3Schools Pathfinder

Yutuqlaringizni kuzating – bu bepul!