木灵鱼儿
阅读:1833
koa框架29 日志
我找了很多个插件,发现都好难用,npm哪里的说明等于没有,你根本不知道他哪些配置参数怎么弄,百度的文章真的是五花八门,不是抄就是缺胳膊短腿, 想来想去还是自己写好了。
日志的格式我是仿 koa-logger,我感觉他这个样式还不错,但是他这个插件只能console输出,如果是测试环境,还行,但是上线后作为日志保存,就不太行。
我尝试去用他的方法去保存,会乱码,编码我也设置为utf8了,所以无解啊。(超蛋疼有没有)
预览
相对来说还是比较简单。
原理
通过中间件的形式,正常请求和发生错误,为此,我们需要创建一个全局的错误处理中间件,在这个里面我们触发自己写的日志方法。
const logger = require("./libs/logger");
//全局错误处理
server.use(async (ctx, next) => {
try {
await next();
//日志
logger(ctx);
} catch (e) {
//日志
logger(ctx, e);
}
});
我们可以看到,我们将ctx对象和e对象传入了,有e的话就是报错了,没有就是正常。
然后我们创建一个模块logger.js
const fs = require("promise-fs");
const path = require("path");
const {
log_path
} = require("../config");
const moment = require("moment");
const option = {
flag: "a"
};
//定时删除文件 7day
setInterval(async () => {
try {
const dirArr = await fs.readdir(log_path);
// [ '2020-09-05.log', '2020-09-06.log' ]
if (dirArr.length) {
dirArr.forEach(async dir => {
//如果这个文件已经超过七天了就删除
const currentTime = moment().format("YYYY-MM-DD");
const outTime = moment(dir.split(".")[0]).add(7, "d").format("YYYY-MM-DD");
if (moment(outTime).isBefore(currentTime)) {
await fs.unlink(path.join(log_path, dir));
}
});
}
} catch (e) {
console.log("自动删除日志文件失败", e);
}
}, 7 * 24 * 60 * 60 * 1000);
module.exports = async function(ctx, error) {
//解构
const {
request,
response
} = ctx;
//文件路径
const filePath = path.join(log_path, `${moment().format("YYYY-MM-DD")}.log`);
//信息
let message = `>> ${request.method} ${request.url} ${moment().format("YYYY-MM-DD HH:mm:ss")} \r\n`;
//是否有错误
if (!error) {
//信息
message += `<< ${request.method} ${response.status} ${response.message} ${moment().format("YYYY-MM-DD HH:mm:ss")} \r\n`;
} else {
//信息
message += `<< ${request.method} ${response.status} ${response.message} error: ${error.message} ${moment().format("YYYY-MM-DD HH:mm:ss")} \r\n`;
}
//写入
await fs.writeFile(filePath, message, option);
}
使用了promise-fs,他的方法和fs差不多,不过是promise封装,然后还使用了path进行地址拼接,从config配置文件里读取日志的目录,使用了moment 用于时间操作。
fs模块支持第三个参数为配置,默认是覆盖文件模糊,我们改为a模式,这样就是追加模式。
然后就是对ctx对象的信息进行提取,然后合成一个字符,然后fs写入。
难点可能就是自动清理日志文件了。
我设置7天清理一次,先读取目录,获取一个目录下所有文件名的数组,通过split获取到文件名,文件名是时间。
然后通过moment 的方法,判断过期时间是否在当前时间之前。
比如15号是否在23号之前,15号是过期时间,在他之前肯定就是已经过期了,需要删除,然后我们进行删除。
需要注意一下就是这个重复定时间时间不要设置太短,你设置个10ms,肯定会报错的,因为文件可能刚删除了,你又来删除,速度太快也是不行的。
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。
相关推荐
centos 安装最新版 node.js
[hide]先用yum 安装一次node先升级yum update 提示下载程序,回复y安装nodeyum install nodejsyum安装的node一般都不是最新的,所以我们还需要升级node的版本npm i n -g全局安装一个n插件n lts表示安装最新的稳定版!一些常用命令n ls查看已安装的node版本n rm 16.0.3删除16.0.3版本更多功能阅读插件文档:n等待安装完毕后,此时其实版本已经安装好了,但是输入node -v还是低版本,是因为centos的用户缓存问题。我们退出登录再登录就会刷新缓存了,此时的node -v输出的就是最新版本exit 退...
node npm yarn 如何同时运行多个指令
node的bash命令其实是有对应的指令字符的,但是,这个指令只能再linux,mac上才有生效,再windows是无效的,所以了解一下就行。命令说明&&顺序执行多条命令,当碰到执行出错的命令后将不执行后面的命令&并行执行多条命令||顺序执行多条命令,当碰到执行正确的命令后将不执行后面的命令|管道符windows上进行多命令"scripts": { "dev": "cross-env NODE_ENV=development webpack --env development --progress -...
koa教程2 HttpBearerAuth 传递token
前端发送token到后端,一般有三种方式:链接中携带token,query参数post这种请求body中携带token头信息携带token但是事实上http已经为我们提供了传token的方式,是一个相对来说比较安全的方式,就是HttpBearerAuth 其实他也是一个头信息来着,只是相对来说多了一点操作,在apipost软件中,我们可以直接可视化设置如果是axios,则是需要添加一个头信息:axios({ method: 'get', url: url, responseType: 'blob', headers: { 'Authoriz...

koa教程2 微信openid登录
微信的openid,前端登录时,会发送一个code码到后端,后端接收到这个code,然后配合appid、appsecret参数,像wx发送一个get请求。wx的请求地址:GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code具体查看文档:微信官方文档-服务端可以看到这段get请求有四个参数:属性类型默认值必填说明appidstring 是小程序 appIdsecretstring 是...
koa教程2 权限分级控制
在之前的代码中,我们使用了一个scope属性来表示用户的权限,但是scope是一个数字,他的阅读性是非常差的,当其他人开发的时候,可能并不知道你这个数字是什么意思?所以,我们需要将它转义成文本。为了方便判断,我们在enum.js中增加一个用户等级的对象enum.js://通用判断是否存在该类型 function isThisType(val) { let flag = false; Object.keys(this).find(key => { if (this[key] === val) { return flag = true; } })...
koa教程2 token鉴权
之前我们在token中传入我们的自定义参数,现在我们要做一个token鉴权,很简单,如果他的token合法,就可以访问这个路由,如果不合法,就打回。这个也不能说是真正意义上的鉴权,因为他还没有判断scope值,所以只能说是简单判断。做这个判断我们就可以通过中间件的形式,于是我们在middlewares目录下创建一个auth.js文件auth.js:const parseBearerToken = require("@utils/paresBearerToken"); const jwt = require("jsonwebtoken"); cons...
koa教程2 用户登录
登录类型用户注册之后,自然是用户登录,登录的时候我们需要考虑到登录的方式,往往在正式的项目里面,登录的方式可能会有很多种:账号密码登录手机号登录小程序一键登录那么我们登录的时候就要进行判断,设置一个type的属性,用于在登录时判断用户是什么类型的登录,这个由前端那边设定参数。type:1为账号密码登录,2为手机号登录,3为小程序一键登录作为判断,我们可以写一个查询表(枚举),在项目根目录创建一个lib目录,在里面创建一个enum.js文件。enum.js://通用判断是否存在该类型 function isThisType(val) { let flag = false; Obje...
node 自定义路径别名
用过vue cli的话,对路径中的@应该不陌生,他表示根目录,但是在node的环境里面,我们编写模块并引入时,并没有这种方便的写法。在node环境中,我们可以通过process.cwd()来表示根目录,但是这样的话,每次使用绝对路径引入,路径总是需要写一大堆拼接。const db = require(`${process.cwd()}/config/config`).database;这样略显麻烦,于是我们可以在全局写一个引入插件的方法:global.myRequire = function (path) { return require(`${process.cwd()}/${pa...
koa教程2 密码加密
默认情况下,我们通过User.create({ email, password, nickname });模型传入的数据,是无加密的,也就是说,在数据库中密码是明文显示的,这样肯定是不行,我们需要使用bcrypt插件进行加密yarn add bcryptjs --dev打开models/user.jsuser.js:const bcrypt = require("bcryptjs"); const { sequelize } = require(`${process.cwd()}/core/db`); const { Sequelize, Model, DataTy...

koa教程2 使用sequelize连接数据库,创建用户模型
数据库的连接处理,我们需要使用sequelize插件。这个插件还有对应的数据库驱动,如果是使用mysql,那么驱动是mysql2,具体可以查看中文版的入门教程:入门yarn add sequelize mysql2 --dev安装完成后我们先需要创建数据库连接。连接数据库在根目录/core目录**下创建一个db.js文件用于连接数据库。在连接数据库之前,我们需要一些数据库的参数,如账号,密码,端口,数据库名字,数据库地址,为了方便管理配置,我们在根目录创建一个config目录,里面存放一config.js文件 ,这个之前的教程我们就已经创建好了。config.js:module.expo...