NodeJS 로그 남기기
어플리케이션은 개발 및 운영시에 로그를 남길 필요가 있습니다.
특히 운영시에는 장애가 발생했을때 사용자가 겪는 장애 현상만으로는 장애의 원인을 판단하기 어려운 경우가 대다수입니다.
이럴때 관리자나 개발자가 어플리케이션에서 어떤 일이 발생했는지 판단할만한 정보가 필요하게 되며, 이러한 당시의 어플리케이션 정보를 기록하는 것이 로깅입니다.

로그를 어플리케이션 관리 콘솔창에 실시간으로 출력할 수도 있지만, 향후 참고할만한 기록으로서 log.txt 와 같이 파일로 남길 수도 있습니다.
여기서는 winston 모듈을 통해 로그를 남기는 방법을 알아보겠습니다.


winston 모듈 설치
winston 모듈을 설치하기 위해 npm으로 패키지를 설치해줍니다.

윈도우 command(명령 프롬프트)로 nodejs 프로젝트의 루트(최상위) 경로로 이동합니다.
1
cd c:\myProject                       
cs

 


npm install 명령으로 다음의 세가지 모듈을 설치합니다.
1
2
3
npm install winston --save
npm install winston-daily-rotate-file --save
npm install moment --save
cs

 

 


프로젝트에 사용중인 package.json이 있는 경우
이미 개발중이고 package.json이 있는 경우 dependancy 설정에 다음과 같이 추가하고 package.json이 존재하는 경로에서 npm install 명령을 통해 설치해줍니다.
1
2
3
4
5
"dependencies": {
    "moment""^2.20.1",
    "winston""^2.4.0",
    "winston-daily-rotate-file""^1.7.2"                       
}
cs

 

1
npm install                                      
cs

 


Logger 설정 및 사용방법
로깅을 하기 위해서는 크게 두 단계를 거치게 됩니다.

1. Logger(로깅을 남기는 모듈) 을 설정해줍니다. 이때 로그 레벨, 로그파일 경로, 로그 규칙 등을 설정합니다.
2. 설정된 Logger를 통해 로그를 남깁니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
var winston = require('winston');
var winstonDaily = require('winston-daily-rotate-file');
var moment = require('moment');
 
function timeStampFormat() {
    return moment().format('YYYY-MM-DD HH:mm:ss.SSS ZZ');                            
};
//logger 설정
var logger = new (winston.Logger)({
    transports: [
        new (winstonDaily)({
            name'info-file',
            filename: './log/server',
            datePattern: '_yyyy-MM-dd.log',
            colorize: false,
            maxsize: 50000000,
            maxFiles: 1000,
            level: 'info',
            showLevel: true,
            json: false,
            timestamp: timeStampFormat
        }),
        new (winston.transports.Console)({
            name'debug-console',
            colorize: true,
            level: 'debug',
            showLevel: true,
            json: false,
            timestamp: timeStampFormat
        })
    ],
    exceptionHandlers: [
        new (winstonDaily)({
            name'exception-file',
            filename: './log/exception',
            datePattern: '_yyyy-MM-dd.log',
            colorize: false,
            maxsize: 50000000,
            maxFiles: 1000,
            level: 'error',
            showLevel: true,
            json: false,
            timestamp: timeStampFormat
        }),
        new (winston.transports.Console)({
            name'exception-console',
            colorize: true,
            level: 'debug',
            showLevel: true,
            json: false,
            timestamp: timeStampFormat
        })
    ]
});
 
//logger를 통한 로그 출력
logger.info("infolevel 로깅");
cs

설정 내용 설명
transports 속성을 통해 여러개의 설정 정보를 넘길 수 있습니다.
info-file 이라는 설정의 경우를 예로 들어보겠습니다.
filename 속성과 datePattern 속성을 조합해 로그 파일의 파일명이 결정됩니다.
여기서는 현재 소스를 기준으로 ./log 디렉터리 하위에 server_2018-01-27.log 와 같은 파일명으로 로그가 기록됩니다.
위 소스가 실행되는 동일한 위치에 log 디렉터리가 존재해야 합니다.

만약 위 소스가 myProject/bin/logTest.js 였다면 myProject/bin/log 라는 디렉터리를 만들어주어야 하며, 로그파일은 /myProject/bin/log/server_2018-01-27.log 와 같이 생성됩니다.

