日志对 Web 框架的重要性不言而喻,在监控应用状态、排查问题、关键动作记录等有非常重要的作用,egg.js 对日志提供了内置的支持
日志分类
egg.js 按照场景对日志做了分类
- core log:框架内核、插件打印的日志,存储在
egg-web.log下 - app log:应用相关日志,供应用开发者使用,存储在
${appinfo.name}-web.log下 - agent log:agent 进程的日志,egg.js 框架和使用到 agent 进程的插件 在执行任务时把日志打印到
egg-agent.log下 - error log:使用 egg.js 打印的错误日志会存储在
common-error.log下,帮助开发者定位问题
可以修改 config 来自定义日志文件名称
config.logger = {coreLogName: 'egg-web.log',appLogName: `${appInfo.name}-web.log`,agentLogName: 'egg-agent.log',errorLogName: 'common-error.log',};
日志路径
- 在本地开发环境中所有日志存储在
/logs/${appinfo.name}下 - 在线上环境日志存放在
${appinfo.root}/logs/${appinfo.name}下
可以修改不同环境的配置文件,自定义日志存储路径
// config/config.${env}.jsconfig.logger = {dir: '/path/to/your/custom/log/dir',};
打印日志
app log
如果想做一些应用级别的日志记录,如记录启动阶段的一些数据信息,可以通过 App Logger 来完成
// app.jsmodule.exports = app => {app.logger.debug('debug info');app.logger.info('启动耗时 %d ms', Date.now() - start);app.logger.warn('warning!');app.logger.error(someErrorObj);};
框架和插件开发者还会使用到 app.coreLogger
// app.jsmodule.exports = app => {app.coreLogger.info('启动耗时 %d ms', Date.now() - start);};
Agent Logger
在开发框架和插件时有时会需要在 Agent 进程运行代码,这时使用 agent.coreLogger
// agent.jsmodule.exports = agent => {agent.logger.debug('debug info');agent.logger.info('启动耗时 %d ms', Date.now() - start);agent.logger.warn('warning!');agent.logger.error(someErrorObj);};
Context Logger
egg.js 的业务开发者最常使用的是请求的 log,用来记录 Web 行为相关日志
ctx.logger.debug('debug info');ctx.logger.info('some request data: %j', ctx.request.body);ctx.logger.warn('WARNNING!!!!');// 错误日志记录,直接会将错误日志完整堆栈信息记录下来,并且输出到 errorLog 中ctx.logger.error(new Error('whoops'));
每行日志会自动记录上当前请求的一些基本信息, 如
- userId
- ip
- 耗时
- traceId
- method
- url
框架开发者和插件开发者还会使用到 ctx.coreLogger
ctx.coreLogger.info('info');
日志级别
日志分为 NONE,DEBUG,INFO,WARN 和 ERROR 5 个级别,和 egg.js logger 中方法名对应,为了方便开发,在开发环境会同步输出到终端,可以通过配置修改打印到终端、输出到日志文件的级别
打印所有级别日志到终端
// config/config.${env}.jsexports.logger = {consoleLevel: 'DEBUG',};
关闭所有打印到文件的日志
// config/config.${env}.jsexports.logger = {level: 'NONE',};
生产环境打印 DEBUG 日志
为了避免一些插件的调试日志在生产环境打印导致性能问题,生产环境默认禁止打印 DEBUG 级别的日志
// config/config.prod.jsexports.logger = {level: 'DEBUG',allowDebugAtProd: true,};
日志切割
日积月累日志文件会变得非常庞大,egg.js 提供了自动切割日志的功能
按天切割
egg.js 默认按天切割日志,在每日 00:00 按照 .log.YYYY-MM-DD 文件名进行切割
按小时切割
如果日志量非常大,可以修改配置,按照小时切割,例如把 common-error.log 按照小时进行切割:
// config/config.${env}.jsconst path = require('path');module.exports = appInfo => {return {logrotator: {filesRotateByHour: [path.join(appInfo.root, 'logs', appInfo.name, 'common-error.log'),],},};};
按文件大小切割
egg.js 也可以按照文件大小对日志进行切割,例如把 egg-web.log 按照大小进行切割:
// config/config.${env}.jsconst path = require('path');module.exports = appInfo => {return {logrotator: {filesRotateBySize: [path.join(appInfo.root, 'logs', appInfo.name, 'egg-web.log'),],maxFileSize: 2 * 1024 * 1024 * 1024, // 当文件超过 2G 时进行切割},};};
性能
通常 Web 访问是高频访问,每次打印日志都写磁盘会造成频繁磁盘 IO,为了提高性能 egg.js 不会实时把日志内容写入磁盘,而是把日志内容先缓存一段时间(默认 1s)到内存中,然后再异步写入磁盘
egg.js 日志完整功能可以查看官方文档 Egg.js 日志
