ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 에러로그 : winston, morgan
    JavaScript/Exress 2022. 10. 12. 21:23

    https://github.com/winstonjs/winston

     

    GitHub - winstonjs/winston: A logger for just about everything.

    A logger for just about everything. Contribute to winstonjs/winston development by creating an account on GitHub.

    github.com

     

    https://www.npmjs.com/package/winston

     

    winston

    A logger for just about everything.. Latest version: 3.8.2, last published: a month ago. Start using winston in your project by running `npm i winston`. There are 17098 other projects in the npm registry using winston.

    www.npmjs.com

     

    https://www.npmjs.com/package/winston-daily-rotate-file

     

    winston-daily-rotate-file

    A transport for winston which logs to a rotating file each day.. Latest version: 4.7.1, last published: 4 months ago. Start using winston-daily-rotate-file in your project by running `npm i winston-daily-rotate-file`. There are 1463 other projects in the n

    www.npmjs.com

     


    winston : 에러 로그를 저장하는 라이브러리

    설치

    npm install winston winston-daily-rotate-file  date-utils

    여러 블로그를 참조하여, 세가지 패키지를 한번에 깔았다. 

    winston, winston-daily-rotate-file, date-utils.

    사실 대부분의 곳에서 winston 하나만 을 소개하고 있었으므로 기능을 분별한 이후 수정해야할 대목이다.

    (기술매니저님의 조언에 의하면, winston은 확장성이 매우 높다. 다르게 말하면 윈스턴 자체로는 에러로그 저장 기능과 에러로그 커스터마이징 기능 뿐이다. 그러나 다른 모듈과 섞어서 쓰기에 따라 여러 기능이 가능해진다. 이를테면 에러로그를 슬랙으로 알림을 보낼 수도 있다고 한다.)

     

     

    winston.js

    config 폴더 안에 winston.js를 넣었다.

    경로와 파일명은 수정가능하다. 

    흔히 logger.js로들 쓰는 것으로 보인다.

    이 코드에서는 로그파일이 지정될 경로를 주의해야한다.

    // config/winston.js
    
    const winston = require('winston');
    require('winston-daily-rotate-file');
    require('date-utils');
    const logDir = `${__dirname}/logs` // '../logs'; //로그파일 저장 경로
    
    
    const levels = {
        error: 0,
        warn: 1,
        info: 2,
        http: 3,
        debug: 4,
    }
    
    const level = () => {
        const env = process.env.NODE_ENV || 'development'
        //const env = process.env.LOG_LEVEL || 'info'
        const isDevelopment = env === 'development'
        //const isInfo = env === 'info'
        return isDevelopment ? 'debug' : 'warn'
    }
    
    const colors = {
        error: 'red',
        warn: 'yellow',
        info: 'green',
        http: 'magenta',
        debug: 'blue',
    }
    
    winston.addColors(colors);
    
    const format = winston.format.combine(
        winston.format.timestamp({ format: ' YYYY-MM-DD HH:MM:SS ||' }),
        winston.format.colorize({ all: true }),
        winston.format.printf(
            (info) => `${info.timestamp} [ ${info.level} ] ▶ ${info.message}`,
        ),
    )
    
    
    /*
     * Log Level
     * error: 0, warn: 1, info: 2, http: 3, verbose: 4, debug: 5, silly: 6
     */
    const logger = winston.createLogger({
    
        format,
        level: level(),
        transports: [
            new winston.transports.DailyRotateFile({
                level: 'info',
                datePattern: 'YYYY-MM-DD',
                dirname: logDir,
                filename: `%DATE%.log`,
                zippedArchive: false,	
                handleExceptions: true,
                maxFiles: 3,  // 보관일. 3이면 3일, 30이면 30일.
            }),
            new winston.transports.DailyRotateFile({
                level: 'error',
                datePattern: 'YYYY-MM-DD',
                dirname: logDir + '/error',  
                filename: `%DATE%.error.log`,
                zippedArchive: false,
                maxFiles: 3, // 보관일. 3이면 3일, 30이면 30일.
            }),
            new winston.transports.Console({
                handleExceptions: true,
                colorize: true,
            })
        ]
    });
    
    module.exports = logger;

    logger라는 이름의 모듈로 export되며, 어디에 로그 파일이 저장되는 지가 가장 중요해 보인다.

     

    이 상대경로는 아직 질의사항으로 남아있는데, 다른 곳에서와 그러하듯이 한단계 상위 디렉토리의 logs 폴더를 생각하고 '../logs'; 라고 작성했는데 logs폴더가 바탕화면에 저장되는 것을 볼 수 있었다.

    현재는 `${__dirname}/logs` 로 변경한 상태. 즉, 자신의 디렉토리에서 그냥 저장하라고 지정해놓았다.

     


    더보기

    위 질문에 대해서 기술매니저님으로부터 명쾌한 답변을 들을 수 있었다.

    윈스턴은 파일을 불러오는 것이 아니라 파일을 생성하는 것이니까, 어디서 파일을 생성하는지 봐야한다.

     

    그리고 윈스턴 로그 모듈이 에러로그를 생성하는 곳은, 최상위 데릭토리의 app.js였다.

    그래서 바탕화면으로 빠져나가 저장된 것이다. 

     

    상대경로를 지정할 때는 이 경로가 파일을 불러오는 경로인지, 파일을 생성하는 경로인지에 따라 달리 생각해야한다.

     

    매니저님들 감사합니다. 제가 진짜 많이 도움 받습니다...

     


    여러 다양한 설정이 있지만, 사실 로그 문장의 모양을 커스터마이즈 하는 것이어서 주의를 기울일 곳은 많지 않다.

    예컨대, 다음과 같이 간단한게 줄일 수도 있다.

     

    const winston = require('winston');
    const winstonDaily = require('winston-daily-rotate-file');
     
    const { combine, timestamp, label, printf } = winston.format;
     
    const logDir = '../logs';
     
    const logFormat = printf(({ level, message, label, timestamp }) => {
       return `${timestamp} [${label}] ${level}: ${message}`; 
    });

    format에는 다양한 변수명이 지정되어 있다.
    json, label, timestamp, printf, simple, combine 등.

    형태를 가리키는 것도 있고, 내용을 가리키는 것도 있는 다종다양한 옵션이 있어 아직 파악해나가는 단계이지만,

    combine 만큼은 언급을 해야 할듯 싶다. 

     

    combine은 여러 형식을 혼합해서 사용할 때 쓰는 키워드이다. 

    때문에 로그를 사용자의 뜻대로 커스터마이징 할 때 가장 먼저 등장한다.

     

    app.js

    //app.js
    
    const express = require("express");
    const app = express();
    const routes = require('./routes'); // 통신을 수행하는 Router 생성
    const port = 3000;
    
    
    /**********로거 출력용 logger, morgan**********/
    //const logger = require('./config/winston');
    global.logger || (global.logger = require('./config/winston'));  // → 윈스턴 로거를 전역에서 사용
    const morganMiddleware = require('./middlewares/morganMiddleware');
    app.use(morganMiddleware);  // 콘솔창에 통신결과 나오게 해주는 것
    
    /*****생략*********/
    
    app.get('/', (req, res) => {
      logger.info('GET /');
      res.sendStatus(200);
    });
    
    app.get('/error', (req, res) => {
      logger.error('Error message');
      res.sendStatus(500);
    });
    
    app.listen(port, () => {
      logger.info(port, '포트로 서버가 열렸어요!');
    })

    필요한 부분만 추렸다.

    winston이 익스포트한 logger 모듈을 사용하면, console.log를 대신할 수 있다.

    logger.debug, logger.info, logger.error 등.

    모듈명 뒤에 level 이름을 붙이면 된다.

     

     예컨대 아래와 같은 코드를 전역 미들웨어로 app.js에 적으면, 로그의 level별로 콘솔에서 무지개가 찍힌다.

    app.use(((req, res, next) => {
    logger.info('로그 출력 test용 middleware');
    
    logger.error('error 메시지');
    logger.warn('warn 메시지');
    logger.info('info 메시지');
    logger.http('http 메시지');
    logger.debug('debug 메시지');
    
    next();
    }));

     

     


    Morgan : 서버-클라이언트 통신을 로깅하는 미들웨어

    모건의 미들웨어 코드이다.

    흔히 윈스턴과 연동에서 쓰며, 아래 코드도 그렇다.

    윈스턴의 모듈을 받아서 'stream'한다.

    그리고 개발환경의 변화에 따라 'skip'한다.

    (아직 환경변수에 대한 공부가 되지 않아 더 서술하지 못한다.)

     

    morganMiddleware.js

    const morgan = require("morgan");
    const logger = require('../config/winston');
    
    // 참고 : https://levelup.gitconnected.com/better-logs-for-expressjs-using-winston-and-morgan-with-typescript-1c31c1ab9342
    
    // 스트림 메서드를 Override 합니다.
    // 모건으로 콘솔로그를 대체합니다.
    const stream = {
        // Use the http severity
        write: message => { logger.http(message) }
    };
    
    const skip = () => {
        const env = process.env.NODE_ENV || "development"; //process.env.NODE_ENV
        return env !== "development";
    };
    
    // https://jeonghwan-kim.github.io/morgan-helper/
    morgan.token("status", function (req, res) {
        let color ;
    
        if (res.statusCode < 300) color = "\x1B[32m"    //green
        else if (res.statusCode < 400) color = "\x1B[36m" //cyan
        else if (res.statusCode < 500) color = "\x1B[33m"   //yellow
        else if (res.statusCode < 600) color = "\x1B[31m"   //red
        else color = "\033[0m" /*글자색 초기화*/
    
        return color + res.statusCode + "\033[35m" /*보라색*/;
    });
    
    // body에 담아서 보내준 값을 보여줄 수 있게 해주는 곳. req을 까보자!
    // https://jeonghwan-kim.github.io/morgan-helper/
    morgan.token("request", function (req, res) {
        return "Request_" + JSON.stringify(req.body);
    });
    
    //장난질.
    morgan.token("makeLine", function () {
        let line = "-----------------------------------------------*(੭*ˊᵕˋ)੭* 응답 결과 ╰(*'v'*)╯-----------------------------------------------"
        let blank = "                                   ";
        return line + "\n" + blank;
    });
    
    // Build the morgan middleware
    // morgan 함수의 인자(format)로는 short, dev, common, combined 가 올 수 있다. (정보의 노출 수준)
    // 보통 배포시에는 combined 혹은 common 에 필요한 정보들을 추가하여 사용하는 것을 추천 || 추후 배포 시 사용 -> 주소,IP_ :remote-addr :remote-user |
    const morganMiddleware = morgan(
        ":makeLine 요청_:method | url_':url' | :request | Status_:status | 응답시간_:response-time ms (:res[content-length]줄)",
        { stream, skip }
    );
    
    module.exports =  morganMiddleware;

    여러 커스터마이징 코드가 길지만, 역시 중요한 것은 어떻게 익스포트 되고 어떻게 사용되느냐이다.

     

    app.js

    /**********로거 출력용 logger, morgan**********/
    //const logger = require('./config/winston');
    global.logger || (global.logger = require('./config/winston'));  // → 윈스턴 로거를 전역에서 사용
    const morganMiddleware = require('./middlewares/morganMiddleware');
    app.use(morganMiddleware);  // 콘솔창에 통신결과 나오게 해주는 것

    윗부분은 윈스턴에 관련된 것이고, 아래 두줄이 morgan을 가져오는 코드이다.

    사실 미들웨어 이므로, 임포트 하여 자유롭게 사용할 수 있다. 

    그러나 morgan의 장점은 역시 클라이언트와의 통신에서 그 내용을 일목요연하게 보여준다는 것이기에, 일단 나는 전역으로 작성하였다.

     

    위이 예제 코드에 의해 실행된 morgan의 로그는 이렇다.

    언제 로그가 찍힐지, 그 내용이 어떨지 모두 커스터마이징 할 수 있지만, 

    http 프로토콜로 통실할 때마다 url과 request의 내용을 찍어서 보여주는 방식이 대단히 요긴해 보인다.

     


    https://xively.tistory.com/21

     

    [node.js express] winston으로 node console log 관리하기. winston 사용 설정 자세한 설명!!

    오늘은 express에서 winston으로 console창에 logger 남기는 법, log기록 파일로 저장하는 법에 대해 말해볼 것이다 정말...열심히 찾아가보면서 만들었더니 혼자 쓰기 아까워서 글로 남김ㅋㅋㅋ글쓰는데

    xively.tistory.com

    https://velog.io/@ash/Node.js-서버에-logging-라이브러리-winston-적용하기

     

    [Node.js] Logging 라이브러리 winston 적용하기

    Node.js 서버에 winston으로 로그 남기기

    velog.io

    https://velog.io/@denmark-banana/간단한-Node.js-API-Server-만들기-1

     

    간단한 Node.js API Server 만들기 #1

    간단한 Node.js API Server 만들기 #1 설계 회사 업무상 간단하게 Node.js로 API Server를 구성하게 됬다. 4단계에 걸쳐서 일정을 잡았고 단계에 맞춰 구현할 예정이다. 1. 서버 구축 > Node.js, Express, PM2, (추

    velog.io

    https://levelup.gitconnected.com/better-logs-for-expressjs-using-winston-and-morgan-with-typescript-1c31c1ab9342

     

    Better logs for ExpressJS using Winston and Morgan with Typescript

    A step-by-step guide on how to configure an ExpressJS application with Winston and Morgan loggers using Typescript

    levelup.gitconnected.com

     

    'JavaScript > Exress' 카테고리의 다른 글

    express.urlenconded()  (0) 2022.10.11
    express.router  (0) 2022.10.11
    Express) app 객체, request 객체  (0) 2022.10.01
Designed by Tistory.