node 日志与文件操作

日志

  • 第一,访问日志 access log(server端最重要的日志)
  • 第二,自定义日志(包含自定义事件、错误记录等)

文件操作 node.js stream

使用到两个基础库

const fs = require('fs')
const path = require('path')

使用到path基础库是因为,不同的操作系统的路径拼写是不同的,所以在编写代码的时候需要同一路径

获取文件

通过path.resolve(文件路径)获取文件

const fileName = path.resolve(__dirname,  'xxx.txt')

__dirname 指向为当前文件夹
xxx.txt 为需要获取的文件

读取文件内容

通过fs.readFile(文件,(err,data)=>{})读取文件内容

注意:这是一个异步函数,获取到的data是一个buffer类型(二进制)需要将其转为字符串形式的

fs.readFile(fileName, (err, data) => {
    if (err) {
        console.err(err)
        return
    }
    console.log(data.toString())
        
})

写入文件

通过fs.writeFile(文件,写入的内容,写入的形式,回调)

注意:异步函数,写入的形式是一个对象类型

const opt = {
    flag:'a' // 追加写入,覆盖的话就使用'w'
}
const content = '新写入的内容'
const opt = {
    flag:'a'
}
fs.writFile(fileName, content, opt, (err) => {
   	if(err) {
        console.log(err)
    }
})

判断文件是否存在

通过fs.exist(文件名,回调)

fs.exist(fileName, exist => {
    console.log('exist', exist)
})

回调中返回的参数是用户判断这个文件是否存在

  • true-文件存在
  • false-文件不存在

stream

类似网络视频,在你观看视频的同时,视频在加载,而不是视频加载完之后,传递到客户端进行观看

// 标准输入输出,pipe就是管道(符合水流管道的模型图)
// process.stdin 获取数据,直接通过管道传递给 process.stdout
process.stdin.pipe(process.stdout)

process是标准的意思

执行以上代码:

输入:123
输出:123

输入:147
输出:147

【案例】

const http = require('http')

const server = http.createServer((req, res) => {
    if (req.method === 'POST') {
        req.stdin.pipe(res)
    }
})

server.listen(8000)
  1. 获取http库
  2. 创建服务,当请求的方式为POST时,获取req的数据直接返回给res
  3. 监听8000端口

stream操作文件

拷贝文件
const fs = require('fs')
const path = require('path')

// 两个文件名
const fileName1 = path.resolve(__dirname, 'data.txt')
const fileName2 = path.resolve(__dirname, 'data-bak.txt')

// 读取文件的stream对象
let readStream = fs.createReadStream(fileName1)
// 写入文件的stream对象
let writeStream = fs.createWriteStream(fileName2)

// 执行拷贝,通过pipe
readStream.pipe(writeStream)

// 数据读取完成,即拷贝完成
readStream.on('end',function () {
    console.log("拷贝完成")
})

日志功能开发和使用

// src/untils/log.js
const fs = require('fs')
const path = require('path')

// 写日志
function writeLog(writeStream, log) {
    writeStream.write(log+'\n') // 关键代码
}

// 生成 write Stream
function createWriteStream(fileName) {
    // join是用于拼接目录的
    const fullFileName = path.join(__dirname,'../','../','logs',fileName)
    const writeStream = fs.createWriteStream(fullFileName,{
        flags:'a'
    })

    return writeStream
}

const accessWriteStream = createWriteStream('access.log')

// 写访问日志
function access(log) {
    writeLog(accessWriteStream, log)
}

module.exports = {
    access
}
const { access } = require('./src/utils/log')

.......

access(`${req.method} -- ${req.url} -- ${req.headers['user-agent']} -- ${Date.now()}`)

日志文件拆分

  • 日志内容会慢慢积累,放在一个文件中不好处理
  • 按照事件划分日志文件,如2022-1-22.access.log
  • 实现方式:linux的crontab命令,即定时任务

crontab

  • 设置定时任务,格式*****command
    • 第一个*代表分钟
    • 第二个*代表小时,比如*1***command代表每天的第一个小时执行
    • 第三个*代表日期,每个月的多少日来执行
    • 第四个*代表月份
    • 第五个*代表星期,星期是0-6
  • 将access.log拷贝并重命名为2022-1-22.access.log
  • 清空access.log文件,继续积累日志

日志分析

  • 日志是按行存储的,一行就是一条日志
  • 使用nodejs的readline(基于stream,效率高)
const fs = require('fs')
const path = require('path')
const readline = require('readline')

const fileName = path.join(__dirname,'../','../','log','access.log')

// 创建read stream
const readStream = fs.createReadStream(fileName)

// 创建readline对象
const rl = readline.createInterface({
    input:readStream
})

let chromeNum = 0
let sum = 0

// 逐行读取
rl.on('line', lineData => {
    if (!lineData) {
        return
    }
    // 总行数
    sum++

    const arr = lineData.split(' -- ')
    if (arr[2] && arr[2].indexOf('Chrome') > 0) {
        chromeNum++
    }
})

// 监听完成
rl.on('close', () => {
    console.log("chrome的占比" + chromeNum/sum)
})

重要点总结:

  1. 使用readline的line事件进行逐行读取日志
  2. 使用readline的end事件进行 读取完毕之后的业务处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值