第三篇:koa2-web应用进阶—日志

日志在web应用中日志是必不可少的,在系统调试或运行出现异常时,可以通过日志来进行排查。 甚至利用日志可以进行数据统计。
本篇将介绍 koa2 web 应用中日志文件的配置, 采用的日志模块为Apache开发的Node 版 log4 – log4js-node
推荐一篇介绍 log4js 的博文: NodeJS写日志_Log4js使用详解+常见艰难的解决

一、日志配置

1、 依赖选择: 根据koa wiki中的介绍,中间件 koa-log4 是 log4js-node koa版本, 且支持 koa2。 npm i –save koa-log4
2、 新建日志路径: ./logs, 用于存放生成的日志文件
3、 新建日志配置文件: ./log.js, 加入代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
'use strict'
const path = require('path')
const log4js = require('koa-log4')
const logDir = path.join(__dirname, 'logs') //配置目标路径 logs
/*生成logs目录*/
try {
require('fs').mkdirSync(logDir) //新建目录, ./logs
} catch(err) {
if(err.code !== 'EEXIST') {
console.error('Could not set up log directory, error was: ', err)
process.exit(1)
}
}
//根据log 配置文件(log4js.json)配置日志文件
log4js.configure(path.join(__dirname, 'log4js.json'), { cwd: logDir })
//注册日志: 日志名(前缀)startup
const logger = log4js.getLogger('startup')
//输入日志
logger.info('logs config finished!')

5、 日志配置文件 (log4js.json) 编写 实际使用中以下注释全部删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"appenders": [
{
"type": "console" //控制台输出日志
},
{
"type": "clustered", //支持多 appender 时添加,
"appenders": [
{ //在./logs目录生成 http.log文件
"type": "dateFile", //datefile表示是输出按时间分文件的日志
"filename": "http.log", //文件件名
"pattern": "-yyyy-MM-dd", //非当天日志命名格式,例如:http.log-2016-08-02
"category": "http" //过滤所有日志名为 http 的日志
},
{ //记录所有日志
"type": "file", //file表示日志输出为普通文件,在此种配置下,所有日志会输出到该日志文件
"filename": "app.log", //日志文件名
"maxLogSize": 10485760, //设置日志文件的最大大小,文件体积超过时,自动分文件
"pattern": "-yyyy-MM-dd", //
"numBackups": 5 //备份的文件数量,如果文件过多则会将最旧的删除
},
{
"type": "logLevelFilter", //日志级别过滤
"level": "ERROR", //该日志文件只记录级别在error及以上的日志
"appender": {
"type": "file",
"filename": "errors.log"
}
},
]
}
]
}

关于日志配置更详细的说明可以参看博客 NodeJS写日志_Log4js使用详解+常见艰难的解决

6、 在koa web工程中应如 log4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
const Koa = require('koa')
const co = require('co')
const nunjucksViews = require('koa-nunjucks-promise')
const router = require('koa-router')
const mount = require('koa-mount')
const server = require('koa-static')
const session = require("koa-session2")
const log4js = require('koa-log4')
//----------------------------
require('./log') //引入(运行)日志配置文件, 生产日志目录及相应文件
const logger = log4js.getLogger('app') //将当前文件日志命名为 app
logger.info('--------step into koa-------------')
//----------------------------
const store = require('./store')
const app = new Koa()
const route = new router()
app.use(nunjucksViews(`${__dirname}/views`, { //配置模板文件路径,
ext: 'html', //渲染文件后缀为 html
noCache: true, //开发环境下不设置缓存
watch: true, //开发环境下观察模板文件的变化并更新
filters: { //过滤器
json: function(str) {
return JSON.stringify(str, null, 2)
}
},
globals: { //设置对于nunjucks的全局变量
// staticPath: '//static'
}
}))
app.use(mount('/static', server(`${__dirname}/public`))) //设置静态文件路径
//------------- 记录所有http请求---------------
app.use(log4js.koaLogger(log4js.getLogger('http'), { level: 'auto' }))
//-------------------------------------------
app.use(session({
key: "sessionId", //default "koa:sess",
store: new store(),
maxAge: 5000 //设置session超时时间
}))
route.get('/', co.wrap(function* (ctx) {
//-------------------------------------------
logger.debug(' this is test log') //打印日志,日志级别 debug
//-------------------------------------------
if(ctx.session.view === undefined) {
ctx.session.view = 0
} else {
ctx.session.view += 1
}
console.log('viewNum', ctx.session.view)
yield ctx.render('index', {title: 'Nunjucks', content: 'Feifeiyu yeah!'})
}))
route.get('/route/test', co.wrap(function* (ctx) {
logger.info(' this is test log2') //打印日志,日志级别 info
ctx.body = 'feifeiyu nuaa'
}))
app.use(route.routes())
.use(route.allowedMethods())
app.listen(3000, () => console.log('server started, port 3000'))
module.exports = app

7、 启动工程,开启测试, 在控制台输出日志:如下图所示:
logs
如上图所示: 1、级别 INFO 日志名 startup, log config finished! 日志配置完毕
2、级别 INFO 日志名 app - 刚进入系统时打印的日志
3、级别 ERROR 日志名 http - 访问 /mysql-test 目录, 当该目录在系统中不存在, 输出错误
4、级别 INFO 日志名 app - 在路由 / 下 -> 打印的日志
5、级别 INFO 日志名 http - 访问 / 目录 , 路由成功
6、级别 INFO 日志名 app - 在路由 /route/test 下 -> 打印的日志
7、级别 INFO 日志名 http - 访问 /route/test 目录 , 路由成功

8、 根据 log4js.json中配置,生成的日志文件有如下三个(http.log-2016-08-09为非当天日志)
log
在文件 app.log中, 内容同 终端输出的一致
log
在文件中 http.log 中记录的全是 http 请求的日志
log
在文件 errors.log 中记录的都是级别为error及以上的日志
log

二、严重错误邮件提醒

假如发生严重错误时,最好的做法是能够邮件通知到相关责任人, log4js 可以做到这一点
1、 在配置文件 appenders中添加邮件配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"type": "logLevelFilter",
"level": "FATAL", //在输出FATAL级别的日志发送邮件
"appender": {
"type": "smtp",
"recipients": "recipients@foxmail.com", //邮件人邮箱, 如果有多个写成数组
"sender": "sender@163.com", //发件人邮箱
"sendInterval": 60, //邮件时间间隔
"SMTP": { //邮件首发服务配置,这要参考相关邮箱配置, 以163邮箱为例
"host": "smtp.163.com", //邮件服务地址
"port": 25,
"auth": {
"user": "sender@163.com", //邮箱地址
"pass": "password" //登入密码
}
}
}
}

2、 添加邮件处理中间件: nodemailer; npm i –save nodemailer;
注意: 国内很多邮箱仅仅通过配置邮箱地址和密码是无法配置成功的,例如: qq mail。最好找一种只需要地址和密码就可以验证通过的邮箱。 163 邮箱配置时,密码必须使用手机客户端授权密码。