mcpField
O
openfeature

openfeature

github.com/laurigates开发5972 次安装1 天前更新
代码仓库

关于 openfeature

openfeature 是 OpenFeature SDK 集成指南,供需要在应用中实现功能标志的开发者使用。它介绍跨语言的统一 API、提供程序、评估上下文、钩子及测试模式。

主要功能

  1. 01跨提供程序的统一功能标志 API
  2. 02布尔、字符串、数值和对象标志评估
  3. 03评估上下文与钩子
  4. 04Node.js、Python、Go、Java、Rust 集成
  5. 05内存提供程序与单元测试模式

适用场景

  1. 01为应用接入功能标志 SDK
  2. 02实现 A/B 测试或渐进式发布
  3. 03为标志评估配置用户定向上下文
  4. 04使用内存提供程序测试标志逻辑

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/laurigates/claude-plugins --skill openfeature

安装后在 Claude Code 中输入/openfeature确认已加载。

详细介绍

OpenFeature SDK 集成

何时使用此技能

在以下情况使用此技能……在以下情况改用相关技能……
你需要与供应商无关的 OpenFeature SDK API、钩子和评估模式你需要 GO Feature Flag(GOFF)可自托管后端的具体信息——使用 go-feature-flag
你要在不同提供方之间做出选择,或将 OpenFeature 客户端接入应用代码你想从头搭建完整的功能标志技术栈(SDK + 提供方 + CI)——使用 configure-feature-flags
其他技能需要 OpenFeature 语义的权威参考你想在更改任何内容前,检测现有功能标志配置——使用 configure-feature-flags

与供应商无关的功能标志 SDK,提供跨语言和提供方的标准化 API。用于通过任意功能标志后端实现功能标志、A/B 测试、金丝雀发布或渐进式发布。

何时使用

自动激活条件:

  • 用户提到“功能标志”“功能切换”或“功能管理”
  • 用户询问 A/B 测试或金丝雀发布
  • 用户想要实现渐进式发布
  • 项目包含 OpenFeature SDK 依赖项
  • 用户提到 OpenFeature、flagd 或与供应商无关的标志

相关技能:

  • go-feature-flag - GO Feature Flag 提供方的具体信息
  • launchdarkly - LaunchDarkly 提供方集成

核心概念

架构
┌─────────────────────────────────────────────────────────────┐
│                    Application Code                          │
├─────────────────────────────────────────────────────────────┤
│                  OpenFeature SDK (API)                       │
│  ┌─────────────┬──────────────┬─────────────┬─────────────┐ │
│  │  getBool()  │  getString() │  getNumber()│  getObject()│ │
│  └─────────────┴──────────────┴─────────────┴─────────────┘ │
├─────────────────────────────────────────────────────────────┤
│                       Provider                               │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │  GO Feature Flag │ flagd │ LaunchDarkly │ Split │ etc  │ │
│  └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│                    Flag Source                               │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │   File   │   S3   │  GitHub  │  API  │  ConfigMap      │ │
│  └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
关键组件
  1. API - 用于评估标志的标准化接口
  2. 提供方 - 特定后端的实现
  3. 评估上下文 - 用于定向的用户/请求数据
  4. 钩子 - 用于日志记录、遥测的生命周期扩展

SDK 安装

Node.js(服务端)
# Core SDK
npm install @openfeature/server-sdk

# Providers (choose one)
npm install @openfeature/go-feature-flag-provider  # GO Feature Flag
npm install @openfeature/flagd-provider            # flagd
npm install @openfeature/in-memory-provider        # Testing
Node.js(浏览器/React)
# Web SDK
npm install @openfeature/web-sdk

# React integration
npm install @openfeature/react-sdk

# Web providers
npm install @openfeature/go-feature-flag-web-provider
Python
uv add openfeature-sdk
uv add openfeature-provider-go-feature-flag  # GO Feature Flag provider
Go
go get github.com/open-feature/go-sdk
go get github.com/open-feature/go-sdk-contrib/providers/go-feature-flag
Java
<dependency>
    <groupId>dev.openfeature</groupId>
    <artifactId>sdk</artifactId>
    <version>1.7.0</version>
</dependency>
Rust
[dependencies]
open-feature = "0.2"

基本用法模式

初始化
// TypeScript/Node.js
import { OpenFeature } from '@openfeature/server-sdk';
import { GoFeatureFlagProvider } from '@openfeature/go-feature-flag-provider';

// Initialize provider
const provider = new GoFeatureFlagProvider({
  endpoint: process.env.GOFF_RELAY_URL || 'http://localhost:1031',
});

// Set provider (awaitable for ready state)
await OpenFeature.setProviderAndWait(provider);

// Get client
const client = OpenFeature.getClient('my-app');
标志评估
// Boolean flag
const isEnabled = await client.getBooleanValue('new-feature', false);

// String flag
const buttonColor = await client.getStringValue('button-color', '#000000');

// Number flag
const maxItems = await client.getNumberValue('max-items', 10);

