@ controlvar/js-sdk (英语)
贝塔. 这是 0.x 发布: 锁定您测试的精确版本 .
Controlvar公共API的JavaScript/TypeScript客户端. 18号节点和浏览器,
零运行时间依赖关系(全球) fetch),"共同JS"以类型声明来构建.
旗帜评估和实验任务 由服务器决定 默认; 结果为
内存中每个用户+密钥被缓存. 服务器侧码可以选择使用 当地评价
(单位:千美元)evaluation: 'local',β:旗从服务器的规则中按程序回答,并带有
服务器的答案,任何无法解答的都完全转到服务器。 见
docs/sdk/local-evaluation.md。 。 。 .
完整文档: docs/sdk/javascript.md。 。 。 .
安装
如果安装 @getexperimently/js-sdk,此软件包在工程改名前的名称,解开并安装 @controlvar/js-sdk。 。 。 .
这个 @controlvar/js-sdk 软件包已打开 无0.3.0是一个
β释放.
npm install @controlvar/[email protected]
欲研究SDK本身,见下文Development.
本版本的更改
getStringValue, (中文(简体) ),getNumberValue财务报告和审定财务报表getJsonValue新的: 他们读取了字符串的值, 数字或Json旗服务。 无法返回时, 每人返回默认值, 并传递原因到onError(err, 'value')。见 旗帜值。 。 。 .FlagEvaluation收益value财务报告和审定财务报表valueType。 。 。 .onExposure是新: 当创建客户端时, 您会给客户端一个函数, 它每次调用一次 时间:服务器在实验中输入一个用户,而答案并非来自其缓存。 见 下出出相钩.SwallowedOperation,类型onError第二次辩论有两个新成员:'value',用于 返回默认值的键入计数器,以及'exposure',用于在onExposure。 。 。 .ExperimentationErrorCode类型ExperimentationError是因为code,有两个新成员:'TYPE_MISMATCH',对于一个旗帜服务 另一种类型比读取器'HOOK_ERROR', (中文(简体) ), 失败的onExposure。可以详尽地检查任一类型,例如switch谁default指定值为never,停止编译,直到它处理全部四个 新成员:'value', (中文(简体) ),'exposure', (中文(简体) ),'TYPE_MISMATCH'财务报告和审定财务报表'HOOK_ERROR'。 。 。 .eventId新开的track()财务报告和审定财务报表trackBatch()。见下文事件编号.- 本地评价也回答字符串,数字或json旗的值. SDK 无法使用旗下条目
改为(a)
evaluation或者说value_type它不知道,或者一个错误类型的值)只发送 标记到服务器, 其余的规则仍然在本地响应; 在此之前 版本 aevaluation它不知道拒绝整个规则, 客户端继续回答 从它的上一个. - 一旦当地评价停止回答国旗(
maxStaleMs规则被抛弃,close()),它在当地回答的用户呼叫到服务器;在此版本之前 用户从缓存中保存本地答案最多cacheTtlMs。 。 。 . - A 类
cacheTtlMs联 合 国0缓存什么。 在这个版本之前,一个答案在同一版本内被重用 毫秒,每个缓存的答案都活了一毫秒cacheTtlMs。 。 。 . - 有限度
cacheTtlMs24小时以上atrack()没有键仍然到达实验 或旗子,其答案仍然被缓存;在此版本之前,它只到达在 最后24小时. - 请求错误消息将方法和路径命名为没有查询字符串,该字符串带有 用户 id 和用户的属性; 在此版本之前, 有的将完整 URL 命名 .
事件编号
track() 财务报告和审定财务报表 trackBatch() 拿着 eventId编号 event_id。服务器存储发送的事件
同样的 event_id,用户,实验,旗帜和事件名称仅使用一次. 它需要一个
包含 Controlvar 服务器 event_id 更改( # 1640, 之后的第一个平台发布)
合并:一个更老的服务器忽略了字段.
- SDK没有身份证明:
eventId没有人被派遣,再被派遣 再来一次 做一次ID, 当事件发生, 并给同样的一个 每次发送它. undefined, (中文(简体) ),null财务报告和审定财务报表''无。 服务器拒绝超过 255 个字符的ID 或 一个持有 NUL 的422SDK不检查它.- 一次活动吸引了几个实验和旗帜 在每个条目中都带有同样的标识。 A 类
429重审后发送同样的ID。 SDK不会再次发出取消时间的请求.
快开始
import { ExperimentationClient } from '@controlvar/js-sdk';
const client = new ExperimentationClient({ apiUrl: 'http://localhost:8000', apiKey: 'eptk_...' });
const user = { userId: 'user-123', attributes: { plan: 'pro' } };
const assignment = await client.getAssignment('checkout_flow', user); // { experimentKey, userId, variantId, variantName, isControl, configuration, assigned?, reason? }
const variant = await client.getVariant('checkout_flow', user); // variantName, 'control' on failure
const { enabled, config, reason } = await client.evaluateFlag('new_search', user); // attributes sent as ?context=
const on = await client.isFeatureEnabled('new_search', user); // false on failure
await client.track('user-123', 'purchase', { value: 49.99, experimentKey: 'checkout_flow' });
await client.track('user-123', 'page_view'); // no key → every experiment + flag answered for this user
A 类 track 在每一个实验中都没有按键,并标出客户端为用户在
最后24小时, 缓存与否, 但实验是草稿、 暂停、 完成或存档.
没有,它就被发送一次,没有钥匙,并被保存为历史。 密钥存在于此客户端的记忆中
(最多10 000个用户) clearCache() 留着吧 在服务器上,通过 experimentKey 打开
转换.
API 密码
| 方法 | 回返 | 失败时 |
|---|---|---|
getAssignment(experimentKey, user) | Promise<Assignment> | 拒绝方式 ExperimentationError (单位:千美元)code, (中文(简体) ), status, (中文(简体) ), body(中文(简体) ) |
getVariant(experimentKey, user) | Promise<string> | defaultVariant (单位:千美元)'control'(中文(简体) ) |
evaluateFlag(flagKey, user) | Promise<FlagEvaluation> —— 说 { key, enabled, config, reason?, value?, valueType? } | 拒绝方式 ExperimentationError |
isFeatureEnabled(flagKey, user) | Promise<boolean> | false |
getStringValue(flagKey, user, defaultValue) | Promise<string>,字符串旗的字符串服务于此用户 | defaultValue绝不拒绝; onError(err, 'value') |
getNumberValue(flagKey, user, defaultValue) | Promise<number>,数字标记的数字服务于此用户 | defaultValue绝不拒绝; onError(err, 'value') |
getJsonValue(flagKey, user, defaultValue) | Promise<T>,用于此用户的新对象或阵列副本 | defaultValue绝不拒绝; onError(err, 'value') |
getAllFlags(userId, attributes?) | Promise<Record<string, boolean>> (没有缓存) | 拒绝 |
track(userId, eventName, { value?, properties?, experimentKey?, featureFlagKey?, eventType?, timestamp?, eventId? }) | Promise<void> | 绝不拒绝; onError |
trackBatch(events) | Promise<{ successCount, failureCount, errors }> (满分100分) | 从不拒绝 |
reportError({ errorType, message, featureFlagKey?, experimentKey?, userId?, stackTrace?, metadata?, timestamp? }) | Promise<boolean>数字 : true 当服务器存储报告时( 201) | false绝不拒绝; onError |
fetchAssignments(userId, { activeOnly? }) | Promise<AssignmentRecord[]> 从服务器 | 拒绝 |
getAssignments(userId), (中文(简体) ), getEvaluatedFlags(userId), (中文(简体) ), clearCache() | 模拟缓存访问 | —— 说 |
getCachedFlags(userId) | FlagEvaluation[]: 缓存、 未过期的用户评价; 在本地模式下, 每个带 source (单位:千美元)'local' 或者说 'server'(中文(简体) ) | —— 说 |
ready({ timeoutMs? }), (中文(简体) ), status(), (中文(简体) ), close() | 本地模式: 准备状态、 规则设置状态、 关闭( 发送评价计数) | 从不拒绝 |
consistentHash(userId, flagKey), (中文(简体) ), md5Hex(s), (中文(简体) ), md5Bytes(s) | 兼容散列工具( 不是旗下打桶功能) | —— 说 |
配置 : apiUrl, (中文(简体) ), apiKey (所需); timeoutMs (5000个), cacheTtlMs (30万; 计; 0 缓存什么,
defaultVariant (单位:千美元)'control', (中文(简体) ), fetch, (中文(简体) ), onError(err, 'track' | 'trackBatch' | 'refresh' | 'flush' | 'evaluate' | 'reportError' | 'value' | 'exposure'), (中文(简体) ),
onExposure(exposure) (见接触钩), evaluation (单位:千美元)'server' 或者说 'local', (中文(简体) ), refreshIntervalMs (30 000美元,最低5 000美元), maxStaleMs。 。 。 .
失败永远不会被缓存; 同时调用同一个用户 + 密钥共享一个请求; a 429 是
之后再试一次 Retry-After。 。 。 .
user.attributes 以 context 派任时 财务报告和审定财务报表 国旗评价
(单位:千美元)&context=<url-encoded JSON>,在空出时省略),所以旗下目标设定规则与之相对评价
(单位:千美元)country 也匹配 user.country; 嵌入对象平整为点键, 如 app.version) (中文(简体) ).
Caches 仅由 user + 密钥键入- call clearCache() 修改用户属性后.
reportError 决定 true 当服务器存储报告时。 存储的报告数到
旗下错误率和自动回滚 仅当客户端的密钥有 sdk:ruleset 范围和范围
由用户创建,用户可以更改特征标记;旗帜的安全检查显示其他人是
uncounted_error_count。 。 。 .
招生情况: assigned 财务报告和审定财务报表 reason
一个 Assignment 还携带 assigned 财务报告和审定财务报表 reason。 。 。 . assigned: false 表示服务器没有
注册用户( e)reason 实值 'holdout', (中文(简体) ), 'mutual_exclusion' 或者说 'targeting')并返回
控制变体,这样你就能实现默认体验;没有记录曝光. 导出时
与仓库接触,不包括与 assigned: false:用户没有注册,
财务报告和审定财务报表 reason 说为什么 在字段之前的服务器不会发送, 所以 assigned 实值
undefined (从来没有) false) (中文(简体) ). 特意决定如何对待这些行而不是放下
带有 assigned === true 过滤器.
一个不是ACTIVE的实验 以控制变体回答每个用户, assigned: false 财务报告和审定财务报表
reason 达到其地位'draft', (中文(简体) ), 'paused', (中文(简体) ), 'completed' 或者说 'archived') (中文(简体) ).
曝光钩
onExposure 是您创建客户端时给客户端的函数。 客户每人打一次电话
时间:服务器将用户录入实验,而答案并非来自客户端
缓存:服务器记录曝光的那一刻. 用它来传送曝光到你的分析
工具或仓库.
const client = new ExperimentationClient({
apiUrl: 'http://localhost:8000',
apiKey: process.env.CONTROLVAR_API_KEY!,
onExposure: (exposure) => {
// your analytics tool's call goes here
console.log('exposure', exposure.experimentKey, exposure.variantName, exposure.userId);
},
onError: (error, operation) => {
if (operation === 'exposure') console.warn('onExposure failed', error.cause);
},
});
它收到一个 Exposure数字 : experimentKey, (中文(简体) ), userId, (中文(简体) ), variantId (单位:千美元)null 当服务器发送时
(无)和 variantName。它不要求缓存的答案, 实验没有注册的用户
或未运行的实验(assigned: false),一个失败的呼叫,或者一个特征旗. 若为
它扔出,或者返回一个承诺,拒绝,答案是不变的,错误将发生
onError 操作 'exposure' 财务报告和审定财务报表 code 'HOOK_ERROR'。 。 。 .
详细情况 : 曝光钩。 。 。 .
使用的后端端点
每个请求都携带 X-API-Key, (中文(简体) ), Content-Type: application/json, (中文(简体) ), Accept: application/json。 。 。 .
| SDK电话 | 方法和路径 | 200个答复 |
|---|---|---|
getAssignment, (中文(简体) ), getVariant | POST /api/v1/tracking/assign {experiment_key, user_id, context?} | {experiment_key, user_id, variant_id, variant_name, is_control, configuration, assigned, reason} |
evaluateFlag, (中文(简体) ), isFeatureEnabled | GET /api/v1/feature-flags/evaluate/{flag_key}?user_id=…&context=<url-encoded JSON> | {key, enabled, config, reason} |
getAllFlags | GET /api/v1/feature-flags/user/{user_id}?context=<url-encoded JSON> | {"<flag_key>": bool} |
track 有密钥 | POST /api/v1/tracking/track | 忽略 |
track 无密钥 | POST /api/v1/tracking/batch {events: [...]} (≤100),每个实验一个条目并标出它到达的旗帜;没有, POST /api/v1/tracking/track 无密钥 | 忽略 |
trackBatch | POST /api/v1/tracking/batch {events: [...]} (≤100) | {success_count, failure_count, errors} |
fetchAssignments | GET /api/v1/tracking/assignments/{user_id}?active_only=true | 列列表 |
出错:401个坏键,404个未知的实验或旗下键,或无控制变体(从未被缓存)的草稿实验,422个无效事件,429个速率有限.
非 ACTIVE 的旗帜不是错误: 它回答 enabled: false, (中文(简体) ), reason: "inactive"。 。 。 .
合同烟
cd sdk/js && npm run build --silent && node examples/contract_smoke.mjs
信封 : CONTROLVAR_API_URL (默认) http://localhost:8000, (中文(简体) ), CONTROLVAR_API_KEY (必须),
CONTRACT_EXPERIMENT_KEY (单位:千美元)sdk_contract_ab, (中文(简体) ), CONTRACT_FLAG_KEY (单位:千美元)sdk_contract_flag, (中文(简体) ), CONTRACT_USER_ID。 。 。 .
CI负责SDK的合约烟雾 与真正的API: js 位于 sdks: 清单
SDK 现场合同工作 pr-qa-gate.yml (英语)。 。 。 .
发展
从 sdk/js 在克隆中 此寄存器数字 :
npm install
npm test
npm run build
npm test: Jest测试(嘲弄;当地评价员对照测试/sdk-contract/Rulesset-vectors.json)npm run build: tsc → det/ (CommonJS +.d.ts) (中文(简体) )