1
This commit is contained in:
310
utils/logger.js
Normal file
310
utils/logger.js
Normal file
@@ -0,0 +1,310 @@
|
||||
/**
|
||||
* 日志管理系统
|
||||
* 提供分级日志记录、错误追踪、性能监控
|
||||
*/
|
||||
|
||||
class Logger {
|
||||
constructor() {
|
||||
this.logs = []
|
||||
this.maxLogs = 1000 // 最多保存1000条日志
|
||||
this.level = 'info' // debug, info, warn, error
|
||||
this.enableConsole = true
|
||||
this.enableStorage = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 日志级别枚举
|
||||
*/
|
||||
static LEVELS = {
|
||||
DEBUG: 0,
|
||||
INFO: 1,
|
||||
WARN: 2,
|
||||
ERROR: 3
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录调试信息
|
||||
*/
|
||||
debug(message, data = {}) {
|
||||
this._log('DEBUG', message, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录普通信息
|
||||
*/
|
||||
info(message, data = {}) {
|
||||
this._log('INFO', message, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录警告信息
|
||||
*/
|
||||
warn(message, data = {}) {
|
||||
this._log('WARN', message, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录错误信息
|
||||
*/
|
||||
error(message, data = {}) {
|
||||
this._log('ERROR', message, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心日志方法
|
||||
*/
|
||||
_log(level, message, data) {
|
||||
const log = {
|
||||
level,
|
||||
message,
|
||||
data,
|
||||
timestamp: new Date().toISOString(),
|
||||
page: getCurrentPages().length > 0 ? getCurrentPages()[getCurrentPages().length - 1].route : 'unknown'
|
||||
}
|
||||
|
||||
// 添加到内存
|
||||
this.logs.push(log)
|
||||
if (this.logs.length > this.maxLogs) {
|
||||
this.logs.shift()
|
||||
}
|
||||
|
||||
// 输出到控制台
|
||||
if (this.enableConsole) {
|
||||
const consoleMethod = level.toLowerCase()
|
||||
console[consoleMethod](`[${level}] ${message}`, data)
|
||||
}
|
||||
|
||||
// 保存到本地存储
|
||||
if (this.enableStorage && level === 'ERROR') {
|
||||
this._persistErrorLog(log)
|
||||
}
|
||||
|
||||
// 上报严重错误
|
||||
if (level === 'ERROR') {
|
||||
this._reportError(log)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 持久化错误日志
|
||||
*/
|
||||
_persistErrorLog(log) {
|
||||
try {
|
||||
const errorLogs = wx.getStorageSync('errorLogs') || []
|
||||
errorLogs.push(log)
|
||||
|
||||
// 只保留最近100条错误
|
||||
if (errorLogs.length > 100) {
|
||||
errorLogs.shift()
|
||||
}
|
||||
|
||||
wx.setStorageSync('errorLogs', errorLogs)
|
||||
} catch (e) {
|
||||
console.error('日志持久化失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上报错误
|
||||
*/
|
||||
_reportError(log) {
|
||||
// TODO: 接入错误监控平台(如 Sentry)
|
||||
console.log('错误上报:', log)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取日志
|
||||
*/
|
||||
getLogs(filter = {}) {
|
||||
let logs = this.logs
|
||||
|
||||
if (filter.level) {
|
||||
logs = logs.filter(log => log.level === filter.level)
|
||||
}
|
||||
|
||||
if (filter.page) {
|
||||
logs = logs.filter(log => log.page === filter.page)
|
||||
}
|
||||
|
||||
if (filter.startTime) {
|
||||
logs = logs.filter(log => new Date(log.timestamp) >= new Date(filter.startTime))
|
||||
}
|
||||
|
||||
return logs
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空日志
|
||||
*/
|
||||
clearLogs() {
|
||||
this.logs = []
|
||||
wx.removeStorageSync('errorLogs')
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出日志
|
||||
*/
|
||||
exportLogs() {
|
||||
return {
|
||||
logs: this.logs,
|
||||
exportTime: new Date().toISOString(),
|
||||
systemInfo: wx.getSystemInfoSync()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误处理器
|
||||
*/
|
||||
class ErrorHandler {
|
||||
constructor() {
|
||||
this.logger = new Logger()
|
||||
this.setupGlobalErrorHandler()
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置全局错误捕获
|
||||
*/
|
||||
setupGlobalErrorHandler() {
|
||||
// 捕获未处理的Promise错误
|
||||
wx.onUnhandledRejection((res) => {
|
||||
this.handleError('UnhandledRejection', res.reason)
|
||||
})
|
||||
|
||||
// 捕获小程序错误
|
||||
wx.onError((error) => {
|
||||
this.handleError('AppError', error)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理错误
|
||||
*/
|
||||
handleError(type, error, context = {}) {
|
||||
const errorInfo = {
|
||||
type,
|
||||
message: error.message || error,
|
||||
stack: error.stack || '',
|
||||
context,
|
||||
userAgent: wx.getSystemInfoSync(),
|
||||
timestamp: Date.now()
|
||||
}
|
||||
|
||||
this.logger.error(`${type}: ${errorInfo.message}`, errorInfo)
|
||||
|
||||
// 显示用户友好的错误提示
|
||||
this.showUserFriendlyError(type, error)
|
||||
|
||||
return errorInfo
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示用户友好的错误提示
|
||||
*/
|
||||
showUserFriendlyError(type, error) {
|
||||
const errorMessages = {
|
||||
'NetworkError': '网络连接失败,请检查网络设置',
|
||||
'StorageError': '存储空间不足,请清理缓存',
|
||||
'UnhandledRejection': '操作失败,请重试',
|
||||
'AppError': '应用出现异常,请重启小程序'
|
||||
}
|
||||
|
||||
const message = errorMessages[type] || '操作失败,请稍后重试'
|
||||
|
||||
wx.showToast({
|
||||
title: message,
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 性能监控
|
||||
*/
|
||||
monitorPerformance(name, startTime) {
|
||||
const duration = Date.now() - startTime
|
||||
|
||||
if (duration > 1000) {
|
||||
this.logger.warn(`性能警告: ${name} 耗时 ${duration}ms`)
|
||||
}
|
||||
|
||||
return duration
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取错误统计
|
||||
*/
|
||||
getErrorStats() {
|
||||
const errorLogs = wx.getStorageSync('errorLogs') || []
|
||||
|
||||
const stats = {
|
||||
total: errorLogs.length,
|
||||
byType: {},
|
||||
byPage: {},
|
||||
recent: errorLogs.slice(-10)
|
||||
}
|
||||
|
||||
errorLogs.forEach(log => {
|
||||
stats.byType[log.data.type] = (stats.byType[log.data.type] || 0) + 1
|
||||
stats.byPage[log.page] = (stats.byPage[log.page] || 0) + 1
|
||||
})
|
||||
|
||||
return stats
|
||||
}
|
||||
}
|
||||
|
||||
// 创建全局实例
|
||||
const logger = new Logger()
|
||||
const errorHandler = new ErrorHandler()
|
||||
|
||||
/**
|
||||
* 用户反馈系统
|
||||
*/
|
||||
class FeedbackSystem {
|
||||
/**
|
||||
* 提交反馈
|
||||
*/
|
||||
static submit(feedback) {
|
||||
const feedbackData = {
|
||||
...feedback,
|
||||
timestamp: Date.now(),
|
||||
systemInfo: wx.getSystemInfoSync(),
|
||||
logs: logger.getLogs({ level: 'ERROR' }).slice(-20)
|
||||
}
|
||||
|
||||
logger.info('用户反馈', feedbackData)
|
||||
|
||||
// TODO: 上传到服务器
|
||||
this._saveLocal(feedbackData)
|
||||
|
||||
return feedbackData
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存到本地
|
||||
*/
|
||||
static _saveLocal(feedback) {
|
||||
try {
|
||||
const feedbacks = wx.getStorageSync('userFeedbacks') || []
|
||||
feedbacks.push(feedback)
|
||||
wx.setStorageSync('userFeedbacks', feedbacks)
|
||||
} catch (e) {
|
||||
console.error('反馈保存失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取反馈列表
|
||||
*/
|
||||
static getList() {
|
||||
return wx.getStorageSync('userFeedbacks') || []
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
logger,
|
||||
errorHandler,
|
||||
Logger,
|
||||
ErrorHandler,
|
||||
FeedbackSystem
|
||||
}
|
||||
Reference in New Issue
Block a user