【老板要你啥都会系列】| 前端晋升全栈--项目日志

news/2024/4/29 6:57:04/文章来源:https://blog.csdn.net/Lushengshi/article/details/127101114

目录

1.开篇

2.nodejs文件操作

3.stream

4.stream演示

5.写日志

6.拆分日志

7.分析日志介绍

8.readline


1.开篇

   日志包含什么访问人数啊、峰值啊、bug 啊什么的,如果没有日志那么很容易失控。 访问日志可以参考我们 http-server,每次访问都会有这些东西。自定义日志是则并不是每次访问都打印的,根据情况或自己的需要,有点像 console.log。
日志:
  • 系统没有日志,就等于人没有眼睛——抓瞎
  • 第一,访问日志 access log ( server端最重要的日志)
  • 第二,自定义日志(包括自定义事件、错误记录等)

 开发的话自然是打印在控制台,而上线了当然是要把日志保存到文件中。 如果不用 stream 的话,直接操作文件会很大的消耗 cpu 和内存。

目录

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

 日志文件很大自然不可能放到 redis(占超级多内存而且也是异步的,没必要马上记日志)mysql 的话需要表结构(B树)才比较合适(而且文件每个地方都可以访问,不必要安 装 mysql 文件)。

nodejs文件操作

  1. 日志要存储到文件中
  2. 为何不存储到mysql中?
  3. 为何不存储到redis中?

2.nodejs文件操作

   新建一个文件夹 file-test,直接建一个 test1.js,引入两个 node.js 自带的 fs path 库(因为Linux windows 的文件目录路径是不一样的,需要这个 path 来统一)。 再建一个 data.text,随便写点什么作为我们测试的文件。 回到 test1,利用 resolve 方法,__dirname 代表当前文件的目录获取到 data 我们就去读取文件,readFile 方法,异步的 (注意获取的是数据其实是二进制,记得转换成字符串)。
  但是按照目前这种写法,虽然可以打印出 data,倘若这个 data 有 5 G 这么大,我们还这样搞,那么势必是比较浪费性能和内存(一个进程最大也就 3G)的。

   先看怎么写入文件,定义写入的文件,定义 option(flag 为 a 代表 append 追加写入,而 w 是直接覆盖)。然后就可以调用 writeFile(包含四个参数:要被写入的文件、写入的内容、 选项、回调函数)。同理,写入也是有耗费性能的情况(每次写入一行都 writeFile,一直 writeFile,就不停的打开文件,而且也很难写入非常大的数据)。再看看另一个,判断文件是否存在,调用 exists 方法,接收文件名和回调,会返回一个布尔值,注意也是异步。

const fs = require('fs' ) 
const path = require( 'path')const fileName = path.resolve(_dirname, 'data.txt') //拿到要操作的文件//读取文件
fs.readFile(fileName,(err ,data) => {if (err) {console. log(err)return 
}console. log(data.tostring()) //注意拿到的是二进制文件,需要转换成字符串!
})//写入文件
const content ='三星阿卡丽\n'   //随便写入点东西
const opt =flag:'a'
} //定义写入的形式,a代表追加写入
fs .writeFile(fileName, content, opt, (err) => {if (err) {console.log(err) return
}
})

3.stream

    IO 就是输入输出(input 和 output)。网络 IO 常见于视频播放几个 G,不可能直接下载到客户端再看,一来占用内存,二来带宽问题。IO 实在是慢,读写文件发送网络请求什么的。
IO操作的性能瓶颈:
  1. IO包括"网络IO”和"文件IO"
  2. 相比于CPU计算和内存读写, IO的突出特点就是:慢!
  3. 如何在有限的硬件资源下提高I0的操作效率?
借助下图来说,我们之前操作文件就是直接把整个桶给搬起来到到另一个桶,这就要你力气大(硬件资源超好,带宽超强)。但是在资源有限的情况下,那个管子插进去慢慢流就好,慢慢加载。

 

stream

 

 

实际上 request response 都是继承了 stream 的一些特性或者说本身就是 stream

