跳转到内容

日志系统

基于 Winston 的日志方案,支持控制台输出、文件按日期/大小轮转、阿里云 SLS 远程日志。

基础用法

typescript
import { createLogger, logger, WinstonLoggerService } from '@maxtan/nest-core'

// 初始化日志(在 main.ts 中调用)
createLogger()

// 使用 logger 记录
logger.info('普通信息')
logger.warn('警告信息')
logger.error('错误信息', errorObj)
logger.debug('调试信息')

自定义配置

typescript
createLogger({
  useConsole: true, // 是否输出到控制台,默认 true
  maxDays: 90, // 日志文件保留天数,默认 90
  maxSize: '20m', // 单个文件最大大小,默认 20MB
  timezone: 'Asia/Shanghai', // 日志时区,默认系统本地时区(IANA 时区名)
  sls: {
    // 阿里云 SLS(可选)
    accessKeyId: 'your-ak',
    accessKeySecret: 'your-sk',
    endpoint: 'cn-hangzhou.log.aliyuncs.com',
    projectName: 'your-project',
    logStoreName: 'your-logstore',
    topic: 'nest-boot',
    source: 'source',
    env: 'production'
  }
})

时区配置

默认输出系统本地时区时间。设置 timezone 可指定 IANA 时区:

typescript
createLogger({ timezone: 'Asia/Shanghai' })
// => [2026-06-12 23:45:49.123] [info] 服务器启动

createLogger({ timezone: 'America/New_York' })
// => [2026-06-12 11:45:49.123] [info] 服务器启动

集成到 NestJS

方式一:LoggerModule(推荐)

通过 LoggerModule.forRoot() 注册,onModuleInit 时自动调用 createLogger(),无需手动初始化。同时导出 WinstonLoggerService 供 DI 注入:

typescript
import { LoggerModule } from '@maxtan/nest-core'

@Module({
  imports: [
    LoggerModule.forRoot({
      useConsole: true,
      maxDays: 90,
      timezone: 'Asia/Shanghai'
    })
  ]
})
export class AppModule {}

DI 注入使用 WinstonLoggerService,便于测试时替换为 mock:

typescript
import { Injectable } from '@nestjs/common'
import { WinstonLoggerService } from '@maxtan/nest-core'

@Injectable()
export class OrderService {
  constructor(private readonly logger: WinstonLoggerService) {}

  async create(dto: CreateOrder) {
    this.logger.log('创建订单', dto)
    // ...
    this.logger.error('创建失败', error)
  }
}

WinstonLoggerService 兼容 NestJS LoggerService 接口(log / error / warn / debug / verbose),内部委托给全局 logger 单例,DI 注入与 import { logger } 的输出一致。

方式二:手动初始化

typescript
import { NestFactory } from '@nestjs/core'
import { createLogger, WinstonLoggerService } from '@maxtan/nest-core'

async function bootstrap() {
  createLogger({ useConsole: true })

  const app = await NestFactory.create(AppModule, {
    logger: new WinstonLoggerService()
  })

  await app.listen(3000)
}

两种模式可共存

LoggerModule 注册后,import { logger } 直接导入和 DI 注入 WinstonLoggerService 指向同一实例。使用 LoggerModule 后不需要再手动调用 createLogger()

文件轮转

日志文件自动按日期和大小轮转,超期文件自动压缩归档:

logs/default-2026-02-10.log        # 当前文件
logs/default-2026-02-09.log.gz     # 已压缩归档
  • 自动按日期切割日志文件
  • 旧文件自动压缩为 .gz 格式,节省磁盘空间
  • 超过 maxDays(默认 90 天)的文件自动删除

配置参考

AllLoggerOptions

参数类型默认值说明
useConsolebooleantrue是否输出到控制台
maxDaysnumber90日志文件保留天数
maxSizestring'20m'单个日志文件最大大小
timezonestring-IANA 时区名(如 'Asia/Shanghai'),默认系统本地时区
slsSlsAppenderOptions-阿里云 SLS 配置

SlsAppenderOptions

参数类型默认值说明
accessKeyIdstring-阿里云 AccessKey ID
accessKeySecretstring-阿里云 AccessKey Secret
endpointstring'cn-hangzhou.log.aliyuncs.com'SLS 服务端点
projectNamestring-SLS 项目名称
logStoreNamestring-SLS 日志存储名称
topicstring'nest-boot'日志主题
sourcestring'source'日志来源
envstring'production'环境标识

最佳实践

  1. 启动时初始化:在 main.ts 的最前面调用 createLogger(),确保所有日志都能被捕获
  2. 优先使用 LoggerModule:在 NestJS 上下文中推荐 LoggerModule.forRoot() 注册 + DI 注入,便于测试替换
  3. 区分环境
    • 开发环境:useConsole: true
    • 生产环境:可关闭控制台,启用 SLS
  4. 合理保留期:根据存储空间设置 maxDays,默认 90 天
  5. 结构化信息:使用 logger.info({ traceId, action, duration }) 传入对象,便于日志检索
  6. 敏感信息:避免在日志中输出密码、Token 等字段,操作日志模块已内置自动脱敏

相关文档