You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
3.5 KiB
104 lines
3.5 KiB
|
1 week ago
|
import { DEV } from 'cc/env';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 线上诊断:仅白名单 tag 上传平台(pfLog + RealtimeLogManager)。
|
||
|
|
* 其余只打 DEV console,避免误报占满后台配额。
|
||
|
|
* 单条 ≤256 字符;同 key 默认 10 分钟冷却。
|
||
|
|
*/
|
||
|
|
export class PfDiagnostics {
|
||
|
|
private static _realtime: { error?: (m: string) => void; warn?: (m: string) => void; info?: (m: string) => void; log?: (m: string) => void } | null = null;
|
||
|
|
private static _filterReady = false;
|
||
|
|
private static _lastMsByKey: Record<string, number> = {};
|
||
|
|
|
||
|
|
/** 仅这些 key 实际上传抖音/微信日志后台(预警波次类 WARN 仅本地,不上传) */
|
||
|
|
private static readonly PLATFORM_UPLOAD_KEYS = new Set([
|
||
|
|
'BATTLE:STUCK_PAUSE',
|
||
|
|
'SETTLE:OPEN_FAIL',
|
||
|
|
'SKILL:OPEN_FAIL',
|
||
|
|
'SKILL:OPEN_RELOAD',
|
||
|
|
'STACK:BLOCK_STACK',
|
||
|
|
'STACK:PIN_COLLAPSE',
|
||
|
|
'MEM:WARN',
|
||
|
|
]);
|
||
|
|
|
||
|
|
private static _realtimeLogger() {
|
||
|
|
if (this._realtime !== null) return this._realtime;
|
||
|
|
const pf = gg?.sdk?.pf ?? (typeof globalThis !== 'undefined' ? (globalThis as any).tt : null);
|
||
|
|
if (!pf?.getRealtimeLogManager) {
|
||
|
|
this._realtime = null;
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
const logger = pf.getRealtimeLogManager({ syncToConsole: !!DEV });
|
||
|
|
if (!this._filterReady) {
|
||
|
|
logger.addFilterMsg?.('xxfkz');
|
||
|
|
this._filterReady = true;
|
||
|
|
}
|
||
|
|
this._realtime = logger;
|
||
|
|
} catch {
|
||
|
|
this._realtime = null;
|
||
|
|
}
|
||
|
|
return this._realtime;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static _battlePrefix(): string {
|
||
|
|
const b = gg.game?.CurentBattle;
|
||
|
|
const ch = b?.getReportDYChapterId?.() ?? gg.data?.doc?.chapter ?? 0;
|
||
|
|
const wave = b?.CurentWaveNum ?? 0;
|
||
|
|
return `ch${ch}_w${wave}`;
|
||
|
|
}
|
||
|
|
|
||
|
|
static shouldUploadPlatform(domain: string, tag: string): boolean {
|
||
|
|
return this.PLATFORM_UPLOAD_KEYS.has(`${domain}:${tag}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** @returns 是否实际上传平台(冷却或未在白名单会返回 false) */
|
||
|
|
static write(
|
||
|
|
domain: string,
|
||
|
|
tag: string,
|
||
|
|
detail: string,
|
||
|
|
cooldownMs = 600000,
|
||
|
|
level: 'error' | 'warn' | 'info' = 'warn',
|
||
|
|
): boolean {
|
||
|
|
const key = `${domain}:${tag}`;
|
||
|
|
const upload = this.shouldUploadPlatform(domain, tag);
|
||
|
|
|
||
|
|
let msg = `${this._battlePrefix()}-${domain}-${tag}-${detail}`;
|
||
|
|
if (msg.length > 250) msg = msg.slice(0, 250);
|
||
|
|
|
||
|
|
if (DEV) {
|
||
|
|
console.warn('[PfDiag]', upload ? msg : `[local-only] ${msg}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!upload) return false;
|
||
|
|
|
||
|
|
const now = Date.now();
|
||
|
|
const last = this._lastMsByKey[key] ?? 0;
|
||
|
|
if (now - last < cooldownMs) return false;
|
||
|
|
this._lastMsByKey[key] = now;
|
||
|
|
|
||
|
|
try {
|
||
|
|
gg.sdk?.pfLog?.(msg);
|
||
|
|
} catch { /* ignore */ }
|
||
|
|
|
||
|
|
const logger = this._realtimeLogger();
|
||
|
|
if (logger) {
|
||
|
|
const fn = logger[level] ?? logger.warn ?? logger.log;
|
||
|
|
try {
|
||
|
|
fn?.call(logger, msg);
|
||
|
|
} catch { /* ignore */ }
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 离开战斗回大厅:清掉战斗域诊断冷却,新局可重新上报 */
|
||
|
|
static resetBattleSession(): void {
|
||
|
|
const battleDomains = new Set(['BATTLE', 'STACK', 'SETTLE', 'SKILL']);
|
||
|
|
for (const key of Object.keys(this._lastMsByKey)) {
|
||
|
|
if (battleDomains.has(key.split(':')[0] ?? '')) {
|
||
|
|
delete this._lastMsByKey[key];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|