日志是每个后台服务必须具备的功能,egg框架提供了很好的日志功能,基本使用可以看https://eggjs.org/zh-cn/core/logger.html,本文主要记录一下egg日志使用中遇到的一些问题。
一、查看egg服务启动日志
egg框架中提供了记录服务启动的日志,当我们启动服务时,会在控制台看到输出信息,如下图所示:
我们可以看到这一句[egg-scripts] Save log file to C:\Users\admin\logs
,意思是将启动日志保存到C:\Users\admin\logs
目录下,查看一下,服务启动日志果然是有的,这个目录是windows系统的,而Linux系统,日志是存在/root/logs
或者’/用户/logs’(根据启动服务的用户决定)目录下的,先看一下启动日志长啥样的,如下图所示:
二、egg服务启动日志目录位置
所以首先要明白一个问题:这个目录是从哪里定义的呢?去百度了一下,发现这篇文章有讲到https://blog.csdn.net/weixin_34409357/article/details/88905398。根据这篇文章去查看了一下egg-scripts
依赖包源码,找到node_modules/egg-scripts/lib/cmd/start.js
文件,可以在run方法中看到,
const HOME = homedir();
const logDir = path.join(HOME, 'logs');
这两行代码表示获取当前用户的根路径然后在根路径下创建logs目录,这就是服务器启动日志存储路径的默认由来,具体实现可以进入 homedir()
方法中查看。
三、自定义egg服务启动日志目录位置
弄明白了什么是服务启动日志和日志位置,接下来才是要做的事情,就是自定义此日志的存储路径。eggjs文档中没有说明怎么改,所以还是找了下别人家的文章:https://www.jianshu.com/p/919f3e288e5a。
方法很简单,就是在package.json
文件的启动服务时加上
--stdout=/your/path/master-stdout.log --stderr=/your/path/master-stderr.log
我的完整配置是
"start": "egg-scripts start --sticky --daemon --stdout=/app/工程目录/logs/prod/run/master-stdout.log --stderr=/app/工程目录/logs/prod/run/master-stderr.log"
其中工程目录要换成自己的工程目录。
保存路径是程路径下logs/prod/run
在启动日志中,可以查看当前服务的启动和停止记录,egg框架还提供了其他类型的日志,具体可以参考egg文档,那这些日志基本配置是没问题的,需要注意的是开发环境和生产环境配置是不一样的。所以我在项目中区分了开发环境和生产环境,都是存储在项目根目录下,但由不同目录存储,配置如下
一、config.prod.js(生产)
config.logger = {
level: 'INFO',
dir: path.join(__dirname, '../logs/prod/app') // 保存路径为工程路径下`logs/prod/app`
};
二、 config.local.js(开发)
其中开发环境中,项目数据库框架使用的是egg-sequelize
,egg-sequelize
默认使用app.logger.info
打印信息,所以如果把egg日志级别设置成info级别,会把执行的SQL语句也会写入日志文件,而开发环境是可以在控制台上看到日志输出,所以不需要写入日志文件中,所以我把日志级别设置为warn级别,就不会写入数据库执行SQL记录。
config.logger = {
level: 'WARN', // 避免记录数据库执行语句
dir: path.join(__dirname, '../logs/dev/app')
};
使用egg-sequelize
框架会默认将执行SQL打印并写入日志文件,查看源码配置https://github.com/eggjs/egg-sequelize/blob/master/lib/loader.js,找到默认日志配置:
const defaultConfig = {
delegate: 'model',
baseDir: 'model',
logging(...args) {
// if benchmark enabled, log used
const used = typeof args[1] === 'number' ? `(${args[1]}ms)` : '';
app.logger.info('[egg-sequelize]%s %s', used, args[0]);
},
host: 'localhost',
port: 3306,
username: 'root',
benchmark: true,
define: {
freezeTableName: false,
underscored: true,
},
};
找到日志配置:
logging(...args) {
// if benchmark enabled, log used
const used = typeof args[1] === 'number' ? `(${args[1]}ms)` : '';
app.logger.info('[egg-sequelize]%s %s', used, args[0]);
},
默认使用app.logger.info('[egg-sequelize]%s %s', used, args[0]);
,因为使用info打印,所以默认信息会写入日志文件中,我想重写这一段,但是报错了,所以上面才把开发环境中的日志级别设置为warn
。而生产环境是不需要记录执SQL的,因为会把日志变很大,所以在生产环境中禁掉了执行SQL信息,配置如下:
config.sequelize = {
dialect: "mysql",
// host
host: "",
// 端口号
port: "",
// 用户名
username: "",
// 密码
password: "",
// 数据库名
database: "",
// 时区,sequelize有很多自动时间的方法,都是和时区相关的,记得设置成东8区(+08:00)
timezone: '+08:00',
// 禁止日志输出
logging: false
};
最后一点,日志存储目录权限一定要可写可读。