winston-daily-rotate-file 모듈을 사용했으므로 매일매일 날짜별로 파일을 만들어 로그를 기록합니다. 
로그파일 하나의 최대 용량(maxsize)은 50mb 이며 최대용량을 넘어갔을경우 새파일로 최대 1000개(maxFiles) 까지 생성합니다.

level속성을 통해 어떤 로그레벨로 로깅시 해당 설정을 사용할것인지를 지정해줍니다.
'info' 값을 설정했으므로 info 레벨에서 로깅시 해당 로그파일에 기록하게 됩니다.
showLevel에 true를 넘기게 되면 로그 출력시 어느 레벨의 로그인지 정보를 출력하게 됩니다.
timestamp에는 콜백함수를 넘기게 되는데 로그 출력시 기록할 시간 포맷을 리턴하는 함수를 넘겨주면 됩니다.


로그레벨
로그레벨에 따라 해당 레벨에 대한 로그만 출력할 수 있습니다.
어플리케이션을 실행될 때 로그레벨을 지정해줄 수 있으며, 해당 레벨에 따른 로그만 출력할 수 있으므로 불필요한 로그를 출력하지 않음으로써 로그 정보를 효율적으로 관리할 수 있습니다.
예를 들어 운영중인 어플리케이션의 평소에는 info레벨에서의 로그만 찍다가 장애가 발생했을때 warning이나 error 레벨의 로그레벨로 전환할 수 있을것입니다.

로그레벨은 다음과 같으며 하위의 레벨은 상위 수준을 포함하여 출력합니다. 즉 info 로그레벨은 debug() 를 통해 출력한 debug 레벨까지 포함합니다.
1
debug:0 > info:1 > notice:2 > warning:3 > error:4 > crit:5 > alert:6 > emerg:7
cs

 



로거 사용 및 출력 결과
설정한 logger 객체를 이용하여 logger.info() , logger.debug() 등 원하는 로그 레벨에 따라 어플리케이션 로직 안에서 로깅을 합니다.
소스의 마지막에 다음과 같이 로깅을 한경우 콘솔과 로그 파일에는 다음과 같이 기록됩니다.
1
logger.info("infolevel 로깅");          
cs

 


server_2018-01-27.log
1
2018-01-27 17:01:27.519 +0900 - info: infolevel 로깅
cs

 

 

 

블로그 이미지

도로락

IT, 프로그래밍, 컴퓨터 활용 정보 등을 위한 블로그

댓글을 달아 주세요! 질문 환영합니다!

  • 마키토 2020.05.27 19:58  댓글주소  수정/삭제  댓글쓰기

    안녕하세요... 샘플 그대로 구현해서 붙여넣었는데요...
    라이브러리 3개 모두 설치했습니다.
    Command: node "C:/Users/ll/brackets_nodejs/NodeExample/ch04_test15.js"
    internal/fs/utils.js:230
    throw err;
    ^
    Error: ENOENT: no such file or directory, mkdir 'log\exception._2020-05-We.5/27\'
    at Object.mkdirSync (fs.js:841:3)
    at C:\Users\ll\brackets_nodejs\NodeExample\node_modules\file-stream-rotator\FileStreamRotator.js:654:20
    at Array.reduce ()
    at mkDirForFile (C:\Users\ll\brackets_nodejs\NodeExample\node_modules\file-stream-rotator\FileStreamRotator.js:642:27)
    at Object.FileStreamRotator.getStream (C:\Users\ll\brackets_nodejs\NodeExample\node_modules\file-stream-rotator\FileStreamRotator.js:519:5)
    at new DailyRotateFile (C:\Users\ll\brackets_nodejs\NodeExample\node_modules\winston-daily-rotate-file\daily-rotate-file.js:80:57)
    at Object. (C:\Users\ll\brackets_nodejs\NodeExample\ch04_test15.js:23:9)
    at Module._compile (internal/modules/cjs/loader.js:1133:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1153:10)
    at Module.load (internal/modules/cjs/loader.js:977:32) {
    errno: -4058,
    syscall: 'mkdir',
    code: 'ENOENT',
    path: 'log\\exception._2020-05-We.5/27\\'
    }
    Program exited with code 1

    이런 에러가 나는데.. 뭐가 잘못된건가요??