uniapp本地存储日志

news2024/12/23 19:29:55

uniapp本地存储日志

  • 背景
  • 实现
    • 代码实现
    • 使用
    • 查看生成log
    • 读取
  • 注意事项
  • 尾巴

背景

我们的APP开发完成之后,在我们测试环境或者自测的时候都好好的,但是发布到生产环境客户使用总会出现一些奇奇怪怪的问题。这时候因为没在开发环境,我们无法查看到日志,所以我们需要手机到用户的操作日志然后上传,方便我们排查出问题。

实现

我们通过5+API提供的IO模块来进行文件的读写操作。主要实现如下功能:
1、日志打印
2、日志按天存储(同一天的日志会自动续写到文件)
3、日志删除
4、日志压缩

代码实现

主要通过plus.io.requestFileSystem对应用私有目录进行读写,完整代码如下:

// 新建logger.js文件
// 日志存放的文件夹目录
const LOG_DIR = '_doc/logs';
/**
 * 获取当前时间
 */
function getDayStr() {
	var y, m, d, h, mm, s;
	var date = new Date();
	y = date.getFullYear();
	m = date.getMonth() + 1;
	d = date.getDate();
	m = m < 10 ? '0' + m : m;
	d = d < 10 ? '0' + d : d;
	// //console.log('日期:',y,m,d)
	// return '20220607' // 生成指定日期
	return '' + y + m + d;
}
/**
 * 获取当前时间,yyyy-mm-dd hh:mm:ss
 * 用于记录日志的时间信息
 */
function getTimeStr() {
	var y, m, d, h, mm, s;
	var date = new Date();
	y = date.getFullYear();
	m = date.getMonth() + 1;
	d = date.getDate();
	h = date.getHours();
	mm = date.getMinutes();
	s = date.getSeconds();
	m = m < 10 ? '0' + m : m;
	d = d < 10 ? '0' + d : d;
	h = h < 10 ? '0' + h : h;
	mm = mm < 10 ? '0' + mm : mm;
	s = s < 10 ? '0' + s : s;
	var timeStr = y + '-' + m + '-' + d + ' ' + h + ':' + mm + ':' + s;
	return timeStr;
}
/**
 * 日志TXT的名称
 */
function getLogFileName() {
	const txt = LOG_DIR + '/' + getDayStr() + '.txt';
	// //console.log('TXT文件名称:',txt)
	return txt;
}
let tasks = [];
/**
 * @param {Object} tag 标识
 * @param {Object} msg 空格
 */
function writeToTxt(tag) {
	return new Promise((resolve, reject) => {
		let msgs = '';
		for (var i = 1; i < arguments.length; i++) {
			const item = arguments[i];
			if (
				typeof item == 'string' ||
				typeof item == 'number' ||
				typeof item == 'boolean'
			) {
				msgs = msgs + '\t' + item;
			} else {
				msgs = msgs + '\t' + JSON.stringify(item);
			}
		}
		// 获取当前时间
		let txt_msg = getTimeStr() + '\t[' + tag + ']\t' + msgs + '\n';
		tasks.push(txt_msg);
		resolve(true);
	}).then(() => {
		clearTask();
	});
}
// 清空日志到日志文件
function clearTask() {
	// #ifdef APP-PLUS
	if (tasks.length === 0) {
		return;
	}
	const txt_msg = tasks.join('');
	tasks = [];
	const fileName = getLogFileName();
	plus.io.requestFileSystem(
		plus.io.PRIVATE_DOC,
		fs => {
			fs.root.getFile(
				fileName, {
					create: true,
				},
				function(entry) {
					// 写入到本地
					entry.createWriter(
						function(writer) {
							writer.onwrite = function(e) {
								// console.log("Write data success!");
								//console.log('写入本地日志 >>>> ', txt_msg);
							};
							writer.onerror = function(e) {
								if (process.env.NODE_ENV === 'development'){
									console.eror(
										'写入本地日志失败 >>>> ',
										JSON.stringify(e),
										txt_msg
									);
								}
							};
							// Write data to the end of file.
							writer.seek(writer.length);
							writer.write(txt_msg);
						},
						function(e) {
							if (process.env.NODE_ENV === 'development') {
								console.log(e.message);
							}
						}
					);
				}
			);
		},
		function(e) {
			if (process.env.NODE_ENV === 'development') {
				console.log('Request file system failed: ' + JSON.stringify(e));
			}
		}
	);
	// #endif
}

/**
 * 压缩所有的日志为zip
 */
