使用express.js+socket.io实现在线实时查看日志文件内容,不用到服务器上看日志文件了我使用express
前言
前段时间使用midway做了一个后端服务上线了,用户量还挺大的,因为自己没做充分的测试,导致线上有些bug,为了定位bug,我在关键位置打了一些日志。
当用户和我说,XXX功能不能使用了,我就去看看日志定位问题,然后修复bug。
因为是小项目,记录日志我没有使用一些在线平台,而是把日志以文件的形式放到了服务器上。导致我需要看日志的时候,还要把日志文件下载到本地查看。
这样太麻烦了,如果能在线看就好了,从网上找了一下,没有找到合适的,所以打算自己写一个。花了大概半天时间就写完了,下面和大家分享一下这个脚本的实现过程。
服务使用教程
安装全局依赖
npm i simple-logs-viewer -g
安装成功后,在日志目录下,执行命令
simple-logs-viewer
网页默认使用30070端口,访问 http://localhost:30070
如果不想使用默认端口,可以指定端口
simple-logs-viewer 3001
如果想在服务器上后台运行服务,可以screen
命令
安装 screen
命令
# CentOS
yum install screen
# Debian/Ubuntu
apt install screen
启动一个screen
screen -S session_name
session_name是你给这个screen会话起的名字。
启动成功后,在这个窗口启动simple-logs-viewer服务,即使把终端关掉,服务也不会断掉。
演示
在服务器使用screen启动一个新的会话
screen -S 1
进入日志目录
cd /root/logs/项目名称
运行 simple-logs-viewer
服务
simple-logs-viewer
在服务器把30070端口开放出去,通过 http://公网ip:30070
就可以访问了
查看日志内容
手动修改当前文件,模拟日志文件变更
点击箭头,查看最新内容
支持查看java、nestjs、原生node使用winston库生成的日志文件
实现过程
初始化express项目
找一个空文件夹,创建项目
npm init -y
安装express
npm i express
在项目根目录下创建index.js文件
const express = require('express');
const app = express();
// 当对主页发出 GET 请求时,响应“hello world”
app.get('/', (req, res) => {
res.send('hello world');
});
app.listen(3000, () => {
console.log('启动成功,访问http://localhost:3000')
})
在项目终端中,使用node启动项目
node index
在浏览器中访问 http://localhost:3000
现在每次改东西都需要重新执行一下node命令,可以使用nodemon
库自动重启服务,先安装nodemon
npm i nodemon
在package.json
文件里配置start
命令
{
"start": "nodemon index.js"
}
启动项目
npm start
改动文件保存后,会自动重启服务
实现日志文件列表
获取当前启动服务的文件夹地址
// 获取当前启动服务的文件夹地址
const dirPath = process.cwd();
使用fs
里的readdir
方法获取当前文件夹下的所有文件
使用浏览器访问 http://localhost:3000
获取文件大小和最后修改时间,并按照最后修改时间倒序排序,返回给前端
在utils.js
文件里添加两个format方法
/**
* 将日期对象格式化为 YYYY-MM-DD HH:mm:ss 格式的字符串
*
* @param dateObj 要格式化的日期对象
* @returns 格式化后的日期字符串
*/
function formatDateTime(dateObj) {
const year = dateObj.getFullYear();
const month = ('0' + (dateObj.getMonth() + 1)).slice(-2);
const date = ('0' + dateObj.getDate()).slice(-2);
const hours = ('0' + dateObj.getHours()).slice(-2);
const minutes = ('0' + dateObj.getMinutes()).slice(-2);
const seconds = ('0' + dateObj.getSeconds()).slice(-2);
return `${year}-${month}-${date} ${hours}:${minutes}:${seconds}`;
}
/**
* 格式化文件大小
*
* @param size 文件大小,单位为字节
* @returns 返回格式化后的文件大小字符串,单位为 bytes、KB 或 MB
*/
function formatFileSize(size) {
if (size < 1024) {
return size + ' bytes';
} else if (size < 1024 * 1024) {
return (size / 1024).toFixed(2) + ' KB';
} else {
return (size / (1024 * 1024)).toFixed(2) + ' MB';
}
}
module.exports = {
formatDateTime,
formatFileSize,
}
查看返回结果
上面获取到了文件数据,现在我们实现一下前端页面。因为页面比较简单,就没用react或vue这种前端框架,直接使用服务端生成html返回给前端展示。
这里使用了ejsJavaScript 模板引擎生成html。
安装ejs
npm i ejs
使用ejs生成html,遍历files动态生成列表
访问网页查看效果
这样写比较麻烦,ejs支持从文件中加载模版,创建views
文件夹,然后创建logs.ejs
文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>logs</title>
</head>
<body>
<ul>
<% files.forEach(function (file) { %>
<li><%= file.name %></li>
<% }) %>
</ul>
</body>
</html>
改造一下ejs方法,使用renderFile
这样也太难看了,使用bootstrap
库美化一下样式,使用表格来展示列表
先引入bootstrap
样式文件
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
使用bootstrap
表格样式
查看效果
添加搜索框
实现搜索功能
查看日志内容
再对外暴露一个接口,渲染日志内容
在views文件夹下,创建detail.ejs
文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= file %></title>
</head>
<body>
<%= content %>
</body>
</html>
再从线上复制一个真实的日志文件到项目里,common-error.log.2024-07-08
点击当前日志文件,会打开http://localhost:3000/common-error.log.2024-07-08
链接
显示日志内容
这样太丑了,使用prismjs库高亮内容,进入官网,下载js和css文件
选择Tomorrow Night
主题
选择类型
最后下载js和css文件到项目public文件夹下
使用express.static
方法把public
文件夹下的文件暴露出去,可以使用连接访问
改造detail.ejs
文件,引入prism.css
和prism.js
文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= file %></title>
<link rel="stylesheet" href="/prism.css" />
<style>
* {
padding: 0;
margin: 0;
}
body {
background-color: #2d2d2d;
}
.level.error {
color: #ff4d4f !important;
}
.level.warning {
color: #faad14 !important;
}
.level.info {
color: #52c41a !important;
}
::-webkit-scrollbar-thumb {
background: hsla(0, 0%, 52.9%, .4);
border-radius: 4px;
border: none;
}
::-webkit-scrollbar-thumb {
background: transparent
}
:hover::-webkit-scrollbar-thumb {
background: hsla(0, 0%, 52.9%, .4);
}
::-webkit-scrollbar {
width: 6px;
height: 6px;
background-color: transparent;
}
::-webkit-scrollbar-track {
background-color: transparent;
}
</style>
</head>
<body>
<pre><code class="language-log"><%= content %></code></pre>
<script src="/prism.js"></script>
</body>
</html>
查看效果
使用socket.io实现实时查看日志内容变更
上面我们实现了查看日志文件内容,但是一般日志文件的内容会一直变化,所以下面来实现一下日志文件内容变化,前端也能实时展示。
因为涉及到后端向前端推送,我这里使用的socket.io库。
安装socket.io库
npm i socket.io
改造index.js
文件,引入socket.io
库
监听端口由app改为server
监听连接
detail.ejs
中引入socket.io
库
<script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script>
发起连接
刷新浏览器,测试连接,能成功打印,说明连接上了。
使用一个map把用户socket存起来,当文件改动时,获取当前文件对应的用户socket,然后调用emit方法,给前端发送消息。
前端连接时,把file和contentLength传入后端
contentLength
在渲染detail.ejs
的时候传入
使用chokidar库监听当前文件夹下的文件改动
npm i chokidar
监听文件变化,并给前端发送消息
前端监听change消息,并把新的内容展示出来
有新改动时,展示一个图标告诉用户文件有变化
给图标加样式,并且做一个上下循环动的动画
默认给改成隐藏,当有新变化时展示出来
点击图表滚动到底部
测试改动common-error.log.2024-07-08
文件,手动添加一行日志
自定义端口
现在服务端口写死的是3000,万一服务器上这个端口被占用了就没办法启动了,所以这里允许用户传入端口号。
改造socket.io连接地址
测试
发布到npm
编写README.md
修改package.json
登录npm
发布
查看
最后
项目仓库地址:github.com/dbfu/simple…
转载自:https://juejin.cn/post/7399983106722611236