日志分为三类:普通日志、异常日志和控制台日志。其中普通日志和异常日志会生成日志文件,持久化存储。控制台日志只展示在控制台中,用于辅助开发。
控制台日志
控制台日志用于辅助开发,一般我们使用 nestjs 内置的日志模块以保持日志格式的一致性。
import { Logger } from '@nestjs/common'
Logger.log('app is listening to 8080')
普通日志
普通日志记录请求信息,包括请求的 id、用时、method、url、headers 等信息。
在中间件中实现,使用了 express-winston、winston、winston-daily-rotate-file。
import { Logger } from '@nestjs/common'
import * as expressWinston from 'express-winston'
import { format } from 'winston'
import * as DailyRotateFile from 'winston-daily-rotate-file'
import config from '../config'
const { combine, timestamp, printf } = format
export default expressWinston.logger({
format: combine(
timestamp(),
printf(({ timestamp, meta }) => {
// 设置日志信息、格式
const { req, res, responseTime } = meta
const { id, url, headers, method } = req
Logger.log(`>> ${method}: ${url} ${responseTime}ms [${id}]`)
const data = {
requestId: id,
time: responseTime,
code: res.statusCode,
method,
url,
headers
}
return `${timestamp} ${JSON.stringify(data)}`
})
),
transports: [
new DailyRotateFile({
filename: '%DATE%.log',
...config.LOGGER
})
],
requestWhitelist: [
'url',
'headers',
'method',
'httpVersion',
'originalUrl',
'query',
'id'
]
})
异常日志
异常日志在异常过滤器中捕获,记录请求 id、method、url、exception 等信息。
// log util
import { createLogger, format } from 'winston'
import { Logger } from '@nestjs/common'
import * as DailyRotateFile from 'winston-daily-rotate-file'
import config from '../config'
const { combine, timestamp, printf } = format
export const error = createLogger({
format: combine(
timestamp(),
printf(({ timestamp, id, method, url ,exception }) => {
Logger.error(exception)
return `${timestamp} ${id} ${method} ${url}: ${JSON.stringify(exception)}`
})
),
transports: [
new DailyRotateFile({
filename: '%DATE%.error.log',
level: 'error',
...config.LOGGER
})
]
})
import { HttpException, Catch, ArgumentsHost } from '@nestjs/common'
import { BaseExceptionFilter } from '@nestjs/core'
import { error as logger } from './errorlogger'
@Catch(HttpException)
export class ExceptionFilter extends BaseExceptionFilter {
catch(exception, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const request = ctx.getRequest<any>();
const { id, method, url } = request
logger.error('', {
id,
method,
url,
exception
})
super.catch(exception, host);
}
}
如果需要自定义日志,可以参考 日志。