曝光上报
曝光是一条记录,表明某个 unit_id 实际上接触到了某个实验分组。统计引擎读取的是曝光,不是 分组结果 —— 如果只分组而不上报曝光,这个 unit_id 不会进入实验结果。
本页介绍 SDK 提供的两种上报模式、如何挑选,以及常见的稀释陷阱。
下文 Go 与 HTTP 部分代表今天已正式可用的接入方式。Android、iOS、JavaScript、C++ 部分是 形态预览,这些 SDK 在
Settings → SDK&Key下都是Coming soon。
两种模式
| 模式 | 行为 | 何时用 |
|---|---|---|
| 自动(默认) | 在 getExperiment / getFeatureFlag 返回分组时自动上报一条曝光。 | 调用点就是真正执行实验逻辑的地方。 |
| 手动 | SDK 返回分组但不上报,由你后续调用 LogExperimentExposure。 | 调用点远早于变体真正生效(批处理、扇出 API、启动期"暖缓存"等)。 |
手动模式是用来防止曝光稀释的:平台记下了"这个 unit_id 看到了 treatment",但用户可见的 代码路径其实没跑(实验看上去更大、效果更被摊薄)。
如何切换
可在两个粒度切换:
- 全局,初始化时:JavaScript 用
enableAutomaticExposure: false、Go 用WithDisableReport(true)、Android 用autoReport(false); - 逐次,部分 SDK 支持调用级开关:JavaScript 的
getExperiment(layer, autoLog)第二个参数、 Go 的WithAutomatic(false)等。
调用级开关优先级高于全局默认。
手动上报 API
go
// Go
exp, _ := userCtx.GetExperiment(ctx, "6666", "abc_layer_name", abc.WithAutomatic(false))
// ... 让变体真正生效 ...
abc.LogExperimentExposure(ctx, "6666", exp)cpp
// C++
auto exp = abc_cpp_sdk::AbcService::GetInstance()
->GetExperiment("6666", "abc_layer_name", abc_cpp_sdk::WithSetUnitID(uid));
exp.LogExposure();java
// Android
AbcExpInfo info = mAbcExperiment.getExperiment("abc_layer_name");
boolean ok = mAbcExperiment.LogExperimentExposure(info);objective-c
// iOS
[abcSdk logExperimentExposure:expInfo];javascript
// JavaScript
const exp = abc.getExperiment("abc_layer_name", false);
abc.logExperimentExposure(exp);服务端 SDK 的发送
服务端 SDK 在本地累计曝光,周期性刷到消息队列。默认节奏对绝大多数业务足够,无需在热路径 手动 flush。优雅退出时调用 Release(Go),SDK 会在进程结束前把缓冲清空。
客户端 SDK 的发送
客户端 SDK 按定时或缓冲水位批量上报。网络失败时事件留在内存中等待下次重试;App 退出时若 OS 直接结束进程,可能少量事件丢失 —— 平台侧请按"至少一次"语义设计。
常见误区
GetExperiments(批量)开启自动上报:批量接口一次返回所有层的分组,开了自动上报就是 每层一条曝光,对那些变体未真正展示给用户的层造成稀释。请用WithAutomatic(false)(Go)或WithSetDisableReport(true)(C++),按需手动上报。- 在后台暖缓存路径上报曝光:服务为"性能"在启动时预拉分组,会在用户什么都还没做之前就给 每个
unit_id上报一条曝光。暖缓存路径请用手动模式。 - 完全不上报以"保持结果干净":会出现样本比例失衡 —— 平台见到了分组却看不到曝光。 变体真的运行时一定要上报。