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平台未做测试。
尾巴
今天的文章就到这里了,希望能给大家帮助,如果喜欢我的文章,欢迎给我点赞,评论,关注,谢谢大家!