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

