This commit is contained in:
2026-09-13 02:28:46 +08:00
parent df5492a48a
commit 42f9530a59
27 changed files with 979 additions and 149 deletions
+141
View File
@@ -0,0 +1,141 @@
import { LogLevel, LOG_LEVEL, LOG_TO_REALTIME } from './config'
/**
* 全项目统一日志出口。
*
* 用法:logger.debug('模块名', '消息', 任意参数)
* 级别:DEBUG < INFO < WARN < ERROR < SILENT,低于当前生效级别的调用直接返回,
* 且级别判断前置,不做任何字符串拼接,热路径(如每次请求)零开销。
*
* 输出:
* 1. console —— 按级别选用 log / warn / error,开发者工具与真机调试可见
* 2. 微信实时日志 —— 仅 WARN 及以上写入,可在小程序后台「实时日志」查询线上问题
*/
// 手动覆盖的级别(LOG_LEVEL 为 null 时按环境自动推导)
let manualLevel: LogLevel | null = LOG_LEVEL
// 解析后的生效级别缓存,避免每次调用都读环境信息
let resolvedLevel: LogLevel | null = null
const LEVEL_NAMES: Record<number, string> = {
[LogLevel.DEBUG]: 'DEBUG',
[LogLevel.INFO]: 'INFO',
[LogLevel.WARN]: 'WARN',
[LogLevel.ERROR]: 'ERROR',
}
// 按运行环境推导默认级别:开发版最详细,正式版只看异常
function resolveByEnv(): LogLevel {
try {
const info = wx.getAccountInfoSync()
const env = info.miniProgram && info.miniProgram.envVersion
if (env === 'develop') return LogLevel.DEBUG
if (env === 'trial') return LogLevel.INFO
return LogLevel.WARN
} catch (e) {
// 取不到环境信息时(低版本基础库等)退化为 DEBUG,保证开发期可见
return LogLevel.DEBUG
}
}
// 当前生效级别
export function getLevel(): LogLevel {
if (resolvedLevel === null) {
resolvedLevel = manualLevel === null ? resolveByEnv() : manualLevel
}
return resolvedLevel
}
/**
* 运行时调整日志级别(调级后对全局生效)。
* 传 null 恢复为「按环境自动」。
*/
export function setLevel(level: LogLevel | null): void {
manualLevel = level
resolvedLevel = null
}
// 实时日志单例(惰性初始化,取不到时降级为仅 console,绝不因日志抛错影响业务)
let realtimeManager: any = null
let realtimeInited = false
function getRealtimeManager(): any {
if (realtimeInited) return realtimeManager
realtimeInited = true
try {
if (typeof wx.getRealtimeLogManager === 'function') {
realtimeManager = wx.getRealtimeLogManager()
}
} catch (e) {
realtimeManager = null
}
return realtimeManager
}
// 序列化日志参数:实时日志有单条长度限制,做截断保护
function stringify(args: any[]): string {
try {
return args
.map((a) => {
if (typeof a === 'string') return a
try {
return JSON.stringify(a)
} catch (e) {
return String(a)
}
})
.join(' ')
.slice(0, 1000)
} catch (e) {
return ''
}
}
function emit(level: LogLevel, module: string, args: any[]): void {
if (level < getLevel()) return
const prefix = `[${LEVEL_NAMES[level]}][${module}]`
// console 通道
if (level === LogLevel.ERROR) {
console.error(prefix, ...args)
} else if (level === LogLevel.WARN) {
console.warn(prefix, ...args)
} else {
console.log(prefix, ...args)
}
// 实时日志通道:仅 WARN 及以上,避免击穿配额
if (!LOG_TO_REALTIME || level < LogLevel.WARN) return
const manager = getRealtimeManager()
if (!manager) return
const text = `${prefix} ${stringify(args)}`
try {
if (level === LogLevel.ERROR && typeof manager.error === 'function') manager.error(text)
else if (typeof manager.warn === 'function') manager.warn(text)
} catch (e) {
// 日志写入失败不影响业务
}
}
export const logger = {
/** 开发期流程细节:页面入参、请求发起/成功、数据条数 */
debug(module: string, ...args: any[]): void {
emit(LogLevel.DEBUG, module, args)
},
/** 关键流程节点:登录成功、刷新成功、下单/上传/分享成功 */
info(module: string, ...args: any[]): void {
emit(LogLevel.INFO, module, args)
},
/** 可恢复异常与静默降级:静默 catch、跳转失败、非关键请求失败 */
warn(module: string, ...args: any[]): void {
emit(LogLevel.WARN, module, args)
},
/** 真正的错误:网络异常、业务错误码、账号禁用、登录态失效 */
error(module: string, ...args: any[]): void {
emit(LogLevel.ERROR, module, args)
},
}
export default logger