node中stream与日志管理

                                                                          node中stream与日志管理

    日志:用于记录上线之后的一些信息,因为在上线之后可能会产生bug,可以通过查看日志来查询bug。也可以通过查看日志来查询每天的访问的各种信息,例如:访问的浏览器  系统等。那么对于日志的开发需要处理那些方面呢,总结概述为下面的三个方面:

    1.nodejs文件操作,nodejs stream
    2.日志功能开发和使用
    3.日志文件拆分,日志内容分析

那么日志存在文件之中的原因又有那些呢,总结为以下几个方面:

1.文件中的内容可以转到各个服务器上去计算运行,不需要配置。
2.日志中的内容只是一条一条的信息,本身对内存性能上的要求并不是太高
3.不存在mysql中的原因是,mysql是硬盘数据库,里面存放的是各表之间的某种关联关系,如果要将日志中内容放在其他服务器进行分析,使用MySQL则需要在服务器中对mysql进行配置以及保证各服务器上的数据库必须保证一致
4.不存在redis当中是因为redis是内存数据库,日志会随着时间的推移而变得越来越多因此,如果使用redis是非常的不划算的。因为redis中的内存是非常宝贵的,日志对于性能的要求不太高,因此不需要。

因此在这里需要去进行说明的就是在node中如何去操作stream,那么接下来就用一个实际的例子来说明。首先创建两个文件,第一个文件将其命名为data.text,第二个文件将其命名为index.js。第一个文件用于去存放日志中的信息,第二个文件用于去读写日志。具体的实现过程如下:

// 需要引入两个文件,一个fs,用于对文件做一系列操作, 引入path,获取文件的路径
const fs = require('fs');
const path = require('path');

//获取文件的位置,通过path.resolve()来寻找
const fileName = path.resolve(__dirname,'data.txt');

//读取文件
fs.readFile(fileName,(err, data) => {
    if(err){
         console.error(err);
        return;
    }
   //此时获取到的文件格式是二进制的需要使用toString将其转换成字符串
     console.log('data is \n',data.toString())
 })

//写入文件
const content = '\n这是新写入的内容';
const opt = {
    flag: 'a' //'a'表示新追加的内容  'w'表示覆盖的内容
}
//需要在writeFile中传入四个参数,第一个参数表示需要写入的文件的路径,第二个参数表示要写入的内容  第三个参数表示要写入的方式
//第四个参数传入一个错误类型之后的反应
fs.writeFile(fileName , content , opt , err => {
    if(err){
        console.error(err);
    }
})

将第二个文件中引入上面的代码,即可实现写入和读文件操作。

了解完在node中如何读取文件之后,之后的内容就可以了解stream了。对于之前的I/O读取有以下的几个缺点

1.IO包括 “网络IO”和“文件IO” 两者都有一个共性在输入与读取文件的时候,都是将IO操作中的数据读取完之后,才进行下一步的操作,很显然这样的处理方式是非常的不可取的。
2.相比于CPU计算和内存的读写,IO操作的速度就非常的慢了。

因此针对于上面文件的不足,在此就引入stream来进行优化,即:在有限的硬盘资源下,提高IO操作的速率的方法,就是使用流的思想。stream由三个部分组成 resource  pipe  deststream的思想就是缓冲思想,将文件初始中的数据先通过pipe给dest,然后就这样一直传送数据,最后直至到文件传输完成,即可完成文件传送过程,这也就是去提高IO操作效率的方法

  因此在stream中其标准的输入输出为以下的方式:process中,std表示标准  in  out表示输入与输出  pipe表示连接的管道,下面的这种输入输出方式是标准的输入与输出通过process来进行管理process.stdin.pipe(process.stdout)。因此对于stream流文件的实现过程就用下面的代码实例所展示一般:

//将req  res以stream的方式连接
const http = require('http');

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

//使用stream进行文件的copy,实现部分的代码如下:
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');
})

//将文件中的内容读入,并通过res返回,具体的实现代码如下
const http = require('http');
const fs = require('fs');
const path = require('path');
const fileName1 = path.resolve(__dirname, 'data.txt');
const readStream = fs.createReadStream(fileName1)