// Object/JSON flag
const config = await client.getObjectValue('feature-config', {});

// With evaluation context
const context = { targetingKey: userId, email: userEmail, groups: ['beta'] };
const isEnabled = await client.getBooleanValue('new-feature', false, context);
评估上下文
// Creating context
const context: EvaluationContext = {
  // Required: unique identifier for targeting
  targetingKey: user.id,

  // Optional: additional attributes for targeting rules
  email: user.email,
  groups: user.roles,
  plan: user.subscription,

  // Custom attributes
  country: request.geoip.country,
  browser: request.headers['user-agent'],
};

// Set global context (applies to all evaluations)
OpenFeature.setContext(context);

// Or per-evaluation context
await client.getBooleanValue('feature', false, context);
钩子
import { Hook, HookContext, EvaluationDetails } from '@openfeature/server-sdk';

// Logging hook
const loggingHook: Hook = {
  before: (hookContext: HookContext) => {
    console.log(`Evaluating flag: ${hookContext.flagKey}`);
  },
  after: (hookContext: HookContext, details: EvaluationDetails<unknown>) => {
    console.log(`Flag ${hookContext.flagKey} = ${details.value}`);
  },
  error: (hookContext: HookContext, error: Error) => {
    console.error(`Error evaluating ${hookContext.flagKey}:`, error);
  },
};

// Register globally
OpenFeature.addHooks(loggingHook);

// Or per-client
client.addHooks(loggingHook);
React 集成
import { OpenFeatureProvider, useFlag, useBooleanFlagValue } from '@openfeature/react-sdk';
import { GoFeatureFlagWebProvider } from '@openfeature/go-feature-flag-web-provider';

// Provider setup
const provider = new GoFeatureFlagWebProvider({
  endpoint: import.meta.env.VITE_GOFF_RELAY_URL,
});

function App() {
  return (
    <OpenFeatureProvider provider={provider}>
      <MyComponent />
    </OpenFeatureProvider>
  );
}

// Using flags in components
function MyComponent() {
  // Simple boolean value
  const isEnabled = useBooleanFlagValue('new-feature', false);

  // Full flag details
  const { value, isLoading, error } = useFlag('button-color', '#000');

  if (isLoading) return <Spinner />;

  return (
    <div>
      {isEnabled && <NewFeature />}
      <Button color={value}>Click me</Button>
    </div>
  );
}

测试

内存中提供方
import { OpenFeature } from '@openfeature/server-sdk';
import { InMemoryProvider } from '@openfeature/in-memory-provider';

// Configure test flags
const testProvider = new InMemoryProvider({
  'new-feature': {
    variants: {
      on: true,
      off: false,
    },
    defaultVariant: 'off',
    disabled: false,
  },
  'button-color': {
    variants: {
      blue: '#0066CC',
      green: '#00CC66',
    },
    defaultVariant: 'blue',
    disabled: false,
  },
});

// Use in tests
beforeAll(async () => {
  await OpenFeature.setProviderAndWait(testProvider);
});

afterAll(async () => {
  await OpenFeature.close();
});
单元测试中的模拟
import { vi } from 'vitest';
import { OpenFeature } from '@openfeature/server-sdk';

// Mock the entire SDK
vi.mock('@openfeature/server-sdk', () => ({
  OpenFeature: {
    getClient: vi.fn().mockReturnValue({
      getBooleanValue: vi.fn().mockResolvedValue(true),
      getStringValue: vi.fn().mockResolvedValue('test-value'),
    }),
  },
}));

最佳实践

1. 尽早初始化
// Initialize before app starts handling requests
async function bootstrap() {
  await initializeFeatureFlags();  // First
  await initializeDatabase();
  await startServer();
}
2. 使用有意义的标志名称
// Good: descriptive, namespaced
'checkout.new-payment-flow'
'dashboard.beta-analytics'
'api.rate-limit-v2'

// Bad: vague, unclear
'feature1'
'test-flag'
'enabled'
3. 始终提供默认值
// Good: safe default that works if provider fails
const isEnabled = await client.getBooleanValue('risky-feature', false);

// Consider: what's the safe behavior if flags fail?
const maxItems = await client.getNumberValue('max-items', 100); // Safe limit
4. 处理提供方错误
try {
  const value = await client.getBooleanValue('feature', false);
} catch (error) {
  // Log but don't crash - use default
  logger.error('Feature flag evaluation failed', { error });
  return defaultBehavior();
}
5. 清理旧标志
// Track flag usage with hooks
const flagUsageHook: Hook = {
  after: (context, details) => {
    metrics.increment(`feature_flag.${context.flagKey}.evaluations`);
  },
};

// Regularly review and remove flags with 100% rollout
// or flags that haven't been evaluated in months

文档

相关命令

  • /configure:feature-flags - 设置功能标志基础设施
  • /configure:sentry - 错误跟踪(用于功能标志回滚监控)

评论

支持 Markdown