4.stream演示

   新建一个 stream-test 文件夹,新建一个 test1.js。其实这个 pipe 就是 Linux 里面的标准输入出,输入啥打印啥,不用管,std 就是标准的意思,in 就是输入嘛,out 就是输出咯。就演示一下管道,输入就是流入嘛,输出就是流出嘛。接下来演示那个直接返回 request 数据,这里我们 post 的 request 内容就是 response 展示的内容,request response 是桶,用管道连接,是流的关系。当然要是输入的很多,就 会一点点的流过去。 接下来是操作文件对象。
var fs = require('fs')
var path = require( 'path')//两个文件名
var fileName1 = path.resolve(_dirname,
data. txt')var fileName2 = path.resolve(_dirname, 'data-
bak. txt')//读取文件的stream 对象
var readStrekm = fs. createReadStream( fi leName1)
//写入文件的stream 对象
var writeStream = fs.createWr iteSt ream(f i LeName2 )
//执行拷贝,通过pipe
readSt ream. pipe (writeSt ream )
//数据读取完成,即拷贝完成
readStream. on( 'end', function () {
console. log('拷贝完成')
})
创建写入文件和读取文件两个对象(桶)读取文件的话是从 stream 传给返回值,这些都是变成桶与桶然后流转过去,效率非常高。
//直接返Erequest数据
const http = require( http' )
const server = http .createserver((req, res) => {if (req.method === 'POST') {req.pipe(res) //从我们发送的request波到传回来的response,显示在返回结果那里
}
})
server.listen(8008)
创建两个随便的数据文件 data.txt data-bak.txt,导入这两 个文件,分别创建读与写两个 stream 对象(桶)。这个同样可以监听 data end(这样子就知道确实是一点点读取文件的,而传统的操作是一下子都给拿出来)
//复制文件
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 ' )
})
// http请求 文件
const fs = require('fs' )
const path = require('path')
const http = require('http')
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 )

5.写日志

   在 blog-1 下建一个 logs 文件夹,下面建三个文件:access.log、 event.log、error.log。 在 src 下建一个 utils 文件夹,里面建一个 log.js。定义一个 createWriteStream 函数,就是生成右边的桶被写入),由 于只是传入 xxx.log,所以还需要再拼接一下路径,在当前目 录(utils)上翻一层再上翻一层(blog-1),找到下面的 logs 文件夹,再找到传入的文件,就能拿到真正的地址, 根据这个地址去创建流对象(追加方式)然后返回整个对象即可。
   
    将 access.log 传入建一个对应的流对象,然后再定义一个要传给外面的函数 access(传入 log参数)用来写访问日志, 写日志我们统一定义成一个函数 writeLog,接收流对象和 log,直接调对象的 write 方法,传入需要写的内容即可记得换行),在 access 调用这个方法即可,其它的日我
们就不管了,也是一样的道理。 那 么 怎 么 去 用 呢 ? 回 到 aoo.js 获 取 access 方 法 , 在serverHandle 使用,把 methodurluser-agent、当前时间 戳传入。由于是通过流写入的,效率很高,每次访问都可以写入东西。


6.拆分日志

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

 这个由于服务器基本都是 Linux 和类 Linux 的,定时任务的话 windows 可能没办法实现,所以这一块可以了解下即可,主 要是运维的搞。 解释一下*代表什么意思,第一个*代表分钟(如果不写具体 的值保持*就代表忽略,比如 1 * * * *就代表每天的第一分钟执行这个命令)第二个*代表小时(12***代表每天的第二个小时的第 1 分钟执行)第三个是日期第四个是月份第五个是 星期。command 就是一个 shell 脚本。

crontab:

  • 设置定时任务,格式: **** * command
  • 将access.log拷贝并重命名为2019-02-10.access.log
  • 清空access.log文件,继续积累日志
这个完全不需要修改代码,所以肯定是运维来搞,不过了解也是可以的。Node.js 当然也能做这个,但是就比操作系统隔了一层,不如直接通过操作系统的 shell 脚本来操作更加便捷 和高效(也好分离代码)。 回到 utils,建一个 copy.sh(即 shell 脚本),第一行是固定的即 shell 的执行文件,将 logs 的路径拷贝过去,cd logs, 拷贝 access.log 重命名为当前时间的 access.logecho 移动空字符串到 access.log 相当于清空 access.log。然后在 Linux 下面执行就行了!

7.分析日志介绍