const server = http.createServer((req,res) => {
    if(req.method === 'GET'){
        readStream.pipe(res);
    }
})

server.listen(8000);

至此为止关于流的操作到此就结束,下面部分讲解的就是如何使用stream来处理日志

1.在博客的服务器端去书写日志
      首先需要去创建一个logs的文件夹,里面放的是各种的日志文件,然后在src目录下创建一个工具文件并且命名为utils并在这个文件下面去创建一个logs.js的文件,用于去写文件  具体的实现代码如下:首先引入nodejs自带的文件fs以及path
const fs = require('fs');
const path = require('path');

然后再生成一个写的文件流
//生成写文件流
const createWriteStream = (fliename) => {
    //join()中的内容所说的是上两级目录下的logs下的文件
    const fullFileName = path.join(__dirname, '../' ,'../' , 'logs' ,fliename);
    const writeStream = fs.createWriteStream(fullFileName , {
        flags: 'a' //表示在文件中追加内容
    })
    return writeStream;
}

然后再创建一个写日志的文件
const writeLog = (writeStream, log) => {
    writeStream.write(log + '\n'); //写入内容
}

最后就是写访问日志,再将这个方法导出
//写访问日志
const accessWriteStream = createWriteStream('access.log');

const access = (log) => {
    writeLog(accessWriteStream  ,log);
}

module.exports = {
    access
}

最后在app.js文件中去记录这个文件主要记录的内容有
req.method req.url  req.headers['user-agent']  Date.now()

最后进行的就是日志拆分,那么为什么要进行日志的拆分呢,原因是我们需要对日志进行定时的管理,因为存储的文件是有限的。对于日志的拆分我们做一个了解即可,因为在这个部分由专门的运维人员来进行,在这里就主要叙述日志拆分的过程

1.日志的内容会随着时间的增加而增多,放在一个文件当中不好处理,因此需要我们去进行拆分
2.日志的拆分方式,在通常的情况下采用的方式都是按照时间来划分
3.实现方式通常的情况下都是linux的crontab命令,即定时任务来完成
4.虽然node也可以来对日志进行拆分,但是去定时的启动,其是在操作系统之上的软件部分定义的,而linux则是定义在
操作系统之上的,所以可以完成定时任务
5.设置定时任务,其格式: *****command,*****代表需要定时更新日志的时间
6.将access.log拷贝并且重新命名为年月日.access.log
7.清空access.log文件,继续积累日志

具体的实现过程如下:

1.首先是在utils文件下,新建copy.sh文件(在进行日志拆分的时候要记住需要在linux系统下才能完成)、
2.在copy.sh中写入下面的代码:
  # ! bin/src
  cd 日志文件路径
  cp access.log $(date +%Y-%m-%d).access.log //%Y-%m-%d表示年月日
  echo "" > access.log //将access.log文件中的内容清空

定时拆分日志时,需要使用crontab -e进入编辑
然后使用* 0 * * * sh加上日志文件目录  
然后就可以定时的触发脚本

在nodejs中提供了一个readline主要用于去分析日志  日志中的存储是一条一条数据这样的形式所储存的、因此在这里就可以很轻易的来分析日志,对于不同的功能由不同的处理方式,在下面实现的功能中主要是去分析所有的浏览器中chrome所占的比例,具体的分析日志的代码如下:

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

//获取文件名
const fileName = path.join(__dirname, '../' , '../' , 'logs' ,'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' , dataLine => {
    if(!dataLine){
        return;
    }

    sum++;
    //分析日志中的chrome
    const arr = dataLine.split(' -- ');
    if(arr[2] && arr[2].indexOf('Chrome') > 0){
        chromeNum ++ ;
    }
})

rl.on('close' , () => {
    console.log('占比为',chromeNum / sum)
})

说到这里关于日志的处理过程就叙述完毕,再来总结以下整个的过程I/O读取,stream读取,使用stream进行日志管理,日志拆分,日志分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值