openfeature について
openfeatureは、アプリケーションにフィーチャーフラグを実装する開発者向けのOpenFeature SDK統合ガイドです。複数言語で共通のAPI、プロバイダー、評価コンテキスト、フック、テスト方法を説明します。
主な機能
- 01ベンダー非依存のフィーチャーフラグAPI
- 02Boolean・文字列・数値・オブジェクトの評価
- 03評価コンテキストとフック
- 04Node.js、Python、Go、Java、Rustへの統合
- 05インメモリプロバイダーとユニットテスト方法
活用シーン
- 01アプリケーションへのフィーチャーフラグSDK導入
- 02A/Bテストや段階的ロールアウトの実装
- 03フラグ評価でのユーザーターゲティング設定
- 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 を使用します |
言語やプロバイダーを問わず、標準化された API を提供する、ベンダーに依存しないフィーチャーフラグ SDK です。フィーチャーフラグ、A/B テスト、カナリアリリース、プログレッシブロールアウトを、任意のフィーチャーフラグバックエンドで実装する際に使用します。
使用する場面
自動的に有効になる条件:
- ユーザーが「feature flags」、「feature toggles」、「feature management」に言及した場合
- ユーザーが 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 │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
主なコンポーネント
- API - フラグ評価の標準化されたインターフェース
- プロバイダー - バックエンド固有の実装
- 評価コンテキスト - ターゲティングに使用するユーザー/リクエストデータ
- フック - ロギングやテレメトリーのためのライフサイクル拡張
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
ドキュメント
- OpenFeature 仕様: https://openfeature.dev/specification
- SDK リファレンス: https://openfeature.dev/docs/reference/concepts/evaluation-api
- プロバイダー一覧: https://openfeature.dev/ecosystem
- フックガイド: https://openfeature.dev/docs/reference/concepts/hooks
関連コマンド
/configure:feature-flags- フィーチャーフラグのインフラストラクチャを設定します/configure:sentry- エラー追跡(フィーチャーフラグのロールバック監視用)
コメント
Markdown 対応