function zipLogDir(callback) {
	// #ifdef APP-PLUS
	var zipFile = '_doc/logs.zip';
	var targetPath = LOG_DIR;

	// 开始压缩文件
	if (process.env.NODE_ENV === 'development') {
		console.log('开始压缩', targetPath, zipFile);
	}
	plus.zip.compress(
		targetPath,
		zipFile,
		function(res) {
			if (process.env.NODE_ENV === 'development') {
				console.log('开始压缩 Compress success!', res);
			}
			if (callback) {
				callback({
					success: true,
					res,
					zipPath: zipFile,
				});
			}
		},
		function(error) {
			if (process.env.NODE_ENV === 'development') {
				console.error('开始压缩 Compress error!', error);
			}
			if (callback) {
				callback({
					success: false,
					error,
				});
			}
		}
	);
	// #endif
}
/**
 * 删除多少天之前的日志文件
 */
function removeFile(durationDay) {
	// #ifdef APP-PLUS
	return new Promise((resolve, reject) => {
		if (!durationDay || durationDay <= 0) {
			durationDay = 10;
		}
		var dirPath = LOG_DIR;
		plus.io.resolveLocalFileSystemURL(
			dirPath,
			function(entry) {
				//读取这个目录对象
				var directoryReader = entry.createReader();
				//读取这个目录下的所有文件
				directoryReader.readEntries(
					function(entries) {
						console.log('日志文件数量', entries.length);
						//如果有才操作
						if (entries.length > 0) {
							let now = getDayStr();
							for (let file of entries) {
								// 判断需要保留的日志
								let day = file.name.replace('.txt', '');
								if (parseInt(day) + parseInt(durationDay) < parseInt(now)) {
									console.log('需要删除的日志是', file.name);
									try {
										file.remove(
											function() {
												if (process.env.NODE_ENV === 'development') {
													console.error('删除日志成功', file.name);
												}
											},
											function(e) {
												if (process.env.NODE_ENV === 'development') {
													console.error('删除日志失败', file.name, e);
												}
											}
										);
									} catch (e) {
										if (process.env.NODE_ENV === 'development') {
											console.error('删除日志失败', file.name, e);
										}
									}
								} else {
									if (process.env.NODE_ENV === 'development') {
										console.log('保留的日志是', file.name);
									}
								}
							} // for
						} // if
						resolve();
					},
					function(e) {
						if (process.env.NODE_ENV === 'development') {
							console.log('读取文件失败:' + e.message);
						}

						resolve();
					}
				);
			},
			function(e) {
				if (process.env.NODE_ENV === 'development') {
					console.log('读取目录失败:' + e.message);
				}
				resolve();
			}
		);
	});
	// #endif
}

/**
 * 自定义TXT日志
 */
const logger = {
	/**
	 * @param {Object} msg 日志信息的字符串信息
	 */
	debug: function() {
		writeToTxt('DEBUG', ...arguments);
		//production
		if (process.env.NODE_ENV === 'development') {
			console.debug(...arguments);
		}
	},
	log: function() {
		writeToTxt('LOG', ...arguments);
		if (process.env.NODE_ENV === 'development') {
			console.log(...arguments);
		}
	},
	info: function() {
		writeToTxt('INFO', ...arguments);
		if (process.env.NODE_ENV === 'development') {
			console.info(...arguments);
		}
	},
	warn: function() {
		writeToTxt('WARN', ...arguments);
		if (process.env.NODE_ENV === 'development') {
			console.warn(...arguments);
		}
	},
	error: function() {
		writeToTxt('ERROR', ...arguments);
		if (process.env.NODE_ENV === 'development') {
			console.error(...arguments);
		}
	},
	/**
	 * @param {String} tag 日志信息的自定义信息
	 */
	tag: function(tag) {
		writeToTxt(tag, ...arguments);
		if (process.env.NODE_ENV === 'development') {
			console.log(...arguments);
		}
	},
	/**
	 * @param {Object} msg 日志信息的字符串信息
	 */
	network: function() {
		writeToTxt('NETWORK', ...arguments);
		if (process.env.NODE_ENV === 'development') {
			console.log(...arguments);
		}
	},
	/**
	 * @param {Object} msg 日志信息的字符串信息
	 */
	logIpExchange: function(msg) {
		writeToTxt('IpExchange', ...arguments);
		if (process.env.NODE_ENV === 'development') {
			console.log(...arguments);
		}
	},
	/**
	 * 压缩成zip,并返回路径
	 * @param {Object} callback
	 */
	zipLogDir,
	/**
	 * 删除多少${durationDay}天之前的日志文件
	 * @param {Object} durationDay 默认是10天
	 */
	removeFile,
	/**
	 * 主要使用方法。先移除
	 * @param {Object} callback
	 */
	removeFileAndZipLogDir(callback) {
		removeFile().then(() => {
			zipLogDir(callback);
		});
	},
};

