网站首页 > 技术教程 正文
错误日志分析
首先我们要读取Nginx日志,我们可以看到Nginx的错误日志格式一般都是这样子,需要注意的是Nginx的错误日志格式是差不多的因为无法设置日志格式只能设置日志错误等级所以我们分析的时候很方便
- 这里我们用到readline逐行读取,简单来说可以做文件逐行读取:比如说进行日志分析。
- 自动完成:比如输入npm,自动提示"help init install"。
- 命令行工具:比如npm init这种问答式的脚手架工具。 这里我们主要做日志分析其他的感兴趣可以琢磨一下
实现方法
const readline = require('readline'); const fs = require('fs'); const path = require('path'); console.time('readline-time') const rl = readline.createInterface({ input: fs.createReadStream(path.join(__dirname, '../public/api.err.log'), { start: 0, end: Infinity }), }); let count = 0; rl.on('line', (line) => { const arr = line.split(', '); const time = arr[0].split('*')[0].split('[')[0].replace(/\//g, '-');//获取到时间 const error = arr[0].split('*')[1].split(/\d\s/)[1];//错误原因 const client = arr[1].split(' ')[1];//请求的客户端 const server = arr[2].split(' ')[1];//请求的网址 const url = arr[3].match(/\s\/(\S*)\s/)[0].trim()//获取请求链接 const upstream = arr[4].match(/(?<=").*?(?=")/g)[0];//获取上游 const host = arr[5].match(/(?<=").*?(?=")/g)[0];//获取host const referrer = arr[6] ? arr[6].match(/(?<=").*?(?=")/g)[0] : '';//来源 console.log(`时间:${time}-原因:${error}-客户端:${client}-网址:${server}-地址:${url}-上游:${upstream}-主机:${host}-来源:${referrer}`); count++; }); rl.on('close', () => { let size = fs.statSync(path.join(__dirname, '../public/api.err.log')).size; console.log(`读取完毕:${count};文件位置:${size % 2 === 0}`); console.timeEnd('readline-time') });
上面代码有几点需要注意的是会创建一个文件可读流然后由于演示所以我是直接找的本地地址如果是生产环境的话大家可以直接填写服务器上的错误日志地址,如果没有Nginx错误日志分割的话每天会产生很多日志,createReadStream读取几十M的文件还好如果读取几百M或者上G的容量日志这会造成性能问题,所以我们需要在每次createReadStream没必要每次从0字节开始读取,ceateReadStream提供了start和end
所以我们每次可以在读取完之后记录一下当前文件字节大小下一次读取文件就是可以用该文件上次的大小开始读取
let size = fs.statSync(path.join(__dirname, '../public/api.err.log')).size;
我们可以对比一下每次从0字节开始读取和从指定字节读取
保存数据进行分析
这里我是用node-schedule这个库进行定时保存错误日志和linux的cron差不多,用的mongodb保存数据,这里更推荐大家用elasticsearch来做日志分析
rl.on('close', async () => { let count = 0; for (let i of rlist) { count++; if (count % 500 === 0) { const res = await global.db.collection('logs').bulkWrite(rlist.slice(count, count + 500), { ordered: false, w: 1 }).catch(err => { console.error(`批量插入出错${err}`) }); } else if (count === rlist.length - 1) { //批量插入 数据 const res = await global.db.collection('logs').bulkWrite(rlist.slice(rlist - (rlist % 500), rlist.length), { ordered: false, w: 1 }); let size = fs.statSync(addres).size; size = size % 2 === 0 ? size : size + 1;//保证字节大小是偶数 不然会出现读取上行内容不完整的情况 count = 0; rlist.length = []; //更新数据库里面文件的size global.db.collection('tasks').updateOne({ _id: addre }, { $set: { _id: addre, size, date: +new Date() } }, { upsert: true }); } } resolve(true); })
上面主要是500条保存一次,因为我用的是批量插入然后mongodb有限制一次性最多插入16M数据的限制,所以大家看自己清空决定一次性插入多少条 犹豫对readline的实现比较感兴趣,就去翻阅了一下源码发现并不是我们想的那么复杂,readline源码,下面贴一下line事件的源码,想继续深入的同学可以看看全部的源码
if (typeof s === 'string' && s) { var lines = s.split(/\r\n|\n|\r/); for (var i = 0, len = lines.length; i < len; i++) { if (i > 0) { this._line(); } this._insertString(lines[i]); } } ... Interface.prototype._line = function() { const line = this._addHistory(); this.clearLine(); this._onLine(line); }; ... Interface.prototype._onLine = function(line) { if (this._questionCallback) { var cb = this._questionCallback; this._questionCallback = null; this.setPrompt(this._oldPrompt); cb(line); } else { this.emit('line', line); } };
保存的数据需要进行分析比如哪个IP访问最多哪条错误最多可以用聚合来进行分析贴出示例分析某个IP在某一天访问出错最多的原因
db.logs.aggregate( // Pipeline [ // Stage 1 { $group: { '_id': { 'client': '114.112.163.28', 'server': '$server', 'error': '$error', 'url': '$url', 'upstream': '$upstream','date':'$date' ,'msg':'$msg' } , 'date':{'$addToSet':'$date'}, count: { '$sum': 1 } } }, // Stage 2 { $match: { count: { $gte: 1 }, date: ['2019-05-10'] } }, { $sort: { count: -1 } }, ], // Options { cursor: { batchSize: 50 }, allowDiskUse: true } );
作者:zpzxgcr
链接:https://juejin.im/post/5cda14246fb9a032465872a3
欢迎关注公众号:前端冒险指南
猜你喜欢
- 2024-10-11 老版本nginx存在安全漏洞,请升级至1.18稳定版本
- 2024-09-19 nginx 解决 readv() failed (104: Connection reset by peer)
- 2024-09-19 Godaddy购买SSL之后Nginx配置流程以及各种错误的解决
- 2024-09-19 nginx报错111: Connection refused
- 2024-09-19 2023年 Nginx 面试题总结(nginx配置和优化面试)
- 2024-09-19 Web中间件漏洞之Nginx篇(中间件漏洞总结)
- 2024-09-19 Nginx 备忘录 - 03. location 与 error_page
- 2024-09-19 高性能网关-Nginx-proxy_next_upstream自定义配置错误重试机制
- 2024-09-19 如何在 NGINX 中创建自定义 404 错误页面
- 2024-09-19 Linux运维之为Nginx添加错误日志(error_log)配置
你 发表评论:
欢迎- 最近发表
-
- Linux新手必看:几种方法帮你查看CPU核心数量
- linux基础命令之lscpu命令(linux中ls命令的用法)
- Linux lscpu 命令使用详解(linux常用ls命令)
- 如何查询 Linux 中 CPU 的数量?这几个命令要知道!
- 在linux上怎么查看cpu信息(linux如何查看cpu信息)
- 查看 CPU 的命令和磁盘 IO 的命令
- 如何在CentOS7上改变网卡名(centos怎么改网卡名字)
- 网工必备Linux网络管理命令(网工必备linux网络管理命令是什么)
- Linux 网络命令知多少(linux 网络 命令)
- Linux通过命令行连接wifi的方式(linux命令行连接无线网)
- 标签列表
-
- 下划线是什么 (87)
- 精美网站 (58)
- qq登录界面 (90)
- nginx 命令 (82)
- nginx .http (73)
- nginx lua (70)
- nginx 重定向 (68)
- Nginx超时 (65)
- nginx 监控 (57)
- odbc (59)
- rar密码破解工具 (62)
- annotation (71)
- 红黑树 (57)
- 智力题 (62)
- php空间申请 (61)
- 按键精灵 注册码 (69)
- 软件测试报告 (59)
- ntcreatefile (64)
- 闪动文字 (56)
- guid (66)
- abap (63)
- mpeg 2 (65)
- column (63)
- dreamweaver教程 (57)
- excel行列转换 (56)
本文暂时没有评论,来添加一个吧(●'◡'●)