一、前言
开发日志对整个项目可以起到备忘、记录、总结等作用。以帮助开发或者运维人员快速定位错误位置,提出解决方案。
系统没有日志,就等于人没有眼睛(重要性可见一斑)
第一,访问日志 access log(server 端最重要的日志)
第二,自定义日志(包括自定义事件、错误记录等)
所以,日志的存在还是非常非常有必要的!
日志要放在文件中,可读可写~
- node.js 文件操作,node.js stream(流 => 提升性能)
- 日志功能开发和使用
- 日志文件拆分,日志内容分析
二、文件的读写
1、读取文件
接下来,我们先学习如何进行文件的读取…
创建 file-test 文件夹,文件夹下创建 test1.txt 文件 和 data.txt 文件
test1.txt
进行文件读取操作,读取 data.txt 文本的内容,并进行输出
const fs = require('fs') const path = require('path') // 获取文件目录 __dirname 表示当前文件所在目录 const fileName = path.resolve(__dirname, 'data.txt') // 读取文件内容(异步的) fs.readFile(fileName, (err, data) => { if (err) { console.error(err) return } // data 是二进制类型,需要转成字符串类型 console.log(data.toString()) })
data.txt
这是我们在文本中存储的一些信息
Hello 这里是前端杂货铺 感谢你的观看 Thanks
2、写入文件
接下来,我们进行文件的写入操作(分为两种:追加写入和覆盖写入)
test1.js
const fs = require('fs') const path = require('path') // 获取文件目录 __dirname 表示当前文件所在目录 const fileName = path.resolve(__dirname, 'data.txt') // 写入文件 const content = '哇咔咔,这是新写入的内容\n' // 写入的方式(追加'a'/覆盖'w') const opt = { flag: 'a' // 追加写入用'a',覆盖用 'w' } // 写入文件(文件名,内容,方式,错误的回调) fs.writeFile(fileName, content, opt, err => { if (err) { console.error(err) } })
终端运行 node test1.js
3、判断文件是否存在
接下来,我们来进行判断文件是否存在的操作
test1.js
const fs = require('fs') const path = require('path') // 获取文件目录 __dirname 表示当前文件所在目录 const fileName = path.resolve(__dirname, 'data.txt') // 判断文件是否存在 fs.exists(fileName, (exist) => { console.log('exist', exist) })
三、stream 流
1、IO 操作的性能瓶颈
IO 包括 “网络IO” 和 “文件IO”
相比于 CPU 计算和内存读写,IO 的突出特点就是慢!
我们需要在有限的硬件资源下提高 IO 的操作效率!!
那么我们就要使用 stream 流(不是一下子全给,而是通过“小管子”一点点给…)
2、stream 流
在 stream-test 文件夹下创建 test1.js 文件
test1.js
// 标准输入输出 process.stdin.pipe(process.stdout)
下面我们监听端口,通过 postman 进行简单测试
test1.js
const http = require('http') const server = http.createServer((req, res) => { if (req.method === 'POST') { // 管道连接请求和响应 req.pipe(res) } }) // 监听的端口 8000 server.listen(8000)
终端 node test1.js 启动它,之后去 postman 进行测试
3、复制文件
我们先创建 stream-test 文件,之后创建文本(原文本和复制的目标文本,之后在 test1.js 中添加一些代码),此时 data.txt 文本有内容,data-bak.txt 文本为空。
data.txt
这里是前端杂货铺 当前目标如下: 把 data.txt 文本里的内容拷贝到 data-bak.txt 中
test1.js
// 复制文件 const fs = require('fs') const path = require('path') const fileName1 = path.resolve(__dirname, 'data.txt') const fileName2 = path.resolve(__dirname, 'data-bak.txt') // 读取流 const readStream = fs.createReadStream(fileName1) // 写入流 const writeStream = fs.createWriteStream(fileName2) // 管道连接 readStream.pipe(writeStream) // 监听每一次读取的内容 readStream.on('data', chunk => { console.log(chunk.toString()) }) // 监听拷贝完成 readStream.on('end', () => { console.log('copy done') })
4、发起请求读取文件
发送一个 GET 请求,读取文本的内容
test.js
const http = require('http') const fs = require('fs') const path = require('path') const fileName1 = path.resolve(__dirname, 'data.txt') const server = http.createServer((req, res) => { if (req.method === 'GET') { const readStream = fs.createReadStream(fileName1) // 将 res 作为 stream 的 dest readStream.pipe(res) } }) // 监听的端口 8000 server.listen(8000)
终端 node test1.js 运行,之后打开 8000 端口
四、写日志
我们首先改变一下我们的目录结构(新增如下文件)
logs 里面的文件用来存放写入的日志(创建空文件就好),utils 里面的 log.js 文件用来编写一些写入日志的逻辑
og.js
首先我们引入所需模块,封装写入流函数,访问我们所需的日志,进行换行写入
// 引入 fs 和 path 模块 const fs = require('fs') const path = require('path') // 写日志 function writeLog(writeStream, log) { // 关键代码(每写入一行日志换行一次) writeStream.write(log + '\n') } // 生成 write Stream(第二个水桶) function createWriteStream(fileName) { // 找到文件名 const fullFileName = path.join(__dirname, '../', '../', 'logs', fileName) // 创建写入流(追加的方式) const writeStream = fs.createWriteStream(fullFileName, { flags: 'a' }) // 返回写入的内容 return writeStream } // 写访问日志 const accessWriteStream = createWriteStream('access.log') // 参数 log 为 app.js 中传入的内容 function access(log) { writeLog(accessWriteStream, log) } module.exports = { access }
之后更改 app.js 文件,调用 access 函数
app.js
我们先导入 access 进来,之后进行调用,传进所需的参数,用来记录 access log
const { access } = require('./src/utils/log') ... const serverHandle = (req, res) => { // 记录 access log access(`${req.method} -- ${req.url} -- ${req.headers['user-agent']} -- ${Date.now()}`) ...... }
之后,我们打开 http://localhost:8000/api/blog/list 端口,进行三次刷新,查看 access.log 文件中日志的写入
五、写在最后
至此,我们明白了 如何进行文件读写,了解了 stream流 的原理及其基本使用,以及如何写日志。 继续跟进学习吧!
后续会对该项目进行多次重构【多种框架(express,koa)和数据库(mysql,sequelize,mongodb)】
如果你需要该项目的 源码,请通过本篇文章最下面的方式 加入 进来~~