前端记录日志生成文件保存到本地

一、前言

项目上线后业务人员反馈说是打印数据不准确,通过websocket连接打印机服务去进行打印,会出现条码漏打的情况;通过后端日志和打印机日志均没有找到问题原因,猜测是websocket连接断开导致的问题。

也想通过前端日志去排查问题,本人据理力争说控制台有日志输出;奈何现场人员不会看控制台信息,无奈只能研究如何去生成前端日志。

二、日志思路

首先需要了解前端如何去生成日志,最终保存到用户电脑中。为此需要明确几点:

  1. 日志的生成方法;
  2. 日志信息如何展示;
  3. 保存方法与保存路径;
  4. 哪些信息需要保存到日志中;

2.1 日志生成的方法

日志信息需要定义一个变量,这个根据具体需求;如果是单一功能需要日志操作信息,则只需要定义局部变量;如果是整个项目都需要日志操作信息,则需要定义全局变量。

本次示例日志变量挂载到window上,这样可以直接获取及更改。

// 判断是否有日志变量
if (window.historryRecordLogs) {// 初始化日志变量window.historryRecordLogs = [];
}
// 根据项目需求去跟更改日志信息类型,建立一个消息队列;
// 需要记录的信息放进日志队列里面去
window.historryRecordLogs.push({// 如果需要前台展示效果可以根据类型展示不同样式type: "日志类型",	message: "具体日志信息",userName: "操作人",dateTime: "操作时间",
});

2.2 整理生成txt文件下载

最终我们需要得到这样一个日志文件,就需要前端生成一个文件,手动或被动去生成一个日志文件。

实现步骤:

  1. 整理日志信息,汇总输出文字;
  2. JS通过Blob方法生成一个Blob文件;
  3. 在生成一个临时a标签,来模拟手动下载;

简单示例:

// 导出下载日志文件
const exportFileTxt = () => {// 判断是否有日志变量if (window.historryRecordLogs && window.historryRecordLogs.length) {// 整理日志信息const dataTxt = window.historryRecordLogs.reduce((cur, next) => cur +=`操作人:${next.userName},日志信息:<${next.message}> 操作时间:${next.dataTime}\n`, "");// 生成一个Blob文件const urlObject = window.URL || window.webkitURL || window;const blobFile = new Blob([dataTxt]);// 生成一个a标签模拟下载const aDom = document.createElement("a")aDom.href = urlObject.createObjectURL(blobFile);// 定义文件名称aDom.download = `${moment(new Date())}_logs`;aDom.click();}
};

2.3 保存路径

保存路径是当前浏览器的默认下载路径,无法手动指定下载文件路径;

2.3.1 下载方式:
  1. 可以设置用户退出登录后默认下载;
  2. 放在头部导航栏,有需求的情况下再点击下载;
2.3.2 注意事项
  1. 如果采用默认下载的情况需要结合具体情况;
  2. 当用户直接关闭浏览器时无法自动下载;
  3. 直接关闭标签页也无法下载(这个可以监听关闭当前标签页的事件);
window.addEventListener('beforeunload', function (e) {// 取消关闭标签页的默认行为e.preventDefault();// 自定义确认消息e.returnValue = '您有未保存的更改,确定要离开吗?';
});

2.4 整理哪些信息存储日志

  1. 前端接口的报错信息;
  2. 敏感数据的操作流程;
  3. websocket连接状态详细日志记录;

三、详细记录

3.1 前端接口报错信息记录

// 封装一个请求方法,在catch阶段进行错误捕获
const request = async (url, options) => {try {const response = await fetch(url, options);if (!response.ok) {throw new Error(response.statusText);}return await response.json();} catch (error) {window.historryRecordLogs.push({type: "error",message: error.message,userName: "操作人",dateTime: moment(new Date()).format('YYYY-MM-DD HH:mm:ss')});throw error;}
};

3.2 敏感数据的操作流程