export default logger;

使用

引入logger.js文件

//这里根据你自己路径来
import logger from '@/common/js/logger.js'

删除5天前的日志

logger.removeFile(5)

打印

logger.log('test')

查看生成log

我们这里使用的是hbx基座调试,这里的plus.io.PRIVATE_DOC对应的手机端文件管理器中Android/data/io.dcloud.HBuilder/apps/Hbuilder/doc/logs,其中doc/logs对应代码中的LOG_DIR变量。
在这里插入图片描述
在这里插入图片描述

到这里log已经成功存储到了手机中。

读取

我们保存log到本地之后,我们希望读取然后上传,依然使用的是plus.io.requestFileSystem这个API,参考上文的写法。遍历文件夹后可以在界面显示让用户手动上传,或者启动应用静默上传。

注意事项

日志本地存储只在APP平台生效,演示为Android平台,iOS平台未做测试。

尾巴

今天的文章就到这里了,希望能给大家帮助,如果喜欢我的文章,欢迎给我点赞,评论,关注,谢谢大家!

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

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

相关文章

【云原生】docker安全与https加密的超文本传输协议CA证书生成

目录 一、docker安全 二、http与https的区别 三、为什么要使用 SSL 证书&#xff1f; 四、https证书认证的过程 https单向认证的访问流程 https双向认证的访问流程 五、如何获取证书&#xff1f; 六、实操获取证书并验证 1、通过阿里云获取证书 2、通过mkcert获取证书…

Flutter的安装与环境配置

一、下载安装Futter&#xff1a; 1、Flutter中文文档&#xff1a; 安装和环境配置 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 2、下载 Futter SDK&#xff1a; Flutter中文文档 里面有&#xff0c;下载完成之后找个文件夹解压出来&#xff0c;最好不要将 Flu…

GoLang和GoLand的安装和配置

1. GoLang 1.1 特点介绍 Go 语言保证了既能达到静态编译语言的安全和性能&#xff0c;又达到了动态语言开发维护的高效率&#xff0c;使用一个表达式来形容 Go 语言&#xff1a;Go C Python , 说明 Go 语言既有 C 静态语言程序的运行速度&#xff0c;又能达到 Python 动态语…

编程实战实例分享,棋牌室计时计费管理系统软件教程

编程实战实例分享&#xff0c;棋牌室计时计费管理系统软件教程 一、前言 以下编程实例以 佳易王棋牌计时计费软件V17.8为例说明 1、开始计时和等待中&#xff0c;图片自动识别&#xff0c;自动匹配 2、开始计时后&#xff0c;系统记录开始时间&#xff0c;并直观显示所用的时…

开源项目MessageNest打造个性化消息推送平台多种通知方式

今天介绍一个开源项目&#xff0c;Message Nest - 可以打造个性化消息推送平台&#xff0c;整合邮件、钉钉、企业微信等多种通知方式。定制你的消息&#xff0c;让通知方式更灵活多样。 开源地址&#xff1a; https://github.com/engigu/Message-Push-Nest 测试平台 系统&am…

网安人必看!CISP家族顶流证书攻略

网络安全已成为当今的热门领域&#xff0c;证书在职业发展中的重要性不言而喻。但是&#xff0c;证书市场五花八门&#xff0c;选择适合自己的证书可是个大问题。别担心&#xff0c;今天我们就来聊聊CISP家族的几个热门认证&#xff0c;让你在网络安全领域的发展更加顺利&#…

Android存储系统基础知识

英文原版链接→ Android存储系统概览图&#xff08;图片模糊的话请拖动图片至新标签页打开&#xff09;&#xff1a; 从 Android 的角度来看 → 内部存储和 → 外部存储&#xff1a; 内部存储 内部存储只能通过已取得 root 权限的设备进行访问。 应用程序包保存在&#xff1a;…

家政小程序开发

随着人民生活水平的提高&#xff0c;我国老龄化日益增加&#xff0c;越来越多的家庭对家政服务需求也日益提升。目前&#xff0c;家政服务业已经成为了人们日常生活中不可缺少的一部分&#xff0c;家政服务市场具有较大的发展潜力。 近几年&#xff0c;家政服务市场规模呈快速…

驱动开发KMDF编译时:cannot open sourcefile “device.tmh“

有人说 设置项目的 WPP Tracing -> 设置 "Run Wpp Tracing" 为 YES&#xff0c;但是属性页压根没有这玩意啊&#xff1f;咋回事呢&#xff1f; 别人的工程属性页是这样的&#xff0c;这是为什么&#xff1f;

