Nodejs

 

 

로그 처리

 

winston 깃 허브 문서 : https://github.com/winstonjs/winston

 

 

소스 :  https://github.com/braverokmc79/login-lecture

 

1. 설치 

$ npm install winston

$ npm install winston-daily-rotate-file

$ npm install dotenv

 

 

 

2.env 설정

 

개발시 dev   ,  운영서버 반영시 production

.env 

NODE_ENV ="dev" 

 

app.js 에 추가

const dotenv = require("dotenv");
dotenv.config();

 

 

 

3. winston.log.js  파일과  logger.js 파일을  config 디렉토리에 저장한다.

 

1) src/config/winston.log.js

const winston = require("winston");
const winstonDaily = require("winston-daily-rotate-file");
const { combine, timestamp, printf, colorize, label } = winston.format;

const logDir = "logs"; // logs 디렉토리 하위에 로그 파일 저장

const logFormat = printf((info) => {
    return `${info.timestamp} ${info.level}: ${info.message}`;
});


const productionWinstonDail = [
    new winstonDaily({
        level: "warn",
        datePattern: "YYYY-MM-DD",
        dirname: logDir + "/warn",
        filename: `%DATE%.warn.log`, // file 이름 날짜로 저장
        maxFiles: 30, // 30일치 로그 파일 저장
        zippedArchive: true,
    }),
    // error 레벨 로그를 저장할 파일 설정
    new winstonDaily({
        level: "error",
        datePattern: "YYYY-MM-DD",
        dirname: logDir + "/error", // error.log 파일은 /logs/error 하위에 저장
        filename: `%DATE%.error.log`,
        maxFiles: 30,
        zippedArchive: true,
    })
]

const devWinstonDail = [...productionWinstonDail];
devWinstonDail.push(    // info 레벨 로그를 저장할 파일 설정
    new winstonDaily({
        level: "info",
        datePattern: "YYYY-MM-DD",
        dirname: logDir + "/info",
        filename: `%DATE%.info.log`, // file 이름 날짜로 저장
        maxFiles: 30, // 30일치 로그 파일 저장
        zippedArchive: true,
    }));

/*
 * Log Level
 * error: 0, warn: 1, info: 2, http: 3, verbose: 4, debug: 5, silly: 6
 */
const winstonLog = winston.createLogger({
    format: combine(
        timestamp({
            format: "YYYY-MM-DD HH:mm:ss",
        }),
        logFormat
    ),

    transports: process.env.NODE_ENV !== "production" ? devWinstonDail : productionWinstonDail
});

winstonLog.stream = {
    // morgan wiston 설정
    write: (message) => {
        logger.info(message);
    },
};

// Production 환경이 아닌 경우(dev 등) 배포 환경에서는 
// 최대한 자원을 안잡아 먹는 로그를 출력해야함
if (process.env.NODE_ENV !== "production") {
    winstonLog.add(
        // new winston.transports.Console({
        //     format: combine(
        //         colorize({ all: true }), // console 에 출력할 로그 컬러 설정 적용함
        //         logFormat // log format 적용
        //     ),
        // });

        new winston.transports.Console({
            name: 'debug-console',
            colorize: true,
            level: "debug",
            format: combine(
                label({ label: '백엔드 맛보기' }),
                colorize(),
                timestamp({
                    format: "YYYY-MM-DD HH:mm:ss"
                }),
                printf(
                    info => `${info.timestamp} | [${info.label}] | (${info.level}) :  ${info.message} `
                )
            ),
            showlevel: true,
            json: false,
        })
    );
}


module.exports = winstonLog;



 

 

2) src/config/logger.js

const winstonLog = require("./winston.log");
const parseurl = require('parseurl');


//로그 처리 및 결과값 반환처리
const logger = (response, req, res) => {
    const url = {
        method: req.method,
        path: parseurl(req).pathname,
        status: (response !== null ? response.err : false) ? 400 : 200,
    };

    if (response === null) {
        winstonLog.info(`${url.method} |  ${url.path} 화면 | Request Query : ${JSON.stringify(req.query)} `);
        return;
    }

    let result = false;

    if (response.err) {
        winstonLog.error(
            `${url.method} ${url.path} ${url.status} Response: ${response.success} | Request Body : ${JSON.stringify(req.body)}  |  msg | ${response.err}`
        );

        result = true;
    } else {

        if (url.method === "GET") {
            winstonLog.info(`${url.method} |  ${url.path} 화면 | Request Query : ${JSON.stringify(req.query)}  |   msg | ${response.msg || ""}  `);

        } else {
            winstonLog.info(
                `${url.method} ${url.path} ${url.status} Response: ${response.success}  | Request Body : ${JSON.stringify(req.body)}  |   msg | ${response.msg || ""}`
            );
        }
        result = false;
    }

    if (result) return res.status(400).json({ msg: response.err.toString() });
    return res.status(200).json(response);
};


module.exports = logger;

 

 

 

3) logs  폴더를 프로젝트 app.js 와 동일한  루트 경로에 생성한다.

 

 

 

 

4. 사용방법

 

1) 모델에서  에러반환 처리 또는 try~catch 처리로 에러 또는 메시지 반환 처리를 한다.

src/models/UserStorage.js

    static async getUserInfo(id) {

        return new Promise((resolove, rejects) => {
            const query = "SELECT * FROM users WHERE id= 6  ?";
            db.query(query, [id], function (err, data) {
                if (err) return rejects(err);
                resolove(data.length === 0 ? false : data[0]);
            })
        });

    }

 

src/models/User.js

    async login() {
        try {
            const client = this.body;
            const { id, psword } = await UserStorage.getUserInfo(client.id);

            if (id) {
                if (id === client.id && psword === client.psword) {
                    return { success: true };
                }
                return { success: false, msg: "비밀번호가 틀렸습니다." };
            }
            return { success: false, msg: "존재하지 않는 아이디 입니다." };

        } catch (err) {
            return { success: false, err }
        }

    }

 

 

 

2) 컨트롤에서   get 방식 post 방식에 따라  알맞게 logger 함수를 사용한다.

 

컨트롤 코드 예

"use strict"

const User = require("../../models/User");
const logger = require("../../config/logger");

const output = {
    home: (req, res) => {
        logger(null, req, res);
        res.render("home/index");
    },

    login: (req, res) => {
        logger(null, req, res);
        res.render("home/login");
    },

    register: (req, res) => {
        logger(null, req, res);
        res.render("home/register");
    }
}


const process = {

    login: async (req, res) => {
        const user = new User(req.body);
        const response = await user.login();
        logger(response, req, res);
    },

    register: async (req, res) => {
        const user = new User(req.body);
        const response = await user.register();
        logger(response, req, res);
    }

}

module.exports = {
    output,
    process
}


 

 

 

3) 반환처리 방법은 프로젝트에 맞게  logger.js 파일을  수정해서 사용할것 

 

 

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

구시월 세단풍(細丹楓) , 당장 보기는 좋아도 곧 흉하게 될 것을 비유하는 말.

댓글 ( 4)

댓글 남기기

작성