// 假设有一个敏感操作的函数
function sensitiveOperation() {try {// 操作逻辑} catch (e) {window.historryRecordLogs.push({type: "sensitiveOperation",message: e.message || '未知错误',userName: "操作人",dateTime: moment(new Date()).format('YYYY-MM-DD HH:mm:ss')});}
}

3.3 websocket连接状态详细日志记录

const ws = new WebSocket("ws://example.com");ws.onopen = () => {window.historryRecordLogs.push({type: "websocket",message: "WebSocket连接已打开",userName: "操作人",dateTime: moment(new Date()).format('YYYY-MM-DD HH:mm:ss')});
};ws.onclose = (event) => {window.historryRecordLogs.push({type: "websocket",message: `WebSocket连接已关闭,代码:${event.code},原因:${event.reason}`,userName: "操作人",dateTime: moment(new Date()).format('YYYY-MM-DD HH:mm:ss')});
};ws.onerror = (error) => {window.historryRecordLogs.push({type: "websocket",message: `WebSocket错误:${error.message}`,userName: "操作人",dateTime: moment(new Date()).format('YYYY-MM-DD HH:mm:ss')});
};

四、总结

通过以上步骤,我们可以实现前端日志的记录和下载,方便我们排查问题。但是需要注意的是,这种方式并不能解决所有的问题,有些问题可能需要结合后端日志或者浏览器的开发者工具来解决。同时,这种方式也有一定的风险,因为日志信息可能会被恶意用户利用,所以我们需要确保日志信息的安全性。

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

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

相关文章

第9天:静态文件和媒体文件管理

第9天&#xff1a;静态文件和媒体文件管理 目标 管理静态资源&#xff08;如CSS、JavaScript、图片等&#xff09;和用户上传的文件。 任务概览 配置静态文件和媒体文件的存储路径。学习如何收集和压缩静态文件。 详细步骤 1. 配置静态文件和媒体文件的存储路径 在setti…

Redis 分布式锁教程

Redis 分布式锁教程 简介 在分布式系统中&#xff0c;多个进程可能会尝试同时访问共享资源&#xff0c;这会导致数据不一致或者竞争条件。分布式锁是一种用于控制对共享资源访问的机制。Redis 是一个流行的内存数据存储系统&#xff0c;可以用来实现分布式锁。 本文将介绍如…

react项目中如何书写css

一&#xff1a;问题&#xff1a; 在 vue 项目中&#xff0c;我们书写css的方式很简单&#xff0c;就是在 .vue文件中写style标签&#xff0c;然后加上scope属性&#xff0c;就可以隔离当前组件的样式&#xff0c;但是在react中&#xff0c;是没有这个东西的&#xff0c;如果直…

【学一点儿前端】单页面点击前进或后退按钮导致的内存泄露问题(history.listen监听器清除)

今天测试分配了一个比较奇怪的问题&#xff0c;在单页面应用中&#xff0c;反复点击“上一步”和“下一步”按钮时&#xff0c;界面表现出逐渐变得卡顿。为分析这一问题&#xff0c;我用Chrome的性能监控工具进行了浏览器性能录制。结果显示&#xff0c;每次点击“上一步”按钮…

Mars3d实现汽车尾气粒子效果从汽车屁股开始发射效果

本身的汽车尾气粒子效果&#xff1a;在汽车模型的中间发射的↓↓↓↓↓↓↓↓↓↓↓ Mars3d实例中是使用transY偏移值实现汽车尾气粒子效果从汽车屁股开始发射效果&#xff1a; // 动态运行车辆的尾气粒子效果 function addDemoGraphic4(graphicLayer) {const fixedRoute new…

三星与SK海力士:以混合键合技术引领3D DRAM革新之路

在高速缓存内存&#xff08;HBM&#xff09;领域持续领跑的三星与SK海力士&#xff0c;正以混合键合技术为突破口&#xff0c;开启3D DRAM技术的新纪元。这一战略转型不仅预示着存储技术的深度革新&#xff0c;更体现了两大半导体巨头在提高集成度、优化性能与成本上的不懈追求…

如何恢复电脑硬盘删除数据?提供一套实用恢复方案

在数字化时代&#xff0c;电脑硬盘中存储的数据对于个人和企业来说都至关重要。然而&#xff0c;有时我们可能会不小心删除了一些重要文件&#xff0c;或者因为某种原因导致数据丢失。这时候&#xff0c;恢复硬盘上被删除的数据就显得尤为重要。本文将为您提供一套实用的电脑硬…

光电数鸡算法《java》

一&#xff1a;需求 题目&#xff1a;一条流水线有工位D1,D2,D3…D20,总共20个工位。 每个工位都装有一个光电计数器&#xff0c;每个工位都为本工位的计数减去前一个工位&#xff08;第一个有数值的工位除外&#xff0c;不计算。&#xff09; 计算规则&#xff1a;比如D1,D2都…

在自托管基础设施上使用 GitOps 部署 MinIO

基于MinIO Weaviate Python GitOps探索的见解&#xff0c;本文探讨了如何增强软件部署流程的自动化。 通过将 GitHub Actions 与 Docker Swarm 集成而产生的协同作用&#xff0c;以自托管基础架构的稳健性为基础&#xff0c;标志着 CI/CD 实践的关键进步。这种方法不仅利用了软…

Go语言开发框架GoFly已集成数据可视化大屏开发功能,让开发者只专注业务开发,本文指导大家如何使用

前言 框架提供数据大屏开发基础&#xff0c;是考虑当前市场软件应用有一大部分是需要把业务数据做出大屏&#xff0c;很多政府项目对大屏需求特别高&#xff0c;还有生产企业项目也对大屏有需求&#xff0c;没有提供基础规范的后台框架&#xff0c;在开发大屏需要很多时间去基…

Mentor Xpedition怎么切换中英文界面

1、Mentor Xpedition的Layout界面&#xff0c;切换中英文的方法如下图&#xff1b; 切换英文设置&#xff0c;设置系统环境变量&#xff1a;MGC_PCB_LANGUAGEEnglish&#xff0c;重新打开软件即可切换成中文界面&#xff1b; 如果想要在切换成中文&#xff0c;把标量值改为Chi…

SegFormer模型

文章目录 SegFormer模型详细讲解SegFormer的架构1. Hierarchical Transformer Encoder2. MLP Decoder SegFormer的优点SegFormer的应用SegFormer的创新点代码部分讲解 SegFormer模型详细讲解 SegFormer是一个用于图像语义分割的深度学习模型&#xff0c;它结合了Transformer架…

万能引用与完美转发

万能引用与完美转发 万能引用完美转发完美转发的应用场景万能引用的一个小点 万能引用 注意&#xff1a;当&&出现在模板中时&#xff0c;不是右值引用&#xff0c;而是叫万能引用。比如下面的T&& t template<typename T> void PerfectForward(T&&a…

民宿在线预订系统

摘要 随着国家的发展&#xff0c;人们也更加重视自己的业余时间。在特定的假期或休闲时间外出度假已逐渐成为这个时代的趋势。在我国&#xff0c;随着经济的发展和城市居民物质生活水平的提高&#xff0c;旅游业也呈现出越来越受欢迎的趋势。同时随着人口的快速流动&#xff0…

jQuery事件和其他方法

&#xff08;2&#xff09;jQuery 事件处理 2.1 事件处理 on() 绑定事件 on() 方法在匹配元素上绑定一个或多个事件的事件处理函数&#xff1b; 语法演示如下&#xff1a; element.on(events,[selector],fn)&#x1f606;温馨提醒&#x1f606;&#xff1a; events&#xff…

Leetcode 522. 最长特殊序列 II (判断子序列 优化)

Leetcode 522. 最长特殊序列 II 暴力枚举 根据特殊序列的定义&#xff0c;枚举出每个 strs[ i ] 的所有子序列&#xff0c;再将这个子序列与strs中的其他串比较判断 使用二进制位运算枚举一个str的所有子序列 使用双指针指向两个串的开头&#xff0c;同时移动判断是否是子序列…

代理网络基础设施 101:增强安全性、速度和可扩展性

编辑代理网络在现代网络架构中发挥着重要作用&#xff0c;充当管理和重新路由数据流的中介。它们处理的数据可以是各种类型&#xff0c;包括搜索查询和潜在的敏感客户信息&#xff0c;这凸显了它们在数据安全方面的作用。 然而&#xff0c;代理的好处不仅限于安全性。它们为用…

类AAAAAAAAAAAA迭代

class A {vector<A>} C 迭代 这个代码在C中是不能编译的&#xff0c;因为它会导致无限的嵌套&#xff0c;因为std::vector<A>会持有A类型的实例&#xff0c;而A类型的实例又会包含一个std::vector<A>&#xff0c;这会无限制地复制和嵌套下去。 如果你想要创…

linux中如何进行yum源的挂载

linux中如何进行yum源的挂载 ​ 1.首先创建目录[rootserver /]# mkdir /rhel92.使用mount命令进行、dev/cdrom/的镜像文件进行挂载[rootserver /]# mount /dev/cdrom /rhel9/ ​ 注意&#xff1a;此时设立的是临时命令。重启后则失效&#xff0c;若想在下次开启后仍然挂载&a…

WPF由文本框输入的内容动态渲染下拉框

在做项目过程中&#xff0c;需要扫码枪扫描快递单号或者手动输入快递单号时&#xff0c;自动检索该单号是哪个快递公司的&#xff0c;下拉框中自动带出该单号的快递公司。当输入的快递单号不存在时&#xff0c;将数据库中所有快递公司都带出 效果&#xff1a; 通过输入的快递单…