@ epilot/ feature- flags
后端功能旗+epilot Node服务的产品分析. 后霍格被盖下,表面为OpenFeature.
为什么
- 所有电子驾驶服务的共同特性旗界面
- OpenFeature抽象表示,如果我们互换供应商,呼叫站点就不会改变
- 方便Lambda的默认
flushAt: 1, (中文(简体) ),flushInterval: 0,请求超时)
安装
npm install @epilot/feature-flags posthog-node
posthog-node 是同级依赖。 检查 扩展到其他提供者 关于如何推广到其他提供者的更多信息.
需要18号节点.
快开始
import { capture, init, isFeatureEnabled, shutdown } from '@epilot/feature-flags';
export const handler = async (event) => {
await init({
posthog: {
apiKey: process.env.POSTHOG_API_KEY,
host: process.env.POSTHOG_HOST,
},
// env defaults to process.env.STAGE — pass an explicit value only to override
// <provider>: {
// apiKey: process.env.<PROVIDER>_API_KEY,
// host: process.env.<PROVIDER>_HOST,
// },
logger: powertoolsLogger,
});
const ctx = { orgId: event.org, userId: event.user };
if (await isFeatureEnabled('ai-spam-detection', ctx, false)) {
capture({ event: 'spam_check_started', context: ctx, properties: { messageId: event.id } });
// ...
}
await shutdown(); // flush analytics before Lambda freezes
};
init() 可以安全地同时拨打——第一次拨打电线给供应商,随后的拨打共享同样的飞行中的承诺.
API 密码
init(options)
type InitOptions = {
posthog?: {
apiKey: string;
host?: string;
flushAt?: number; // default: 1
flushInterval?: number; // default: 0
requestTimeout?: number; // default: 5000ms
featureFlagsPollingInterval?: number; // default: 30s
personalApiKey?: string;
};
env?: string; // deployment stage — see "Environment scoping" below
logger?: Logger; // any object with debug/info/warn/error
cacheTtlMs?: number; // evaluation cache TTL — default: 60s, 0 disables
bulkOrgEval?: boolean; // isOrgFeatureEnabled resolves via the org map — default: true
};
回返 true 当所配置的提供者注册并准备就绪时, false 如果未提供配置或初始化失败( 在这种情况下, 所有旗下 evals 都会回到默认状态 ) capture() 是一个不开放。 失败的输入可以清除缓存的许诺, 以便下一个呼叫者可以重试 .
旗帜评价
const ctx = { orgId, userId };
await isFeatureEnabled('flag-name', ctx, false); // boolean
await getStringFlag('flag-name', ctx, 'default'); // multivariate variant
await getNumberFlag('flag-name', ctx, 0); // numeric payload
await getObjectFlag('flag-name', ctx, { tier: 'free' }); // object payload
| 打开元件的方法 | 邮电 |
|---|---|
getBooleanValue | isFeatureEnabled |
getStringValue | getFeatureFlag (多变量变体) |
getNumberValue | getFeatureFlagPayload |
getObjectValue | getFeatureFlagPayload |
大批对应人员坐在他们旁边——见 一个圆形的多面旗。 。 。 .
镜像标记
多数 epilot 后端旗帜瞄准 organization 仅分组 :
env 组合属性,或 Org 百分比推出。 对于这些旗帜,用户不能
更改结果, 所以使用 org 范围检查 :
await isOrgFeatureEnabled('o365-outlook-connect', orgId, false);
这事关成本, 不只是人造工程学。 评价缓存按键
(kind, flagKey, orgId, distinctId) 财务报告和审定财务报表 distinctId 嵌入用户——如此传入
{ orgId, userId } 创建一个缓存项(和一个可计费的)
后霍格请求) 每个用户 尽管答案对所有人来说都是一样的
他们。 在高流量的路径上,它将缓存分解到~0%的命中率. 由 Org 键入
单靠一个热容器,每个缓存窗口最多可提出一个请求.
继续使用 isFeatureEnabled 满分 { orgId, userId } 当旗帜有时
人员级别条件或用户推开的百分比.
isOrgFeatureEnabled 解决整个在线地图:每个请求一个答案
org-scoped key for that org, 之后在同一缓存窗口中读取从中出.
Batching是普通人的行为,不是每个呼叫者必须达到的
为. 无法解决的地图是 无答复没有 无启用所以钥匙掉下来了
应自己要求而不是采取 defaultValue - 每一面旗帜都是真的
在其默认适用前进行评审。 过 bulkOrgEval: false 改为 init 改为
总是抓取每个密钥; 这只值得对一个服务读取一个 org 范围
需要较小反应的旗帜.
一个圆形的多面旗
Org-scoped的读取已经共享了一个完整的项目地图,所以一个扇出 isOrgFeatureEnabled
电话不要求每个电话。 当呼叫者想要地图时 联系这两个人
本身——已知的密钥集,或每个旗帜:
// Known keys — always a full map, never null:
const flags = await areOrgFeaturesEnabled(['portals-engagement-center', 'portals-mcp'], orgId);
if (flags['portals-mcp']) { /* ... */ }
// Or the whole project's flags, when the set isn't known up front:
const all = await getOrgFeatureFlags(orgId);
if (all?.['portals-engagement-center']) { /* ... */ }
两个都花费了一个请求。 偏爱 areOrgFeaturesEnabled: 它充满 defaultValue 用于任何旗帜
无法解决的项目,所以没有 null 守卫 使用
getOrgFeatureFlags 当呼叫者需要每一面旗帜, 或者需要告诉 未解决 除
已禁用 (登入,说.
两种份额 一个 缓存条目 per org —— 全项目映射. 缩小请求范围
请求的密钥会按请求的一组键键取缓存,将它分解到每个呼叫站点并计算成本 a
请求每个。 因为他们分享它, 任何后期的角镜 isOrgFeatureEnabled 在同一个进程中
免费读取该条目的答案,包括在不相关请求路径上的旗帜.
霍格邮局收费 /flags 电话和
项目中活动旗帜的数量不影响每项请求的成本, (中文(简体) ),
这就是为什么一个地图比N键便宜 和为什么Org-scoped getter把它。 (本节)
当地评价的定义民意测验(一个终点)适用10项要求的逐名乘数
此软件包不使用。 ) 大通电话的确要花费更多的响应大小和缓存
内存,因为一个条目持有每个项目旗而不是一个布尔.
回返 null 当没有PostHog供应商注册或请求无法使用时
映射 – 然后应用您自己的每面旗默认值, 并注意一个密钥从一个
无null 地图是工程没有的旗帜 。 多变量旗帜倒塌到
true 当变量匹配; 读取变量和有效载荷 getStringFlag 编号 :
getObjectFlag。 。 。 .
分析
capture({
event: 'message_sent',
context: { orgId, userId },
properties: { channel: 'email', size: 1024 },
});
await shutdown(); // flushes pending events
capture() 通过 OpenFeature 的路由 track() 和活动的提供者,所以在没有提供者配置时,它是不开放的.
直接 OpenFeature 客户端
import { getFeatureFlagsClient } from '@epilot/feature-flags';
const client = getFeatureFlagsClient();
const details = await client.getBooleanDetails('flag', false, { targetingKey: 'org_user' });
logger.debug(details.reason); // 'TARGETING_MATCH' | 'DEFAULT' | 'ERROR' | ...
背景形状
type EpilotFlagContext = {
orgId?: string;
userId?: string;
};
翻译为:
distinctId = ${orgId}_${userId}groups = { organization: orgId }用于 org 升起旗帜
您也可以通过一个原始的 OpenFeature EvaluationContext 直接进行控制.
环境范围界定
软件包读取 process.env.STAGE 自动发送 groupProperties: { organization: { env } } 在每一旗的评价。 每一个电子驾驶Lambda服务 STAGE 设置,所以你不需要通过手动连接.
这符合现有的 epilot PostHog 旗使用的常规——多个放出组,每个放出组由 env 组属性——因此向dev推出的旗帜不会意外地与prod相匹配,反之亦然.
// default behavior — STAGE picked up from env
await init({ posthog: { ... } });
// override only when you need to (e.g. tests, multi-tenant service)
await init({ posthog: { ... }, env: 'preview-42' });
capture() 事件得到 env 也作为常规事件财产.
评价缓存
每一个未标记的旗帜评价都是可收费的 PostHog 请求——postHog-node 没有自己的结果缓存(没有) personalApiKey 每个电话都是网络 /decide编号 :/flags 请求,而其唯一的内部缓存 $feature_flag_called 分析事件,而不是请求). 因此,供应商对每个评价结果进行缓存 (kind, flagKey, orgId, distinctId) 默认为60个,以每个进程1,000个条目为限.
- 缓存漏掉的费用恰恰是本来会提出的一个请求;冷的容器从未比没有缓存更糟糕.
- 在TTL内用热容器传播旗帜变化;冷容器立即看到它们.
- 失败的评价缓存了 TTL 的倒置默认值, 当 PostHog 无法到达时, TTL 作为后压值加倍 .
- 通过电路或禁用
init({ cacheTtlMs })(单位:千美元)0/ 禁用). - 散装分辨率在每条条目下缓存整个地图
(orgId, distinctId),而当同一上下文被缓存时,单旗布尔检查会读取该条目。 块状扫描结果从不回答人状扫描:块状键嵌入相同的distinctId上下文改变。 地图所持有的密钥不归结于请求,而不是解决false与每个旗手不同 没有 缓存失败, 因为一个缓存失败会让 TTL 的默认标记 .
包裹从不调用 posthog.groupIdentify()。旗帜瞄准仅需要 groups + 键 groupProperties 每一个容器都是新鲜的,所以用容器来识别体积表 $groupidentify 活动)。 坚持下去 env 在 org 组配置文件上——所以 org 可以通过 env 在PostHog UI中——被处理出带外(例如一次性回填脚本或在org创建时间),而不是从请求路径.
若为 process.env.STAGE 没有设定,也没有明确 env 通过, 包跳过 groupProperties 完全没有.
地方发展
npm install
npm run lint # tsc --noEmit
npm test # vitest
npm run build # emit dist/
释放
标记承诺 :
npm version patch # or minor / major
git push --follow-tags
CI 在任何标签匹配上发布到 npm v*。 。 。 .
扩展到其他提供者
要将这个软件包扩展至与其他提供者合作,您可以创建一个自定义提供者,执行OpenFeature提供者接口. 提供者应能够处理国旗评价和分析捕获.
所以,如果你最后使用一个特定于你的使用大小写 PostHog 的内存或内部FF 替代品,这个软件包只是给你一个接口来配合它. 你唯一要做的就是执行提供者接口,然后传给 init 函数.