1.0 前言
我们开发好的后端服务,一般都会部署到主机上(比如阿里云 ECS ),或者容器里,假设现在服务器报错了,我们直接 用 console.error() 打印到控制的台话,机器重启后我们是什么也看不到的,所以我们需要把 日志信息存储到某个目录下,这样出现问题,我们去看对应目录下的日志,对日志分析后,就可以定位到具体问题了,这套设计在后端服务里面统称为日志体系。
2.0 日志分类
类似我们浏览器器 console.log 分为 debug,error,info,warn,几个级别一样,服务端日志通常分为 error、warn、info、debug、trace五个级别,常见如下:
- error 问题已经影响到软件的正常运行,并且软件不能自行恢复到正常的运行状态,此时需要输出该级别的错误日志
- warn 与业务处理相关的失败,此次失败不影响下次业务的执行,通常的结果为外部的输入不能获得期望的结果。
- info 系统运行期间的系统运行状态变化,或关键业务处理记录等用户或管理员在系统运行期间关注的一些信息
- debug 软件调试信息,开发人员使用该级别的日志发现程序运行中的一些问题,排除故障。
- trace 基本同上,但显示的信息更详尽。
3.0 常用日志库
目前最常用的日志库是 log4j,log4js-node 是一款比较好的在 Node 环境下对于日志处理的模块,在 Koa 框架下,koa-log4 在 log4js-node 的基础上做了一次包装,是 Koa 的一个处理日志的中间件。接下来我们针对 koa-log4 讲解。4.0 日志配置logger.js
koa-log4 的配置与 log4js-node 是一样的。// logger.js
const path = require('path')
const log4js = require('koa-log4')
log4js.configure({
appenders: {
access: {
type: 'dateFile',
pattern: '-yyyy-MM-dd.log', //生成文件的规则
filename: path.join(process.cwd(), 'logs', 'access.log') //生成文件名
},
application: {
type: 'dateFile',
pattern: '-yyyy-MM-dd.log',
filename: path.join(process.cwd(), 'logs', 'application.log')
},
// 默认输出到控制台
out: {
type: 'console'
}
},
categories: {
default: { appenders: [ 'out' ], level: 'info' },
access: { appenders: [ 'access' ], level: 'info' },
application: { appenders: [ 'application' ], level: 'INFO'} // level 指的是级别,什么级别的日志才输出
}
})
exports.accessLogger = () => log4js.koaLogger(log4js.getLogger('access')); //记录所有访问级别的日志
//记录所有应用级别的日志,输出到 log/application.log,如果想直接输出到控制台 'application' 改成 "default"
exports.logger = log4js.getLogger('application');
5.0 日志使用方法
5.0.1 访问日志
访问日志的含义是,我们希望记录每个 API 请求,比如访问 /,/login,/index,都记录下来。
对于日志的使用,访问级别的,记录用户的所有请求,作为koa的中间件,直接使用便可,如下: ```javascript // app.js const Koa = require(‘koa’); const KoaRouter = require(‘koa-router’); const app = new Koa(); const router = new KoaRouter(); const { logger, accessLogger } = require(‘./logger’); const router = new KoaRouter();
app.use(accessLogger());
访问 [http://localhost:3000](http://localhost:3000/login),然后查看 logs/access.log
[2020-08-16T22:42:21.756] [INFO] access - ::1 - - “GET / HTTP/1.1” 302 43 “” “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36” [2020-08-16T22:42:21.774] [INFO] access - ::1 - - “GET /login HTTP/1.1” 200 1157 “” “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36” [2020-08-16T22:42:25.368] [INFO] access - ::1 - - “POST /login HTTP/1.1” 302 33 “http://localhost:3000/login“ “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36”
这样我们就能记录每次请求,之后出现 bug 后,也好查看了。
<a name="LfH22"></a>
### 5.0.2 应用日志
应用级别的日志,可记录全局状态下的error,也可记录接口请求当中的错误处理。<br />**捕获全局状态下的error**
```javascript
app.on('error', err => {
logger.error(err);
});
接口请求错误
//controller/login.js
const { logger } = require('../logger');
function login(ctx) {
const token = '121212-45dfgffgfg'
logger.info(__dirname, 'come in login')
try {
ctx.response.header.token = token
ctx.app.userInfo = {
name: '王二码字'
}
ctx.cookies.set(
'token', // key
token, // value
{
domain: 'localhost', // 写cookie所在的域名
path: '/', // 写cookie所在的路径
maxAge: 10 * 60 * 1000, // cookie有效时长
expires: new Date('2017-02-15'), // cookie失效时间
httpOnly: false, // 是否只用于http请求中获取
overwrite: false // 是否允许重写
}
)
ctx.redirect('/')
} catch (error) {
logger.error(error)
}
}
module.exports = {
login
}
这样生成各个级别的日志,线上出现问题,就比较方便的查询问题原因了。
6.0 小结
日志这个功能实际项目开发过程中,是个必备的功能项,大家可以对着 Demo 好好体会下,Demo 地址。