Web应用开发框架-egg进阶与实战(一)——debug调试步骤、日志之日志路径、日志分类、日志级别、如何打印日志、文件日志级别、日志切割、日志影响性能
第三章 Egg进阶与实战
Debug
添加 npm scripts
到 package.json
:
{
"scripts": {
"debug": "egg-bin debug"
}
}
egg-bin
会智能选择调试协议,在 8.x 之后版本使用 Inspector Protocol 协议,低版本使用 Legacy Protocol。
同时也支持自定义调试参数:
egg-bin debug --inpsect=9229
执行 debug
命令时,应用也是以 env: local
启动的,读取的配置是 config.default.js
和 config.local.js
合并的结果。
chrome浏览器调试窗口
调式步骤
- 打开
chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9999/__ws_proxy__
- 选择sources
- 找到你需要调试的地方,打上断点
- 进行http访问
日志
日志对于 Web 开发的重要性毋庸置疑,它对于监控应用的运行状态、问题排查等都有非常重要的意义。
框架内置了强大的企业级日志支持,由 egg-logger 模块提供。
日志路径
所有日志文件默认都放在 ${appInfo.root}/logs/${appInfo.name}
路径下。
如果想自定义日志路径:
一般生产环境下才需要自定义日志
// config/config.${env}.js
exports.logger = {
dir: '/path/to/your/custom/log/dir',
};
日志分类
框架内置了几种日志,分别在不同的场景下使用:
- appLogger
${appInfo.name}-web.log
,例如example-app-web.log
,应用相关日志,供应用开发者使用的日志。我们在绝大数情况下都在使用它。 - coreLogger
egg-web.log
框架内核、插件日志。 - errorLogger
common-error.log
实际一般不会直接使用它,任何 logger 的.error()
调用输出的日志都会重定向到这里,重点通过查看此日志定位异常。 - agentLogger
egg-agent.log
agent 进程日志,框架和使用到 agent 进程执行任务的插件会打印一些日志到这里。
如果想自定义以上日志文件名称,可以在 config 文件中覆盖默认值:
// config/config.${env}.js
module.exports = appInfo => {
return {
logger: {
appLogName: `${
appInfo.name}-web.log`,
coreLogName: 'egg-web.log',
agentLogName: 'egg-agent.log',
errorLogName: 'common-error.log',
},
};
};
日志级别
日志分为 NONE
,DEBUG
,INFO
,WARN
和 ERROR
5 个级别。
日志打印到文件中的同时,为了方便开发,也会同时打印到终端中。
- Error 错误
- Warn 警告,比如vue没有加key
- Info 性能分析,这里一定是有用的信息
- Debug 打印一些随意的信息
- None 不要去打印
如何打印日志
如果我们在处理请求时需要打印日志,这时候使用 Context Logger,用于记录 Web 行为相关的日志。
ctx.logger.debug('debug info');
ctx.logger.info('info');
ctx.logger.warn('WARNNING!!!!');
如果我们想做一些应用级别的日志记录,如记录启动阶段的一些数据信息,可以通过 App Logger 来完成。
// app.js
module.exports = app => {
app.logger.debug('debug info');
app.logger.info('启动耗时 %d ms', Date.now() - start);
app.logger.warn('warning!');
app.logger.error(someErrorObj);
};
对于框架和插件开发者会使用到的 App Logger 还有 app.coreLogger
。
// app.js
module.exports = app => {
app.coreLogger.info('启动耗时 %d ms', Date.now() - start);
};
在开发框架和插件时有时会需要在 Agent 进程运行代码,这时使用 agent.coreLogger
。
// agent.js
module.exports = agent => {
agent.logger.debug('debug info');
agent.logger.info('启动耗时 %d ms', Date.now() - start);
agent.logger.warn('warning!');
agent.logger.error(someErrorObj);
};
文件日志级别
默认只会输出 INFO
及以上(WARN
和 ERROR
)的日志到文件中。
可通过如下方式配置输出到文件日志的级别:
打印所有级别日志到文件中:
// config/config.${env}.js
exports.logger = {
level: 'DEBUG',
};
关闭所有打印到文件的日志:
// config/config.${env}.js
exports.logger = {
level: 'NONE',
};
日志切割
默认日志切割方式,在每日 00:00
按照 .log.YYYY-MM-DD
文件名进行切割。
我们也可以按照文件大小进行切割。例如,当文件超过 2G 时进行切割。
例如,我们需要把 egg-web.log
按照大小进行切割:
// config/config.${env}.js
const path = require('path');
module.exports = appInfo => {
return {
logrotator: {
filesRotateBySize: [
path.join(appInfo.root, 'logs', appInfo.name, 'egg-web.log'),
],
maxFileSize: 2 * 1024 * 1024 * 1024,
},
};
};
我们也可以选择按照小时进行切割,这和默认的按天切割非常类似,只是时间缩短到每小时。
// config/config.${env}.js
const path = require('path');
module.exports = appInfo => {
return {
logrotator: {
filesRotateByHour: [
path.join(appInfo.root, 'logs', appInfo.name, 'common-error.log'),
],
},
};
};
性能
通常 Web 访问是高频访问,每次打印日志都写磁盘会造成频繁磁盘 IO,为了提高性能,我们采用的文件日志写入策略是:日志同步写入内存,异步每隔一段时间(默认 1 秒)刷盘