mirror of
https://wget.la/https://github.com/Wxw-Gu/WechatExplorer
synced 2026-08-18 12:07:01 +08:00
chore: 添加应用诊断日志
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { app, shell } from 'electron'
|
||||
import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import type { AppLogEntry } from '../shared/app-log'
|
||||
|
||||
const MAX_LOG_BYTES = 5 * 1024 * 1024
|
||||
const REDACTED_KEY = /(?:api[-_]?key|authorization|token|secret|password|database[-_]?key)/i
|
||||
|
||||
const sanitize = (value: unknown, depth = 0): unknown => {
|
||||
if (depth > 4) return '[depth-limited]'
|
||||
if (typeof value === 'string') {
|
||||
return value
|
||||
.replace(/\bsk-[a-z0-9_-]{8,}\b/gi, '***')
|
||||
.replace(/\bBearer\s+[a-z0-9._~-]{8,}\b/gi, 'Bearer ***')
|
||||
.slice(0, 2000)
|
||||
}
|
||||
if (Array.isArray(value)) return value.slice(0, 30).map((item) => sanitize(item, depth + 1))
|
||||
if (value && typeof value === 'object') {
|
||||
return Object.fromEntries(
|
||||
Object.entries(value as Record<string, unknown>).map(([key, item]) => [
|
||||
key,
|
||||
REDACTED_KEY.test(key) ? '***' : sanitize(item, depth + 1)
|
||||
])
|
||||
)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
export class AppLogger {
|
||||
private get logDir(): string {
|
||||
return app.getPath('logs')
|
||||
}
|
||||
|
||||
get logPath(): string {
|
||||
return path.join(this.logDir, 'wechatexplorer.log')
|
||||
}
|
||||
|
||||
private rotateIfNeeded(): void {
|
||||
try {
|
||||
if (!fs.existsSync(this.logPath) || fs.statSync(this.logPath).size < MAX_LOG_BYTES) return
|
||||
const previous = `${this.logPath}.1`
|
||||
if (fs.existsSync(previous)) fs.removeSync(previous)
|
||||
fs.moveSync(this.logPath, previous)
|
||||
} catch {
|
||||
// Logging must never interrupt the application.
|
||||
}
|
||||
}
|
||||
|
||||
write(entry: AppLogEntry): void {
|
||||
try {
|
||||
fs.ensureDirSync(this.logDir)
|
||||
this.rotateIfNeeded()
|
||||
const record = {
|
||||
timestamp: new Date().toISOString(),
|
||||
mode: app.isPackaged ? 'packaged' : 'development',
|
||||
level: entry.level,
|
||||
scope: String(entry.scope || 'app').slice(0, 80),
|
||||
message: String(entry.message || '').slice(0, 500),
|
||||
details: sanitize(entry.details || {})
|
||||
}
|
||||
fs.appendFileSync(this.logPath, `${JSON.stringify(record)}\n`, { encoding: 'utf8' })
|
||||
if (!app.isPackaged) {
|
||||
const method =
|
||||
entry.level === 'error'
|
||||
? console.error
|
||||
: entry.level === 'warn'
|
||||
? console.warn
|
||||
: console.log
|
||||
method(`[${record.scope}] ${record.message}`, record.details)
|
||||
}
|
||||
} catch {
|
||||
// Logging must never interrupt the application.
|
||||
}
|
||||
}
|
||||
|
||||
reveal(): void {
|
||||
fs.ensureDirSync(this.logDir)
|
||||
if (!fs.existsSync(this.logPath)) fs.writeFileSync(this.logPath, '', 'utf8')
|
||||
shell.showItemInFolder(this.logPath)
|
||||
}
|
||||
}
|
||||
|
||||
export const appLogger = new AppLogger()
|
||||
Reference in New Issue
Block a user