백엔드 쪽에서, morgan을 winston으로 교체하는 과정에서 object가 console.log 와는 다른 형태로 출력되는 것을 확인.
여러 웹 사이트를 뒤지다 보니, JSON.stringify() 를 사용하면 된다고도 하고, util.format을 사용하면 된다고도 합니다.
둘 모두 적용해 보니, 어떤 것을 사용하던 관계는 없는 것 같은데, 일단 사용 예는 아래의 GIST 코드를 붙여서 올립니다.
다만, object 내의 object는 recursive 하게 변경해주지 않는 것 같은데... 이 부분까진 그닥 필요가 없어서.... -_-;
아래의 샘플로그 처럼, 하나의 object를 출력 할 때, 해당 object 문자열의 앞에 매번 포멧팅된 문자열이 나오는 것이 싫으시다면(로그 용량 같은 문제?), 아래와 같이 printf 함수 내용을 수정하시면 됩니다.
// Before
printf(({ level, message, timestamp }) => {
level = level.toUpperCase()
return util.format('%o', message).trim().split('\n').map((line) => {
return `${timestamp} [${level}]: ${line}`
}).join('\n')
})
// After
printf(({ level, message, timestamp }) => {
level = level.toUpperCase()
return `${timestamp} [${level}]: ${util.format('%o', message)}`
})
Winston format 에서 object 출력을 위한 코드와 샘플로그 예
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2021-07-10T06:54:54.902Z [DEBUG]: { | |
2021-07-10T06:54:54.902Z [DEBUG]: openapi: '3.0.0', | |
2021-07-10T06:54:54.902Z [DEBUG]: info: { | |
2021-07-10T06:54:54.902Z [DEBUG]: title: 'Library API', | |
2021-07-10T06:54:54.902Z [DEBUG]: version: '1.0.0', | |
2021-07-10T06:54:54.902Z [DEBUG]: description: 'A Simple Express Library API' | |
2021-07-10T06:54:54.902Z [DEBUG]: }, | |
2021-07-10T06:54:54.902Z [DEBUG]: servers: [ { url: 'http://localhost:18888' }, [length]: 1 ], | |
2021-07-10T06:54:54.902Z [DEBUG]: paths: { | |
2021-07-10T06:54:54.902Z [DEBUG]: '/api/v1/books': { | |
2021-07-10T06:54:54.902Z [DEBUG]: get: { | |
2021-07-10T06:54:54.902Z [DEBUG]: summary: 'Returns the list of all the books', | |
2021-07-10T06:54:54.902Z [DEBUG]: tags: [ 'Books', [length]: 1 ], | |
2021-07-10T06:54:54.902Z [DEBUG]: responses: { '200': [Object] } | |
2021-07-10T06:54:54.902Z [DEBUG]: }, | |
2021-07-10T06:54:54.902Z [DEBUG]: post: { | |
2021-07-10T06:54:54.902Z [DEBUG]: summary: 'Create a new book', | |
2021-07-10T06:54:54.902Z [DEBUG]: tags: [ 'Books', [length]: 1 ], | |
2021-07-10T06:54:54.902Z [DEBUG]: requestBody: { required: true, content: [Object] }, | |
2021-07-10T06:54:54.902Z [DEBUG]: responses: { '200': [Object], '404': [Object], '500': [Object] } | |
2021-07-10T06:54:54.902Z [DEBUG]: } | |
2021-07-10T06:54:54.902Z [DEBUG]: }, | |
2021-07-10T06:54:54.902Z [DEBUG]: '/api/v1/books/{id}': { | |
2021-07-10T06:54:54.902Z [DEBUG]: get: { | |
2021-07-10T06:54:54.902Z [DEBUG]: summary: 'Get the book by id', | |
2021-07-10T06:54:54.902Z [DEBUG]: tags: [ 'Books', [length]: 1 ], | |
2021-07-10T06:54:54.902Z [DEBUG]: parameters: [ [Object], [length]: 1 ], | |
2021-07-10T06:54:54.902Z [DEBUG]: responses: { '200': [Object], '404': [Object] } | |
2021-07-10T06:54:54.902Z [DEBUG]: }, | |
2021-07-10T06:54:54.902Z [DEBUG]: put: { | |
2021-07-10T06:54:54.902Z [DEBUG]: summary: 'Get the book by id', | |
2021-07-10T06:54:54.902Z [DEBUG]: tags: [ 'Books', [length]: 1 ], | |
2021-07-10T06:54:54.902Z [DEBUG]: parameters: [ [Object], [length]: 1 ], | |
2021-07-10T06:54:54.902Z [DEBUG]: requestBody: { required: true, content: [Object] }, | |
2021-07-10T06:54:54.902Z [DEBUG]: responses: { '200': [Object], '404': [Object], '500': [Object] } | |
2021-07-10T06:54:54.902Z [DEBUG]: }, | |
2021-07-10T06:54:54.902Z [DEBUG]: delete: { | |
2021-07-10T06:54:54.902Z [DEBUG]: summary: 'Remove the book by id', | |
2021-07-10T06:54:54.902Z [DEBUG]: tags: [ 'Books', [length]: 1 ], | |
2021-07-10T06:54:54.902Z [DEBUG]: parameters: [ [Object], [length]: 1 ], | |
2021-07-10T06:54:54.902Z [DEBUG]: responses: { '200': [Object], '404': [Object], '500': [Object] } | |
2021-07-10T06:54:54.902Z [DEBUG]: } | |
2021-07-10T06:54:54.902Z [DEBUG]: } | |
2021-07-10T06:54:54.902Z [DEBUG]: }, | |
2021-07-10T06:54:54.902Z [DEBUG]: components: { | |
2021-07-10T06:54:54.902Z [DEBUG]: schemas: { | |
2021-07-10T06:54:54.902Z [DEBUG]: Book: { | |
2021-07-10T06:54:54.902Z [DEBUG]: type: 'object', | |
2021-07-10T06:54:54.902Z [DEBUG]: required: [ 'title', 'author', [length]: 2 ], | |
2021-07-10T06:54:54.902Z [DEBUG]: properties: { id: [Object], title: [Object], author: [Object] }, | |
2021-07-10T06:54:54.902Z [DEBUG]: example: { | |
2021-07-10T06:54:54.902Z [DEBUG]: id: 'd5fE_asz', | |
2021-07-10T06:54:54.902Z [DEBUG]: title: 'The New Turing Omnibus', | |
2021-07-10T06:54:54.902Z [DEBUG]: author: 'Alexander K. Dewdney' | |
2021-07-10T06:54:54.902Z [DEBUG]: } | |
2021-07-10T06:54:54.902Z [DEBUG]: } | |
2021-07-10T06:54:54.902Z [DEBUG]: } | |
2021-07-10T06:54:54.902Z [DEBUG]: }, | |
2021-07-10T06:54:54.902Z [DEBUG]: tags: [ [length]: 0 ] | |
2021-07-10T06:54:54.902Z [DEBUG]: } | |
2021-07-10T06:54:55.139Z [INFO]: 'listening on 18888' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const winston = require('winston') | |
const util = require('util') | |
const { combine, timestamp, printf } = winston.format; | |
const COMMON_OPT = { | |
handleExceptions: true, | |
json: false, | |
format: combine( | |
timestamp(), | |
printf(({ level, message, timestamp }) => { | |
level = level.toUpperCase() | |
return util.format('%o', message).trim().split('\n').map((line) => { | |
return `${timestamp} [${level}]: ${line}` | |
}).join('\n') | |
}) | |
) | |
} | |
let logger = new winston.createLogger({ | |
transports: [ | |
new winston.transports.Console({ | |
...COMMON_OPT, | |
level: 'debug', | |
colorize: true, | |
}) | |
], | |
exitOnError: false, | |
}) | |
module.exports = { | |
logger, | |
} |