Feature Flag 与 A/B Test

Feature Flag 与 A/B Test

当前 Browser 0.7.0 和 Go 0.6.0 支持 typed Feature Flag 决策与实验曝光。Android、iOS 和小程序暂不支持该能力。

使用前,组织需要同时开通 analyticsab_testing,并在目标环境存在已发布的 Flag Release 或运行中的实验部署。

决策不等于曝光

正确流程是:

  1. 请求 Flag 决策,并始终提供类型正确的 fallback。
  2. 判断业务是否真正采用该值。
  3. 只有值被实际呈现或执行后才发送曝光。
  4. 只有曝光返回 recordedduplicate 时采用实验值;失败时继续使用 fallback。

提前曝光、对未展示的候选值曝光或重复改变主体身份都会污染实验结果。

Browser

快捷方式适用于“得到值后立即使用”的场景:

import { decideAndExpose } from '@entmesh/browser-sdk'

const [decision] = await decideAndExpose([
  { key: 'checkout_copy', fallback: '继续' },
])

renderCheckoutButton(decision.value)

需要延迟应用时,拆分决策和曝光:

import { decide, expose } from '@entmesh/browser-sdk'

const decision = await decide('checkout_copy', '继续')

if (checkoutButtonWillRender) {
  const [result] = await expose([decision])
  const value = result.status === 'recorded' || result.status === 'duplicate'
    ? decision.value
    : '继续'
  renderCheckoutButton(value)
}

成功曝光后,同一 session 的后续 Browser 事件会在 context.experiments 中携带最多 8 个 assignment。reset() 会清除当前 assignment。

Go

requests := []entmesh.FlagRequest{{
    Key:      "checkout_copy",
    Fallback: json.RawMessage(`"继续"`),
}}

decisions, err := client.DecideAndExpose(
    ctx,
    entmesh.ExperimentSubject{UserID: "user-42"},
    requests,
)
if err != nil {
    // decisions 已回退到调用方提供的值。
}

如果决策先于实际展示,使用 DecideFlags,在真正应用后调用 ExposeDecisions。Go 的共享 Client 不保存某个用户的 assignment;需要归因后续事件时显式调用:

event := entmesh.WithExperimentContext(entmesh.Event{
    EventName: "checkout_completed",
    UserID:    "user-42",
}, decisions)

主体与 fallback

  • Flag key 使用小写字母开头,只包含小写字母、数字和下划线,最多 64 个字符。
  • 单次最多请求 20 个不重复的 Flag。
  • Browser 自动携带当前 anonymous/user/session 和可用设备证据。
  • Go 必须在 ExperimentSubject 中显式传入 User、Anonymous、Session 或 IdentityContext
  • Go fallback 必须是最大 4 KiB 的合法 JSON;Browser fallback 的类型应与 Flag 类型一致。

常见 fallback 原因包括未初始化、未同意、未命中流量、未满足 Targeting、运行时不可用、网络错误或曝光失败。业务代码必须保证 fallback 能独立、安全地运行。