客户端日志上报怎么设计?让线上问题不再只靠用户截图

📅 发布时间:2026/7/12 1:25:42 👁️ 浏览次数:
客户端日志上报怎么设计?让线上问题不再只靠用户截图
线上问题最难排查的情况不是系统直接崩了而是用户说刚才不能用了 点了没反应 字幕突然不刷新了 我也不知道发生了什么这类反馈很常见但如果客户端没有日志上来只能反复追问你用的什么系统 当时点了哪个按钮 有没有报错 网络正常吗 能不能录屏排查效率会非常低。所以客户端日志上报不是可有可无的功能而是产品稳定性的重要基础。一、客户端日志要解决什么问题客户端日志的核心目标不是“记录越多越好”而是帮助开发快速回答几个问题用户当时做了什么 系统进入了哪个页面 接口有没有失败 设备和版本是什么 错误发生在哪个阶段 是否可以复现同类问题例如一个实时翻译产品出现“字幕不刷新”仅靠用户描述很难判断原因。可能是麦克风权限异常 网络连接中断 接口请求失败 实时连接断开 服务端任务状态异常 前端渲染报错如果客户端能上报关键日志排查方向会清楚很多。二、日志要分级不要所有日志都当成错误。常见日志等级可以分为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 上使用实时翻译、双语字幕、语音播报和会议总结功能。如果没有客户端日志很多问题只能靠截图和描述猜测。如果日志体系足够清晰开发就可以更快判断问题出在设备权限、网络连接、实时任务、音频播放还是服务端处理链路。这才是客户端日志真正的意义。