接下来就是使用 crontab 了,因为前面已经编写好了 shell 脚本,通过输入 crontab -e 进入编辑器,设置时间,执行脚本的时候需要将整个脚本的路径拷贝过去才行。
日志分析:
  1. 如针对access.log日志,分析chrome的占比
  2. 日志是按行存储的, - -行就是一条日志
  3. 使用nodejs的readline ( 基于stream , 效率高)

 通过 readline 可以一行行的去查看日志,我们先去不同浏览器运行下不同的地址,创造出不一样的 logs。


8.readline

获取到不同浏览器的日志后,我们回到 utils 下面建一个readline.js,引入 fspathreadline。拿到 access.log,并且 基于这个建一个 readStream(因为是读操作)。再调用 createInterface 创一个 readline 对象,输入就是流对象。 定义一个储存 chrome 数量的变量和储存总数的变量,on 监 听 line,每读完一行就会触发。通过--切割数据,第 3 个即数组[2]就是有关浏览器信息的,看看否包含 Chrome 决定加减。
const fs = require( ' fs' )
const path = require( 'path' ) 
const readline = require('readline')//创建流对象(读取)
const fileName = path. join(__ dirname, '../', ' ../', 'logs' , access.log' )
const readstream = fs.createReadstream( fileName)//创建readLine对象
const rl = readline.Interface({input: readstream 
})//定义存放浏览器类型的变量
let chromeNum = 0
letsum=e

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_16008.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

谐振波导光栅的严格分析

摘要 谐振波导光栅(RWG)由于其在波长、相位和偏振等方面的可调谐性,在研究和工业中有着广泛的应用。RWG的结构包含一个薄的高折射率波导薄膜,该薄膜与光栅接触。波导支持多种导模,并且根据厚度的不同,模式的数量也不同。在这个…

javaFx打包exe程序

文章目录将代码打成jar包准备工作下载exe4j定制jre检测jar包用到jre的哪些jmods生成jre准备exe图标使用exe4j将jar转换成exe程序将代码打成jar包 打jar之前,把那些用不到的依赖统统删除,以免包含一些无用的内容,比如用不上的一些依赖jar&…

特征工程之特征降维-特征选择-PCA/LDA

特征降维之特征选择 特征选择是建模中常用的降维手段,比较暴力,直接将不重要特征删除。 缺点:造成信息丢失,不利于模型精度。【与之形成对比的是PCA、LDA等降维方式。】 主要标准有两个: 特征是否发散。特征与目标的…

简单组件讲解

在编程阶段,会遇到有些页面的某一区域的布局或数据显示类似;那么我们就可以复用这一段代码;在使用原生JS编程时,我们习惯是将代码抽出来自成一个文件,需要时引入即可。而在vue中也存在这样一个模块,可以简便的将可复用的代码抽成一个模块,这个就是组件。在很多人看来,组…

产品-如何让用户“更愿意“付费

学院课程 文章目录学院课程前言如何提高用户体验,吸引用户付费关于程序员等级的划分基础免费试看优质博客内容转化为视频用户关于短视频内容的生成关于利用用户的碎片化时间怎么差异化竞品?短视频赛道理解学院现状分析总结前言 学院地址 今天下午公司组织了一场需求…

线性回归

线性回归 导入库 import numpy as np import pandas as pd import matplotlib.pyplot as plt人工数据集n = 100 true_theta = np.array([[1], [1]]) X = np.insert(np.random.normal(5, 1, size=(n, 1)), 0, 1, 1) y = X @ true_theta + np.random.normal(0, 0.04, size=(n, …

Azure | AZ-204 认证之旅-应用服务(二)

theme: orange 我正在参加「掘金启航计划」 Web应用是构建在PaaS层的服务,它是支持托管的,并且是可缩放的,极大提高了工程效率,并且减少了在运营的层面的消耗,这篇文章介绍如何创建应用程序服务。 创建Web应用程序服务…

pytorch深度学习训练模板(分类、回归)

前言 LeNet-AlexNet-ZFNet: LeNet-AlexNet-ZFNet一维复现pytorch VGG: VGG一维复现pytorch GoogLeNet: GoogLeNet一维复现pytorch ResNet: ResNet残差网络一维复现pytorch-含残差块复现思路分析 DenseNet: DenseNet一维复现pytorch 包含所有一维经典模型的代码可随意切换训练 …

云原生技术 --- k8s节点组件之kube-proxy的学习与理解

k8s 网络代理(kube-proxy)在每个节点上运行。网络代理反映了每个节点上 Kubernetes API 中定义的服务,并且可以执行简单的 TCP、UDP 和 SCTP 流转发,或者在一组后端进行 循环 TCP、UDP 和 SCTP 转发。但是,必须要有一个插件,才可以…

毕业设计- 基于单片机与GPS+GSM的车辆定位跟踪系统

文章目录0 前言1 简介2 主要器件3 实现效果4 硬件设计Maduino Zero A9G GPRS/GPSk开发板这款低功耗A9G使用SIM800/900和NEO-6M GPS模块的基于Arduino的GPS跟踪系统5 软件说明使用Arduino的基于GPSGSM的车辆跟踪系统GPSGSM的车辆跟踪系统的代码6 最后0 前言 🔥 这两…

IDEA中使用Git

目录 一、IDEA中使用Git 配置Git settings ——>Version Control——>Git 点击Test测试版本号 下载gitee插件 配置账户 第一种方式:账号密码 第二种方式:通过Token令牌 分享单个项目 组员需要拿到项目的SSH地址 二、总结 一、IDEA中使用G…

万物互联时代到来,猿代码领衔先计算机赋数据化转型

社会经济的高速发展推动着各行各业进行转型升级,而数字经济则是当前社会经济发展的强大驱动。根据相关报道显示,早在多年前我国数字经济规模总量便达到万亿元规模,占2016年全年GDP比重的30%。数字经济的飞速发张需要强劲算力的支撑…

wxpython设计GUI:grid控件实现显示表单数据功能,同时实现界面的上下翻页以及跳转功能

grid控件实现显示表单数据功能,同时实现界面的上下翻页以及跳转功能。 1. 效果展示 2. 代码实现 #!/usr/bin/env python # -*- coding: utf-8 -*- # Author: Logintern09########################################################################### ## Python …

【图像分割】基于matlab直方图的自适应阈值方法分割前景与背景【含Matlab源码 2144期】

一、一种基于直方图的实时自适应阈值分割方法简介 1 引言 在交通管理中,为了获得车辆的运动数据,需要对交通视频进行实时监测,从监测图像序列中检测出运动对象,并对运动对象进行分析处理,从而获得车辆和行人的运动数据…

EMQX Cloud 影子服务:便捷数据缓存服务,加速 IoT 应用开发

全托管 MQTT 消息云服务 EMQX Cloud 可以帮助用户轻松将各类物联网设备连接上云,提供与各类第三方服务的数据集成,助力用户进行高效的数据处理、存储与分析。 为了实现更加便捷的物联网数据处理,进一步简化用户构建物联网应用的开发流程&…

好心情精神心理科:抑郁症,真的会让你变丑!

有患者向好心情平台咨询:“抑郁症多年,我总感觉自己变丑了,脸色也不咋好看,这到底是我的心理作用,还是容貌真有变化呢?” 变丑这件事,不致命,但对于很多人来说,却似乎难…

net转java学习笔记-sqlserver的问题记录

最近公司有个.net项目,用的不是mysql是sqlserver,中间遇到几次问题记录下。 1.navicat连接sqlserver失败 百度了一下这个是缺少了驱动,其实navicat自带了这个驱动,没有安装而已。 打开Navicat的安装路径,Navicat自带s…

qsort:我很强,了解一下(详解过程)

了解qsort,以及模拟实现🎑情境引入🎈qsort📖qsort的头文件📄开场🔑qsort的参数🤔为什么可以对任意类型排序呢?📜参数参数①参数②参数③最难的参数④🎃qsort应…

一个完全纯净的windows资源站

网址:https://hellowindows.cn/ hello Windows呢是一个纯净的Windows系统下载网站,从已经淘汰的xp到新推出的win11,大部分的系统版本都涵盖了 且都是中文版本,更加方便 windows server版本也包括在内哦

17 -- 排序算法之希尔排序

希尔排序算法介绍: 希尔排序是希尔于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序。 写入排序法的基本思想: 希尔排序十八记录按下标的一定增量分组,对每组使用直接插入算法排序:随着增量逐渐…