IT运维如何帮助企业降本增效?

IT监控运维管理技术发展应用和趋势 1、智能运维 随着人工智能和大数据技术的发展&#xff0c;智能运维将成为IT监控运维管理的重要趋势。通过利用机器学习、深度学习等技术&#xff0c;实现对IT系统的自动化监控、故障预测和智能维护&#xff0c;提高运维效率和质量。 2、容…

数字化转型对企业发展有哪些帮助?

数字化转型利用技术增强流程、运营和客户体验&#xff0c;在业务发展中发挥着至关重要的作用。以下是数字化转型促进企业发展的一些助力&#xff1a; 1.提高效率和生产力&#xff1a; 日常任务和流程的自动化有助于简化操作&#xff0c;减少完成它们所需的时间和精力。数字工…

瑞_数据结构与算法_红黑树

文章目录 1 什么是红黑树1.1 红黑树的背景1.2 红黑树的特性 ★★★ 2 红黑树的Java实现2.1 红黑树颜色枚举类Color2.2 红黑树节点类Node2.2.1 实现判断是否是左孩子方法isLeftChild()2.2.2 实现查找叔叔节点方法uncle()2.2.3 实现查找兄弟节点方法sibling() 2.3 红黑树类RedBla…

《Pandas 简易速速上手小册》第1章:Pandas入门(2024 最新版)

文章目录 1.1 Pandas 简介1.1.1 基础知识1.1.2 案例&#xff1a;气候变化数据分析1.1.3 拓展案例一&#xff1a;金融市场分析1.1.4 拓展案例二&#xff1a;社交媒体情感分析 1.2 安装和配置 Pandas1.2.1 基础知识1.2.2 案例&#xff1a;个人财务管理1.2.3 拓展案例一&#xff1…

Qt之QLabel介绍

概述 QLabel是QT界面中的标签类&#xff0c;它从QFrame下继承&#xff0c;QLabel 类代表标签&#xff0c;它是一个用于显示文本或图像的窗口部件。我们主要介绍一下QLabel的一些简单的使用。 设置颜色背景色和字体的颜色大小 字体及颜色 设置文字使用的是setText函数。 QStri…

linux中常用的命令

一&#xff1a;tree命令 &#xff08;码字不易&#xff0c;关注一下吧&#xff0c;w~~w) 以树状形式查看指定目录内容。 tree --树状显示当前目录下的文件信息。 tree 目录 --树状显示指定目录下的文件信息。 注意&#xff1a; tree只能查看目录内容&#xff0c;不能…

如何抠图换背景?分享6个不能错过的工具!

在数字化时代&#xff0c;抠图换背景已经成为了一种常见的图像处理需求。无论是出于商业宣传、个人创作还是日常生活分享的需要&#xff0c;抠图换背景都能帮助我们创造出更具视觉冲击力、更富有个性的图片。那么&#xff0c;如何进行抠图换背景呢&#xff1f;又有哪些工具可以…

云计算HCIE备考经验分享

大家好&#xff0c;我是来自深圳信息职业技术学院22级鲲鹏3-1班的刘同学&#xff0c;在2023年9月19日成功通过了华为云计算HCIE认证&#xff0c;并且取得了A的成绩。下面把我的考证经验分享给大家。 转专业进鲲鹏班考HCIE 大一上学期的时候&#xff0c;在上Linux课程的时候&…

2024新鲜出炉 Java集合常见面试题总结(上)

2024新鲜出炉 Java集合常见面试题总结(上) 文章目录 2024新鲜出炉 Java集合常见面试题总结(上)集合概述Java 集合概览说说 List, Set, Queue, Map 四者的区别&#xff1f;集合框架底层数据结构总结ListSetQueueMap 如何选用集合?为什么要使用集合&#xff1f; ListArrayList 和…

MySql 慢SQL配置,查询,处理

一.慢SQL配置相关 1.查看慢SQL是否开启 执行下面命令查看是否开启慢SQL show variables like %slow_query_log; 复制代码 OFF: 未开启ON: 2.打开慢SQL配置 执行下面的命令开启慢查询日志 set global slow_query_logON; 复制代码 3.修改慢查询阈值 前面介绍了SQL执行到达了…

SD-WAN和专线混合组网:企业出海网络解决方案

目前&#xff0c;有很多国内企业涉足海外业务&#xff0c;如跨境电商、游戏、社交网络、区块链等。都会使用海外服务器。同时&#xff0c;这些企业在国内还有自己的机房&#xff0c;IDC或者使用国内其他云厂商的机房。如果他们想要相互通信或传输数据该怎么办&#xff1f;在成本…