加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.0155.com.cn/)- 应用程序、AI行业应用、CDN、低代码、区块链!
当前位置: 首页 > 创业 > 资本 > 正文

VR创业三年闭环:日志工程师的7个技术决策点

发布时间:2026-11-06 11:32:52 所属栏目:资本 来源:DaWei
导读:  去年六月,VR头显交付前两周,我蹲在测试间看控制台报错——不是红字,是灰的,console.warn里塞满three.js的texture memory exceeded,但日志系统压根没上报,因为埋点SDK根本没加载完就崩在polyfill里。会议室白板没擦干净

  去年六月,VR头显交付前两周,我蹲在测试间看控制台报错——不是红字,是灰的,console.warn里塞满three.js的texture memory exceeded,但日志系统压根没上报,因为埋点SDK根本没加载完就崩在polyfill里。会议室白板没擦干净,上一轮画的埋点拓扑图还糊着半截箭头,产品经理站在投影仪阴影里说“用户行为数据得实时看”,我说“你先让我把GPU崩溃前那120ms的log捞出来”。


  先扔结论:七个决策点里,六个是别人拍的,剩下一个是我咬牙扛的——不往webpack配置里加source-map,连devtool都不设。不是不想,是测试机型号太绝:HTC Vive Pro Eye+Windows 10 LTSC,自带Edge Legacy内核,打开开发者工具直接卡死,F12按下去三秒才弹出空白面板。那天键盘上有个键掉了,R键,我敲console.log的时候老按成E,输出一堆undefined,没人提醒,因为背后有人走过碰了椅子,椅子腿刮地声比报错声还响。


  第一个决策点,日志采样率。后端接口又变了,把/user/info接口拆成/user/profile和/user/permissions,字段名全小写变驼峰,前端埋点还没改,我们日志管道里已经攒了三天的空字段。我说降采样到5%,产品说“核心路径必须100%”,我当场改了nginx配置,在location /api/log/ 下加了if ($http_user_agent ~ "Vive|Quest") { set $sample 0.05; }——行吧,反正他也没真去看日志量。外卖到了没人去拿,泡面汤渗进纸袋边角,凉了。


  第二个,本地缓存策略。不是localStorage那种玩具,是IndexedDB写满再刷盘。设计给的图没有标注,但交互稿里有一帧“视线停留3秒触发事件”,实际跑起来发现HMD眼动追踪延迟不稳,同一台机器上有的帧停住不动,有的直接跳过。我们只好在onXRFrame里塞了debounce,但debounce函数本身在Web Worker里跑,结果日志打在worker线程里,Chrome Performance面板里看到一整条长任务块,耗时大概几秒,记不清了,只记得timeline里那条红色的长条像焊在UI线程上一样。工位的显示器是竖着的,看日志滚动太费劲,后来我就把terminal拖进横屏区域,光标总对不准。


  第三个,错误捕获时机。try-catch盖不住WebGLContextLost,window.onerror也抓不到Shader编译失败。最后靠的是在renderer.render()外层包了个setImmediate兜底,但setImmediate在Edge Legacy里不存在——于是我们写了段检测逻辑,if (!window.setImmediate) window.setImmediate = function(f){ setTimeout(f,0); };提交记录里这行代码的hash是a3f7d8c,日期是去年六月十八号晚上十一点四十七分,commit message写的是“别问,问就是它让vive能吐错”。


  第四个,上报通道。原定走HTTPS直报,结果某次灰度发现Quest 2设备在某些运营商网络下,POST 2KB以上JSON必超时。最后切了双通道:小于1KB走fetch,大于走Image().src带query参数。构建日志里那一行warning现在还钉在我脑仁里:“WARNING: image-based logging violates CSP img-src ‘self’”,可CSP规则是后端配的,他们说“先上线再说”,上线后三天,CDN缓存规则又被运维手动改过一次,导致部分设备上报URL 404——但我们没日志,因为404根本没进我们的捕获逻辑,只有浏览器network tab里静静躺着一堆灰色404。


  第五个,日志结构体。本来约定所有event都带device_id、session_id、timestamp,结果Unity导出的SDK包把session_id硬编码成"unity_default",连续五天日志里查不出单用户行为路径。我拉了三次git blame,定位到一位实习生的PR,改了一行:`sessionId = PlayerPrefs.GetString("session_id", "unity_default");`,注释写着“避免空指针崩溃”。没人怪他,因为那天下午三点他提了PR,四点人就拎包走了,HR说“个人原因”。我坐在那儿删掉那行,改成生成UUID,改完发现Unity C#里生成UUID居然要引System.Security.Cryptography,而那个命名空间在IL2CPP下默认关掉……最后抄了篇Stack Overflow的旧帖,用时间戳+随机数拼了个伪ID,凑合到上线。


  第六个,调试开关。上线前夜,测试发现所有点击事件都漏埋,排查半小时,发现埋点SDK的debug开关被product环境变量覆盖成false,而开关逻辑写在entry.js第一行——但Webpack 4的tree-shaking把它干掉了,因为没人调用console.debug。我们最后补了个无副作用的语句:void (window.DEBUG_LOG || console.debug(''));就为了骗过摇树。有人端着杯子站了很久,水汽在杯壁结了雾,他没喝,也没放下,就在那儿看着终端里滚动的日志流,像在等一个不会来的响应。


  第七个,也就是最后一个,是我在六月二十三号凌晨三点干的:把所有日志上报的body JSON序列化函数,换成JSON.stringify(obj, null, 0),去掉所有换行缩进。就这一行改,日志体积从平均2.3KB压到1.6KB,Quest 2设备上报成功率从78%提到92%——我没验证,因为第二天早上八点客户就要看demo,我直接上了,没测。后来有同事问“为啥不用MessagePack”,我说:“你告诉我哪款VR一体机的WebGL runtime里自带解码器?”


文章配图,仅供参考

  现在我每天早上开电脑,先看Prometheus里log_ingest_failed_total指标。它还在涨,但涨得慢了。上周我把那段兜底的setImmediate替换成queueMicrotask,只在现代浏览器生效,旧设备依旧走setTimeout——没全切,因为测试机里还有两台Oculus Go,它的Chrome内核版本锁死在61,queueMicrotask不存在。我留着那个if分支,就像留着一块没擦干净的白板,不碍事,但知道它在那儿。


  下一步?下周开始砍掉所有console.warn日志上报——它们占体积、不关键、且基本都是three.js自己报的废话。我已经写好filter正则:/^THREE\\.|WebGL:|gl\\./i,明早merge。要是哪个产品经理非要看warn,让他自己搭个本地server,curl --data-binary 拉原始console输出。我不拦。

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!