-
Notifications
You must be signed in to change notification settings - Fork 59
feat(go-feature-flag)!: Introduce in-process evaluation + tracking #1365
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
thomaspoignant
wants to merge
31
commits into
main
Choose a base branch
from
feat-goff-inprocess
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 27 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
31b9a72
feat(go-feature-flag)!: Introduce in-process evaluation + tracking
thomaspoignant 5e76cfd
copy wasm file during build
thomaspoignant 0add4ff
add dependency
thomaspoignant e18384e
Merge branch 'main' into feat-goff-inprocess
thomaspoignant 248696d
Remove unused dependency
thomaspoignant 3cc2b65
fix linter
thomaspoignant 2e37b05
adding mock for config
thomaspoignant 2bbc06e
set default flush interval to 2 minutes
thomaspoignant c5ef0d1
Add script to copy wasm file
thomaspoignant e1f3d43
fixing linter
thomaspoignant 9b70a3d
rework readme
thomaspoignant 00533ed
simplify addEvent
thomaspoignant d799bdf
use integer Unix timestamps
thomaspoignant 20445fb
Merge branch 'main' into feat-goff-inprocess
thomaspoignant 94c9a10
defer initialization of the wasm module
thomaspoignant 96f0404
use setTimeout instead of setInterval
thomaspoignant a0b021f
(event publisher) use setTimeout instead of setInterval
thomaspoignant 62af020
change advanced time
thomaspoignant 8725b7c
check only the collector endpoint
thomaspoignant 172cf4e
test debug CI
thomaspoignant cdde2b2
check only the collector endpoint
thomaspoignant 7a07942
try to specify mock
thomaspoignant 27c926e
Change timing for tests
thomaspoignant 13a3836
log when error during initialization
thomaspoignant ae986e7
Change the return of configuration
thomaspoignant 291bd84
Change mock
thomaspoignant 9b990d9
Fix date
thomaspoignant 53aab0f
remove wasmer because it is not used
thomaspoignant b18832b
rollback package-lock
thomaspoignant 577f290
remove console.log
thomaspoignant 312fc00
fix warning
thomaspoignant File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,215 @@ | ||
# Server-side Go Feature Flag Provider | ||
# Server-side GO Feature Flag Provider | ||
|
||
This provider is an implementation for [`go-feature-flag`](https://github.com/thomaspoignant/go-feature-flag) a simple and complete | ||
feature flag solution, without any complex backend system to install, all you need is a file as your backend. | ||
A feature flag provider for [OpenFeature](https://openfeature.dev/) that integrates with [go-feature-flag](https://github.com/thomaspoignant/go-feature-flag), a simple and complete feature flag solution. | ||
|
||
It uses [`go-feature-flag-relay-proxy`](https://github.com/thomaspoignant/go-feature-flag-relay-proxy) which expose the capabilities of the SDK through an API layer. | ||
This provider supports both **in-process** and **remote** evaluation modes, offering flexibility for different deployment scenarios. | ||
|
||
## Installation | ||
## Features 🚀 | ||
|
||
- **Dual Evaluation Modes**: In-process evaluation for performance and remote evaluation for centralized control | ||
- **Real-time Configuration Updates**: Automatic polling for flag configuration changes | ||
- **Comprehensive Data Collection**: Built-in event tracking and analytics | ||
- **Flexible Context Support**: Rich evaluation context with targeting rules | ||
- **Caching**: Intelligent caching with automatic cache invalidation | ||
- **Error Handling**: Robust error handling with fallback mechanisms | ||
- **TypeScript Support**: Full TypeScript support with type safety | ||
- **OpenFeature Compliance**: Full compliance with OpenFeature specification | ||
|
||
## Installation 📦 | ||
|
||
```bash | ||
npm install @openfeature/go-feature-flag-provider | ||
``` | ||
|
||
### Peer Dependencies | ||
|
||
```bash | ||
npm install @openfeature/server-sdk | ||
``` | ||
|
||
## Quick Start 🏃♂️ | ||
|
||
### Basic Setup | ||
|
||
```typescript | ||
import { OpenFeature } from '@openfeature/server-sdk'; | ||
import { GoFeatureFlagProvider, EvaluationType } from '@openfeature/go-feature-flag-provider'; | ||
|
||
// Initialize the provider | ||
const provider = new GoFeatureFlagProvider({ | ||
endpoint: 'https://your-relay-proxy.com', | ||
evaluationType: EvaluationType.Remote, | ||
}); | ||
|
||
// Register the provider | ||
OpenFeature.setProvider(provider); | ||
|
||
// Get a client | ||
const client = OpenFeature.getClient(); | ||
|
||
// Evaluate a flag | ||
const flagValue = await client.getBooleanValue('my-feature-flag', false, { | ||
targetingKey: 'user-123', | ||
email: '[email protected]', | ||
}); | ||
``` | ||
|
||
### In-Process Evaluation | ||
|
||
For high-performance scenarios where you want to evaluate flags locally: | ||
|
||
```typescript | ||
import { GoFeatureFlagProvider, EvaluationType } from '@openfeature/go-feature-flag-provider'; | ||
|
||
const provider = new GoFeatureFlagProvider({ | ||
endpoint: 'https://your-relay-proxy.com', | ||
evaluationType: EvaluationType.InProcess, | ||
flagChangePollingIntervalMs: 30000, // Poll every 30 seconds | ||
}); | ||
``` | ||
|
||
## Configuration Options ⚙️ | ||
|
||
### Provider Options | ||
|
||
| Option | Type | Default | Description | | ||
| ----------------------------- | ------------------ | ------------ | ----------------------------------------------- | | ||
| `endpoint` | `string` | **Required** | The endpoint of the GO Feature Flag relay-proxy | | ||
| `evaluationType` | `EvaluationType` | `InProcess` | Evaluation mode: `InProcess` or `Remote` | | ||
| `timeout` | `number` | `10000` | HTTP request timeout in milliseconds | | ||
| `flagChangePollingIntervalMs` | `number` | `120000` | Polling interval for configuration changes | | ||
| `dataFlushInterval` | `number` | `120000` | Data collection flush interval | | ||
| `maxPendingEvents` | `number` | `10000` | Maximum pending events before flushing | | ||
| `disableDataCollection` | `boolean` | `false` | Disable data collection entirely | | ||
| `apiKey` | `string` | `undefined` | API key for authentication | | ||
| `exporterMetadata` | `ExporterMetadata` | `undefined` | Custom metadata for events | | ||
| `fetchImplementation` | `FetchAPI` | `undefined` | Custom fetch implementation | | ||
|
||
### Evaluation Types | ||
|
||
#### InProcess Evaluation | ||
|
||
- **Performance**: Fastest evaluation with local caching | ||
- **Network**: Minimal network calls, only for configuration updates and tracking | ||
- **Use Case**: High-performance applications, real-time evaluation | ||
|
||
#### Remote Evaluation | ||
|
||
- **Performance**: Network-dependent evaluation | ||
- **Network**: Each evaluation requires a network call, works well with side-cars or in the edge | ||
- **Use Case**: Centralized control | ||
|
||
## Advanced Usage 🔧 | ||
|
||
### Custom Context and Targeting | ||
|
||
```typescript | ||
const context = { | ||
targetingKey: 'user-123', | ||
email: '[email protected]', | ||
firstname: 'John', | ||
lastname: 'Doe', | ||
anonymous: false, | ||
professional: true, | ||
rate: 3.14, | ||
age: 30, | ||
company_info: { | ||
name: 'my_company', | ||
size: 120, | ||
}, | ||
labels: ['pro', 'beta'], | ||
}; | ||
|
||
const flagValue = await client.getBooleanValue('my-feature-flag', false, context); | ||
``` | ||
|
||
### Data Collection and Analytics | ||
|
||
The provider automatically collects evaluation data. You can customize this behavior: | ||
|
||
```typescript | ||
const provider = new GoFeatureFlagProvider({ | ||
endpoint: 'https://your-relay-proxy.com', | ||
evaluationType: EvaluationType.Remote, | ||
disableDataCollection: false, // Enable data collection | ||
dataFlushInterval: 20000, // Flush every 20 seconds | ||
maxPendingEvents: 5000, // Max 5000 pending events | ||
}); | ||
``` | ||
|
||
### Custom Exporter Metadata | ||
|
||
Add custom metadata to your evaluation events: | ||
|
||
```typescript | ||
import { ExporterMetadata } from '@openfeature/go-feature-flag-provider'; | ||
|
||
const metadata = new ExporterMetadata() | ||
.add('environment', 'production') | ||
.add('version', '1.0.0') | ||
.add('region', 'us-east-1'); | ||
|
||
const provider = new GoFeatureFlagProvider({ | ||
endpoint: 'https://your-relay-proxy.com', | ||
evaluationType: EvaluationType.Remote, | ||
exporterMetadata: metadata, | ||
}); | ||
``` | ||
|
||
## Flag Types Supported 🎯 | ||
|
||
The provider supports all OpenFeature flag types: | ||
|
||
### Boolean Flags | ||
|
||
```typescript | ||
const isEnabled = await client.getBooleanValue('feature-flag', false, context); | ||
const details = await client.getBooleanDetails('feature-flag', false, context); | ||
``` | ||
$ npm install @openfeature/go-feature-flag-provider | ||
|
||
### String Flags | ||
|
||
```typescript | ||
const message = await client.getStringValue('welcome-message', 'Hello!', context); | ||
const details = await client.getStringDetails('welcome-message', 'Hello!', context); | ||
``` | ||
|
||
Required peer dependencies | ||
### Number Flags | ||
|
||
```typescript | ||
const percentage = await client.getNumberValue('discount-percentage', 0, context); | ||
const details = await client.getNumberDetails('discount-percentage', 0, context); | ||
``` | ||
$ npm install @openfeature/server-sdk | ||
|
||
### Object Flags | ||
|
||
```typescript | ||
const config = await client.getObjectValue('user-config', {}, context); | ||
const details = await client.getObjectDetails('user-config', {}, context); | ||
``` | ||
|
||
## Tracking Events 📊 | ||
|
||
The provider supports custom event tracking: | ||
|
||
```typescript | ||
// Track a custom event | ||
client.track('user_action', context, { | ||
action: 'button_click', | ||
page: 'homepage', | ||
timestamp: Date.now(), | ||
}); | ||
``` | ||
|
||
## Contributing 🤝 | ||
|
||
We welcome contributions! Please see our [contributing guidelines](CONTRIBUTING.md) for details. | ||
|
||
## License 📄 | ||
|
||
This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details. | ||
|
||
## Support 💬 | ||
|
||
- **Documentation**: [GO Feature Flag Documentation](https://gofeatureflag.org/), [OpenFeature Documentation](https://openfeature.dev/) | ||
- **Issues**: [GitHub Issues](https://github.com/thomaspoignant/go-feature-flag/issues) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.