Skip to content

曝光上报

曝光是一条记录,表明某个 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 上报一条曝光。暖缓存路径请用手动模式。
  • 完全不上报以"保持结果干净":会出现样本比例失衡 —— 平台见到了分组却看不到曝光。 变体真的运行时一定要上报。