文档 / 搜索 / LingCode Cloud / 数据分析
📘 参考 ● 遥测 更新于 2026-06-11

数据分析与遥测

一句话:SDK 自带第一方数据分析与错误上报——logEventlogScreentracerecordError,并可选地关联到真实的 setUserId。事件在客户端缓冲,刷新发送到你自己的后端,所以既不用额外引入第三方分析库,数据也从不脱离你的掌控。

大多数应用第一天就会接入一个托管分析 SDK,不出一周就把用户行为发往了别人的服务器,还要在构建里再接一套账号。LingCode Cloud 把这些基础能力——事件、屏幕浏览、计时和捕获到的错误——折叠进你已经用于数据和认证的同一个客户端。你调用一个方法,SDK 把它批处理,最后它落进你自己的后端。本页讲清这种拆分为什么重要,以及每个调用具体怎么用。

为什么内建

数据分析与崩溃上报,是几乎每个应用都需要、又几乎都外包出去的两件事。外包意味着打包里多一个依赖、多一个手握用户行为副本的厂商,以及又一个要登录的仪表盘。SDK 的 telemetry 接口把这三样都去掉了:你记录的事件被发到与你数据所在相同的后端,由客户端批处理并刷新发送,不必再安装任何额外的库。

这套模型刻意做得很小。你记录四类信号——事件、屏幕浏览、性能 trace 和错误——并且可以选择性地附上一个真实的用户 id,让数据按「谁做了什么」分群。其余的一切(缓冲、批处理、刷新失败重试)都已替你处理好。

数据去往何处

遥测是第一方的。事件累积在一个小的客户端缓冲里,被投递到你后端的遥测端点——它们不经过任何第三方分析服务。由于目的地就是你自己的 LingCode Cloud 后端,分析数据就停留在你应用其余数据所在的同一个地方。

遥测接口

一切都挂在 client.telemetry 上。下面的示例里客户端都叫 lingcode——在 /try 和 Mac 预览里它已经是 window.lingcode;在你自己的应用里,它是 LingCode.createClient(...) 返回的那个对象。

追踪一个动作

主力是 logEvent。给它一个名字,并可选地附上一袋扁平的标量参数作为上下文:

lingcode.telemetry.logEvent('checkout_started', { plan: 'pro', amount: 29 });

参数是为了之后切片分析——套餐档位、商品数量、用户看到的实验变体。保持它们为标量(stringnumberboolean),并把数量控制在 25 个键以内;嵌套对象和超量的键不该出现在一个事件里。

追踪一个屏幕

屏幕浏览有自己的简写,这样你就不必记住某种事件命名约定:

lingcode.telemetry.logScreen('Pricing');

这与一个针对 Pricing 屏幕的 screen_view 事件完全等价——在用户导航时,从每个路由或视图里调用它。

把分析关联到用户

默认情况下,事件不与任何人关联。一旦有人登录,就通过把他们的应用用户 id 交给遥测层来主动开启;登出时再次清除它,让下一次会话从干净状态开始:

// 登录成功后
lingcode.telemetry.setUserId(user.id);

// 登出时
lingcode.telemetry.setUserId(null);

为了分群——套餐档位、语言区域、分组——设置用户属性。它们会与你之前设置的合并,在客户端持久化,并附加到后续事件上:

lingcode.telemetry.setUserProperties({ plan: 'pro', locale: 'en-US', cohort: '2026-Q2' });

捕获错误

在你的全局错误处理器,以及任何值得知道的 catch 块里,使用 recordError。它接受 Error、一个普通的 { message?, stack? } 对象,或一个裸字符串:

// 一个全局处理器
window.addEventListener('error', (e) => {
  lingcode.telemetry.recordError(e.error ?? e.message);
});

// 或在一个 catch 块里
try {
  await doRiskyThing();
} catch (err) {
  lingcode.telemetry.recordError(err);
}

与其它调用不同,recordError立即刷新发送——一次把页面一起带走的崩溃,不该把它自己的报告也一并带走。

测量耗时

trace 记录一次自定义性能测量,单位毫秒——一张图片加载花了多久、一次查询跑了多久、一个屏幕用多久变得可交互:

const start = performance.now();
await loadHeroImage();
lingcode.telemetry.trace('image_load', performance.now() - start);

// 或者传入你已经有的测量值
lingcode.telemetry.trace('image_load', 320);

缓冲与刷新发送如何工作

事件会自动批处理并刷新发送——通常你不必自己调用 flush()。它真正派上用场的两种情形:在一次硬跳转(整页重定向或关闭)之前,你需要保证投递;以及任何你想让缓冲事件立刻发出去的时刻。recordError 本身已经会刷新,所以崩溃报告不会丢。事件参数保持标量且不超过 25 个键,并依靠 setUserProperties 来承载你将用于筛选的分群——套餐档位、语言区域、分组。

离开前刷新发送

flush() 返回一个 promise,让你能在页面离开前等待投递完成:

// 在硬跳转之前保证缓冲事件已发出
await lingcode.telemetry.flush();
window.location.href = '/checkout';

底层原理(REST)

SDK 把批处理后的事件 POST 到你后端的遥测端点。你很少会直接调用它,但这里列出来,供非 JS 客户端和调试使用:

POST https://lingcode.dev/api/cloud/be/<backend-id>/telemetry
Content-Type: application/json

{
  "events": [
    { "name": "checkout_started", "params": { "plan": "pro", "amount": 29 }, "timestamp": 1718064000000 }
  ]
}

一次失败的发送会以 telemetry_failed 的形式呈现。

身份关联需主动开启。在你调用 setUserId 之前,事件都是匿名的。只有当你有依据时——一个已登录的会话以及你应用所要求的任何同意——才附上真实的用户 id,并在登出时用 setUserId(null) 清除它,这样一台共用设备就不会把两个人的分析数据混在一起。