首页 > 其他分享 >Express+Koa2开发接口学习笔记(五)

Express+Koa2开发接口学习笔记(五)

时间:2024-02-08 21:33:41浏览次数:28  
标签:fs const log Express 接口 access Koa2 path 日志

日志介绍

日志可以记录系统的日常和错误行为

系统日志有2种类型:

①访问日志access log(server端最重要的日志)

②自定义日志(包括自定义事件、错误记录等)

系统日志通常是写在一个文件中,而不是写进Mysql或者redis中。

nodejs文件操作

新建一个项目file-text

在目录下创建test.js和data.txt(在txt文件中随便添加几句)

读取文件时需要用到fs库和path库,用来读取某个路径下的文件

const fs = require("fs"); // 文件库
const path = require("path"); // 路径库,统一mac和windows的路径形式

// 当前目录的data.txt文件
const fileName = path.resolve(__dirname, "data.txt");

①读取文件内容

fs.readFile(fileName, (err, data) => {
  if (err) {
    console.error(err);
    return;
  }
  // data是二进制类型,需要转为字符串
  console.log(data.toString());
});

②写入文件

const content = "这是新写入的内容\n";
const opt = {
  flag: "a", // 追加写入,覆盖用'w'
};
fs.writeFile(fileName, content, opt, (err) => {
  if (err) {
    console.error(err);
  }
});

③判断文件是否存在

const exist = fs.existsSync(fileName);
console.log("文件是否存在", exist);

stream操作文件

IO包括“网络IO”和“文件IO”,相比于CPU计算和内存读写,IO的突出特点就是:慢!

如何在有限的硬件资源下提高IO的操作效率?使用stream。

IO操作就是一口气将A桶的水倒入B桶,而stream操作就是通过管道将A桶的水慢慢流入B桶。

// test.js
// 标准输入输出
process.stdin.pipe(process.stdout);

运行node test.js文件,在控制台输入123可以立马看到返回了123。

// 标准输入输出
// process.stdin.pipe(process.stdout);

const http = require("http");
const server = http.createServer((req, res) => {
  if (req.method === "POST") {
    req.pipe(res); // req与res通过pipe建立联系,如果req很大时才会一点一点传过来
  }
});
server.listen(8080);

运行node test.js文件,在postman或者apifox软件请求本地端口8080,在Body输入数据可以看到返回了刚才输入的数据。

有了stream的概念后就可以尝试使用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对象
const readStream = fs.createReadStream(fileName1);
// 写入文件的stream对象
const writeStream = fs.createWriteStream(fileName2);
// 执行拷贝,通过pipe
readStream.pipe(writeStream);
// 每次"一点点"读取的数据内容
readStream.on("data", (chunk) => {
  console.log(chunk.toString());
});
// 数据读取完成,即将拷贝完成
readStream.on("end", function () {
  console.log("拷贝完成");
});

②请求读取某个文件内容

const http = require("http");
const fs = require("fs");
const path = require("path");

// 发起请求,读取文件内容
const server = http.createServer(function (req, res) {
  const method = req.method;
  if (method === "GET") {
    const fileName = path.resolve(__dirname, "data.txt");
    const stream = fs.createReadStream(fileName);
    stream.pipe(res);
  }
});
server.listen(8000);

访问端口8000可以看到data.txt的文件内容。

写日志

在blog项目的根目录下创建logs文件夹,该文件夹下分别创建access.log(访问日志)error.log(错误日志)event.log(自定义事件日志)

在src目录中创建utils->logs.js用来对外提供一个可以写入访问日志的方法。

const fs = require("fs");
const path = require("path");
const env = process.env.NODE_ENV; //环境变量

// 写日志
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");

// 写访问日志
function access(log) {
  // if (env == "dev") {
  //   console.log(log);
  // } else if (env == "production") {
  //   writeLog(accessWriteStream, log);
  // }
  //任何环境都写入访问日志中
  writeLog(accessWriteStream, log);
}
module.exports = {
  access,
};

然后在app.jsseverHandle中使用access方法记录acccess log

const { access } = require("./src/utils/log");

const serverHandle = (req, res) => {
	  // 记录 access log
      access(
        `${req.method} -- ${req.url} -- ${
          req.headers["user-agent"]
        } -- ${Date.now()}`
      );
	...

}

拆分日志

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

crontab

  • 设置定时任务,格式:*****command
  • 将access.log拷贝并重命名为2024-02-08.access.log
  • 清空access.log,继续记录日志

简单脚本

由于是windows系统,所以需要下载Git,借助Git Bash执行脚本文件。

使用Git Bash运行pwd命令获取logs目录的路径

在src->utils下创建copy.sh,添加脚本代码

