客户端日志上报怎么设计?让线上问题不再只靠用户截图
线上问题最难排查的情况,不是系统直接崩了,而是用户说:
刚才不能用了 点了没反应 字幕突然不刷新了 我也不知道发生了什么这类反馈很常见,但如果客户端没有日志,上来只能反复追问:
你用的什么系统? 当时点了哪个按钮? 有没有报错? 网络正常吗? 能不能录屏?排查效率会非常低。
所以,客户端日志上报不是可有可无的功能,而是产品稳定性的重要基础。
一、客户端日志要解决什么问题?
客户端日志的核心目标不是“记录越多越好”,而是帮助开发快速回答几个问题:
用户当时做了什么? 系统进入了哪个页面? 接口有没有失败? 设备和版本是什么? 错误发生在哪个阶段? 是否可以复现同类问题?例如一个实时翻译产品出现“字幕不刷新”,仅靠用户描述很难判断原因。
可能是:
麦克风权限异常 网络连接中断 接口请求失败 实时连接断开 服务端任务状态异常 前端渲染报错如果客户端能上报关键日志,排查方向会清楚很多。
二、日志要分级
不要所有日志都当成错误。
常见日志等级可以分为:
DEBUG:调试信息 INFO:正常业务流程 WARN:异常但可恢复 ERROR:明确错误 FATAL:严重崩溃或不可继续使用例如:
logger.info('translation_task_start', { taskId, languagePair: 'en-zh' }); logger.warn('websocket_reconnect', { retryCount: 2 }); logger.error('translation_task_failed', { taskId, errorCode: 'NETWORK_TIMEOUT' });这样后端分析日志时,可以优先关注ERROR和FATAL,而不是在大量普通信息中查找问题。
三、日志内容应该包含哪些字段?
一条可用的客户端日志,最好包含这些基础字段:
logId:日志唯一 ID level:日志等级 eventName:事件名称 timestamp:发生时间 userId:用户 ID deviceId:设备 ID appVersion:客户端版本 platform:平台,如 Web、Windows、macOS、iOS、Android page:当前页面 message:日志描述 extra:额外上下文示例:
{ "logId": "log_10001", "level": "ERROR", "eventName": "voice_playback_failed", "timestamp": 1718000000000, "userId": "u_10001", "platform": "macOS", "appVersion": "2.1.0", "page": "translation", "message": "voice playback failed", "extra": { "taskId": "task_20001", "languagePair": "en-ja", "errorCode": "AUDIO_DEVICE_NOT_FOUND" } }字段越规范,后期检索和统计越方便。
四、关键业务流程要埋点式记录
客户端日志不应该只记录错误,也要记录关键流程。
例如同言翻译(Transync AI)这类实时翻译产品,一次完整任务可能包括:
选择语言 选择模型 开启麦克风 开启电脑音频 开始实时翻译 生成双语字幕 开启语音播报 暂停或停止任务 生成 AI 会议总结这些节点都可以记录为普通INFO日志。
例如:
logger.info('translation_task_created', { sourceLang: 'en', targetLang: 'zh', model: 'Monsoon 2.0' }); logger.info('computer_audio_enabled', { success: true }); logger.info('meeting_summary_generate_clicked', { taskId });当用户反馈“会议总结没有生成”时,开发可以从日志里看到:
用户是否真的点击了生成总结 任务是否正常结束 生成总结接口是否发起 接口是否返回失败 失败码是什么这比单纯看服务端日志更完整。
五、错误日志要带上下文
很多错误日志写得太简单:
console.error(error);这种日志对排查帮助有限。
更好的方式是带上上下文:
logger.error('api_request_failed', { url: '/api/translation/start', method: 'POST', status: 500, requestId: 'req_abc123', taskId: 'task_10001', errorMessage: error.message });尤其是接口错误,最好同时记录:
请求路径 请求方法 状态码 requestId 业务 taskId 错误码 重试次数这样客户端日志可以和服务端日志通过requestId串起来。
否则客户端只知道“请求失败”,服务端却很难定位是哪一次请求。
六、日志不要实时逐条上报
如果每产生一条日志就请求一次接口,会造成很多额外流量。
更推荐先写入本地队列,再批量上报。
const logQueue = []; function pushLog(log) { logQueue.push({ ...log, timestamp: Date.now() }); if (logQueue.length >= 20) { flushLogs(); } }批量上报:
async function flushLogs() { if (logQueue.length === 0) return; const logs = logQueue.splice(0, logQueue.length); try { await fetch('/api/client-logs', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(logs) }); } catch (error) { logQueue.unshift(...logs); } }再配合定时上报:
setInterval(flushLogs, 10000);这样既能减少请求数量,也能避免日志上报影响正常业务接口。
七、页面关闭前要尽量补发
Web 端用户关闭页面时,普通请求可能还没发完。
可以用sendBeacon上报最后一批日志:
window.addEventListener('pagehide', () => { if (logQueue.length === 0) return; const logs = logQueue.splice(0, logQueue.length); navigator.sendBeacon( '/api/client-logs', JSON.stringify(logs) ); });不过要注意,sendBeacon适合小数据量。
不要在页面关闭时上报过大的日志包。
八、本地日志也要保留一部分
对于桌面客户端或移动端 App,可以保留最近一段本地日志。
例如:
最近 24 小时日志 最近 2000 条日志 最近 10 个任务日志当用户反馈问题时,可以引导用户上传日志文件。
本地日志适合记录更详细的信息,上报日志则适合记录关键事件和错误摘要。
两者可以配合使用:
普通日志:本地保存 关键错误:立即上报 用户反馈:上传最近日志这样既能控制服务端存储压力,也能在需要时拿到完整线索。
九、必须做隐私脱敏
客户端日志很容易不小心带上敏感信息。
不要上报:
密码 验证码 Token 完整手机号 完整邮箱 身份证号 银行卡号 会议原文内容 用户输入的完整文本例如实时翻译类产品,日志可以记录:
{ "eventName": "translation_task_start", "languagePair": "en-zh", "duration": 1800, "platform": "Windows" }但不应该把完整会议内容、用户语音文本、个人隐私信息直接塞进日志。
可以做统一脱敏:
function maskEmail(email) { return email.replace( /(.{2}).+(@.+)/, '$1***$2' ); }日志系统的目标是排查问题,不是收集用户内容。
十、日志上报要有开关
日志系统本身也可能出问题。
例如:
日志接口异常 日志量突然变大 某个版本疯狂上报重复错误 用户网络较差所以客户端日志最好支持远程配置:
是否开启日志上报 上报采样率 哪些等级需要上报 单次最大日志数量 是否允许上传本地日志例如:
{ "enableClientLog": true, "sampleRate": 0.2, "uploadLevels": ["WARN", "ERROR", "FATAL"] }这样当日志量异常时,可以通过配置降低上报比例,而不是重新发版。
十一、客户端日志检查清单
设计客户端日志上报时,可以检查:
1. 是否有统一日志格式? 2. 是否区分 INFO、WARN、ERROR? 3. 是否记录 appVersion 和 platform? 4. 是否能通过 requestId 关联服务端日志? 5. 是否记录关键业务流程? 6. 是否支持批量上报? 7. 页面关闭前是否尽量补发? 8. 本地是否保留最近日志? 9. 是否做敏感信息脱敏? 10. 是否支持远程开关和采样率?总结
客户端日志上报的价值,是让线上问题从“用户描述”变成“可追踪证据”。
一套实用的客户端日志系统,通常需要包含:
统一日志格式 日志等级 关键流程记录 错误上下文 批量上报 本地缓存 隐私脱敏 远程开关 requestId 串联对于同言翻译(Transync AI)这类跨平台实时产品来说,用户可能在 Windows、macOS、iOS、Android 或 Web 上使用实时翻译、双语字幕、语音播报和会议总结功能。
如果没有客户端日志,很多问题只能靠截图和描述猜测。
如果日志体系足够清晰,开发就可以更快判断:问题出在设备权限、网络连接、实时任务、音频播放,还是服务端处理链路。
这才是客户端日志真正的意义。