#!/bin/sh
cd /d/MyLearning/myproject/blog-1/logs
cp access.log $(date +%Y-%m-%d).access.log
echo "" > access.log
  • #!/bin/sh脚本文件头
  • cd进入某个目录
  • cp拷贝命令
  • echo "" > access.log清空并赋值给access.log,也就是将原来的access.log内容清空

使用Git Bash运行cd命令进入src下的utils目录,然后执行命令sh copy.sh,就可以在logs下看到2024-02-08.access.log以及内容被清空的access.log文件

由于是windows系统,这里就没法用crontab命令对copy.sh这个脚本文件设置定时任务

日志分析

  • 如针对access.log日志,分析chrome的占比
  • 日志是按行存储的,一行就是一条日志
  • 使用nodejs的readline(基于stream,效率高)

utils文件夹下创建readline.js

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", (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);
});

在控制台执行该文件,查看结果。

标签:fs,const,log,Express,接口,access,Koa2,path,日志
From: https://www.cnblogs.com/Small-Windmill/p/18012146

相关文章

  • 10_TIM编码器接口
    TIM编码器接口编码器接口简介正交编码器旋转编码器简介编码器接口基本结构工作模式实例(均不反相)实例(TI1反相)编码器接口测速选择接口和定时器接线图代码Encoder.c#include"stm32f10x.h"//DeviceheadervoidEncoder_Init(void){......
  • 接口传送集合数据备份
    //请求路径Stringurl=address+"/priceFreightpriceController.do?outGetMaplist&chargeableWeight="+weight;//url=url+"&data="+jsonString;Gsongson=newGson();//List转String......
  • 如何基于 spdlog 在编译期提供类 logrus 的日志接口
    如何基于spdlog在编译期提供类logrus的日志接口实现见Github,代码简单,只有一个头文件。前提几年前看到戈君在知乎上的一篇文章,关于打印日志的一些经验总结;实践下来很受用,在golang里结构化日志和logrus非常契合,最常见的使用方式如下。logrus.WithField("addr","127.0......
  • Oracle 19c enterprise manager express username password
    *[Oracle19centerprisemanagerexpressusernamepassword-Search](https://cn.bing.com/search?q=Oracle+19c+enterprise+manager+express+username+password&qs=n&form=QBRE&sp=-1&lq=0&pq=oracle+19c+enterprise+manager+express+username+passw......
  • VUE框架CLI组件调用天气接口实现天气界面动态实现和完整工程------VUE框架
    //这句话就等同于我们写的<scriptsrc="vue.js">//这就是在引入vueimportVuefrom'vue';//然后下一步是导入我们的根组件importAppfrom'./App.vue';//导入混入import{mix1}from'./mixin.js';import{mix2}from'./mixin.js';import......
  • python怎么调用支持java的接口
    在Python编程中,有时候需要调用支持Java的接口,以实现与Java程序的交互和功能扩展。本文将介绍如何在Python中调用支持Java的接口,以实现跨语言的开发和集成。一、背景知识在Python中,我们可以使用JPype库来实现Python与Java之间的交互。JPype是一个Python模块,提供了Python与Java之间的......
  • 作为前端leader,如何搭建属于我们公司自己的流水线自动化部署系统(node+express)
    背景:自动化部署系统主要可以集成到公司内部的管理系统中去,比如公司有多个项目,移动端H5,大屏网站,门户网站等...每次发布或者迭代都需要前端同事打包然后在交给运维或者后端同事放到服务器上进行部署,如果有一个项目多个同事合作完成还要走git合并流程,所以我们的目标就是不让前端进......
  • 【Java核心基础】揭秘Iterable接口和Iterator接口的核心区别!
    在Java中,Iterable接口和Iterator接口都用于遍历集合(Collection)中的元素,但它们的使用方式和功能有所不同。官方文档传送门:https://docx.iamqiang.com/jdk11/api/java.base/java/lang/Iterable.htmlhttps://docx.iamqiang.com/jdk11/api/java.base/java/util/Iterator.html核心......
  • UEFI Shell是Unified Extensible Firmware Interface(统一可扩展固件接口)的一部分,它是
    UEFIShell是UnifiedExtensibleFirmwareInterface(统一可扩展固件接口)的一部分,它是一种命令行界面,允许用户在计算机启动时直接与UEFI固件进行交互。UEFIShell提供了一些基本的命令和功能,可以用于管理系统设置、诊断问题、访问硬件信息等操作。为什么使用UEFIShell:系统维护:......
  • DevExpress WinForms中文教程 - 如何创建可访问的WinForms应用?(二)
    为用户创建易访问的WindowsForms应用程序不仅是最佳实践的体现,还是对包容性和以用户为中心的设计承诺。在应用程序开发生命周期的早期考虑与可访问性相关的需求可以节省长期运行的时间(因为它将决定设计决策和代码实现)。一个可访问的WinForms应用程序提供了各种好处,包括:扩大......