-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Adam Gardner <[email protected]>
- Loading branch information
1 parent
b11775f
commit 8a0ac35
Showing
24 changed files
with
1,767 additions
and
1 deletion.
There are no files selected for viewing
This file contains 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 |
---|---|---|
|
@@ -11,4 +11,7 @@ pkg/eval/flagd-definitions.json | |
core-coverage.out | ||
go.work | ||
go.work.sum | ||
bin/ | ||
bin/ | ||
|
||
# built documentation | ||
site |
This file contains 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 |
---|---|---|
@@ -0,0 +1,54 @@ | ||
site_name: flagd | ||
theme: | ||
name: material | ||
palette: | ||
# Palette toggle for light mode | ||
- media: "(prefers-color-scheme: light)" | ||
scheme: default | ||
toggle: | ||
icon: material/brightness-7 | ||
name: Switch to dark mode | ||
|
||
# Palette toggle for dark mode | ||
- media: "(prefers-color-scheme: dark)" | ||
scheme: slate | ||
toggle: | ||
icon: material/brightness-4 | ||
name: Switch to light mode | ||
# logo: path/to/file.png | ||
# favicon: path/to/file.png | ||
icon: | ||
repo: fontawesome/brands/github | ||
features: | ||
# - navigation.tabs | ||
- content.action.edit | ||
- content.code.copy | ||
|
||
docs_dir: web-docs | ||
repo_url: https://github.com/open-feature/flagd | ||
repo_name: open-feature/flagd | ||
edit_uri: edit/main/web-docs/ | ||
markdown_extensions: | ||
- pymdownx.highlight: | ||
anchor_linenums: true | ||
# linenums: true | ||
- pymdownx.inlinehilite | ||
- pymdownx.snippets | ||
- pymdownx.superfences | ||
|
||
nav: | ||
- 'Home': 'index.md' | ||
- 'Concepts': | ||
- 'Flagd concepts (start here)': 'concepts/index.md' | ||
- 'Flagd architecture': 'concepts/architecture.md' | ||
- 'Flagd on Kubernetes': | ||
- 'Getting started with flagd on kubernetes': 'k8s/index.md' | ||
- 'Flagd outside of kubernetes': | ||
- 'Getting started with flagd outside of kubernetes': 'nonk8s/index.md' | ||
- 'Flag merging': 'nonk8s/flagmerging.md' | ||
- 'Flagd as a system service': 'nonk8s/systemservice.md' | ||
- 'Kubernetes Custom Resources': | ||
- 'FlagSourceConfiguration': 'k8s/crds/flagsourceconfiguration.md' | ||
- 'FeatureFlagConfiguration': 'k8s/crds/featureflagconfiguration.md' | ||
- 'Flagd Telemetry': | ||
- 'Flagd OpenTelemetry Support': 'concepts/opentelemetry.md' |
This file contains 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 |
---|---|---|
@@ -0,0 +1,10 @@ | ||
[build] | ||
publish = "site" | ||
command = """ | ||
restore_home_cache ".cache" "pip cache" && | ||
restore_cwd_cache '.venv' 'python virtualenv' && | ||
pip3 install -q poetry && | ||
poetry config virtualenvs.in-project true && | ||
poetry install -v && | ||
mkdocs build -d site | ||
""" |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains 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 |
---|---|---|
@@ -0,0 +1,19 @@ | ||
[tool.poetry] | ||
name = "flagd.dev" | ||
version = "0.1.0" | ||
description = "flagd documentation" | ||
authors = ["OpenFeature Maintainers"] | ||
license = "Apache-2.0" | ||
readme = "README.md" | ||
|
||
[tool.poetry.dependencies] | ||
python = "^3.11" | ||
mkdocs = "^1.5.2" | ||
mkdocs-material = "^9.1.21" | ||
pymdown-extensions = "^10.1" | ||
fontawesome-markdown = "^0.2.6" | ||
|
||
|
||
[build-system] | ||
requires = ["poetry-core"] | ||
build-backend = "poetry.core.masonry.api" |
This file contains 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 |
---|---|---|
@@ -0,0 +1 @@ | ||
3.11 |
This file contains 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 |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# flagd Architecture | ||
|
||
```mermaid | ||
flowchart LR | ||
source-A -->|config-A| store -->|merge|source-A-config-A\nsource-B-config-B | ||
source-B -->|config-B| store | ||
``` | ||
|
||
## Component overview | ||
|
||
Flagd consists of four main components - Service, Evaluator engine, Runtime and Sync. | ||
|
||
The service component exposes the evaluator engine for client libraries. | ||
It further exposes an interface | ||
for flag configuration change notifications. | ||
|
||
The sync component has implementations to update flag configurations from various sources. | ||
The current implementation | ||
contain sync providers for files, K8s resources and HTTP endpoints. | ||
|
||
The evaluation engine's role is twofold, it acts as an intermediary between configuration changes and the state store by interpreting change events and forwarding the necessary changes to the state store. | ||
It also performs the feature flag evaluations based on evaluation requests coming from feature flag libraries. | ||
|
||
The Runtime stays in between these components and coordinates operations. | ||
|
||
![flagd runtime](../images/of-flagd-0.png) | ||
|
||
## Sync component | ||
|
||
The Sync component contains implementations of the ISync interface. | ||
The interface contract simply allows updating | ||
flag configurations watched by the respective implementation. | ||
For example, the file sync provider watches for a change | ||
(ex: - add, modify, remove) of a specific file in the file system. | ||
|
||
The update provided by sync implementation is pushed to the evaluator engine, which interprets the event and forwards it to the state store. | ||
Change notifications generated in the | ||
process gets pushed to event subscribers. | ||
|
||
![flagd sync logic](../images/of-flagd-1.png) | ||
|
||
## Readiness & Liveness probes | ||
|
||
Flagd exposes HTTP liveness and readiness probes. | ||
These probes can be used for K8s deployments. | ||
With default | ||
start-up configurations, these probes are exposed at the following URLs, | ||
|
||
- Liveness: <http://localhost:8014/healthz> | ||
- Readiness: <http://localhost:8014/readyz> | ||
|
||
### Definition of Liveness | ||
|
||
The liveness probe becomes active and HTTP 200 status is served as soon as Flagd service is up and running. | ||
|
||
### Definition of Readiness | ||
|
||
The readiness probe becomes active similar to the liveness probe as soon as Flagd service is up and running. | ||
However, | ||
the probe emits HTTP 412 until all sync providers are ready. | ||
This status changes to HTTP 200 when all sync providers at | ||
least have one successful data sync. | ||
The status does not change from there on. |
This file contains 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 |
---|---|---|
@@ -0,0 +1,197 @@ | ||
# flagd basics | ||
|
||
Your flagd journey will start by defining your feature flags. | ||
|
||
flagd will then read those feature flags and make them available to your application. | ||
|
||
Your application will interact with flagd via the [OpenFeature SDK](https://openfeature.dev/docs/reference/concepts/evaluation-api) to retrieve flag values via the flagd API. | ||
|
||
![flagd architecture](../images/flagd-logical-architecture.jpg) | ||
|
||
## Defining feature flags | ||
|
||
Flags can be defined in either [JSON](https://github.com/open-feature/flagd/blob/main/samples/example_flags.flagd.json) or [YAML](https://github.com/open-feature/flagd/blob/main/samples/example_flags.flagd.yaml) syntax and the values can be of different types. | ||
|
||
Here are two flags, `flagOne` has `boolean` values and `flagTwo` has `string` values. | ||
|
||
### flags represented as JSON | ||
|
||
```json | ||
{ | ||
"flags": { | ||
"flagOne": { | ||
"state": "ENABLED", | ||
"variants": { | ||
"on": true, | ||
"off": false | ||
}, | ||
"defaultVariant": "on", | ||
"targeting": {} | ||
}, | ||
"flagTwo": { | ||
"state": "ENABLED", | ||
"variants": { | ||
"key1": "val1", | ||
"key2": "val2" | ||
}, | ||
"defaultVariant": "key1", | ||
"targeting": {} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
### flags represented as YAML | ||
|
||
```yaml | ||
flags: | ||
flagOne: | ||
state: ENABLED | ||
variants: | ||
'on': true | ||
'off': false | ||
defaultVariant: 'on' | ||
targeting: | ||
flagTwo: | ||
state: ENABLED | ||
variants: | ||
key1: val1 | ||
key2: val2 | ||
defaultVariant: 'key1' | ||
targeting: | ||
``` | ||
## The structure of a flag | ||
Each flag has: | ||
- A flag key: `flagOne` and `flagTwo` above | ||
- A state: `ENABLED` or `DISABLED` | ||
- One or more possible `variants`. These are the possible values that a flag key can take. | ||
- An optional `targeting` rule (explained below) | ||
|
||
## Targeting rules | ||
|
||
Imagine you are introducing a new feature. You create a flag with two possible variants: `on` and `off`. You want to safely roll out the feature. | ||
Therefore the flags `defaultValue` is set to `off` for all users. | ||
|
||
In other words, the new feature is disabled by default. | ||
|
||
Now imagine you want to enable the feature, but only when the following is true: | ||
|
||
- Logged in users where the user's email ends in `@example.com` | ||
|
||
Rather than codifying that in your application, flagd targeting rules can be used. The flag definition below models this behaviour. | ||
|
||
When a user logs into your application, your application is responsible for sending the `email` address via OpenFeature's context parameter (see below) and flagd will return the correct flag. | ||
If the email address of the logged in users contains `@example.com` then flagd will return the `on` variant (ie. `true`). | ||
All other users receives the `defaultVariant` of `off` (ie. false). | ||
In this context, "all other users" means: | ||
|
||
- Any logged in user whos email does not contain `@example.com` | ||
- Any logged out user | ||
|
||
Your application is responsible for sending the `email` address via OpenFeature's context parameter (see below) and flagd will return the correct flag. | ||
|
||
```json | ||
{ | ||
"flags": { | ||
"isFeatureEnabled": { | ||
"state": "ENABLED", | ||
"variants": { | ||
"on": true, | ||
"off": false | ||
}, | ||
"defaultVariant": "off", | ||
"targeting": { | ||
"if": [{ | ||
"in": [ | ||
"@example.com", | ||
{ | ||
"var": ["email"] | ||
}] | ||
}, | ||
"on", null] | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
### Pseudo-code of application passing context | ||
|
||
```js | ||
// Here, we provide an empty context, hence the flag evaluates to false value which is the defaultVariant | ||
featureAvailable = openFeature.getBooleanValue("isFeatureEnabled", false, {}) // false | ||
// Here, we provide email for the flag evaluation. Still flag evaluates to defaultVariant of false as email does not end with desired domain | ||
featureAvailable = openFeature.getBooleanValue("isFeatureEnabled", false, {"email": "[email protected]"}) // false | ||
// Here, the flag is evaluated with targeting rule matching, hence the value of true | ||
featureAvailable = openFeature.getBooleanValue("isFeatureEnabled", false, {"email": "[email protected]"}) // true | ||
``` | ||
|
||
## Fractional Evaluation | ||
|
||
In some scenarios, it is desirable to use contextual information to segment the user population further and thus return dynamic values. | ||
|
||
Look at the `headerColor` flag below. The `defaultVariant` is `red`, but the flag contains a targeting rule, meaning a fractional evaluation occurs when a context is passed and a key of `email` contains the value `@example.com`. | ||
|
||
In this case, `25%` of the email addresses will receive `red`, `25%` will receive `blue`, and so on. | ||
|
||
```json | ||
{ | ||
"flags": { | ||
"headerColor": { | ||
"variants": { | ||
"red": "#FF0000", | ||
"blue": "#0000FF", | ||
"green": "#00FF00", | ||
"yellow": "#FFFF00" | ||
}, | ||
"defaultVariant": "red", | ||
"state": "ENABLED", | ||
"targeting": { | ||
"if": [{ | ||
"emailWithFaas": { | ||
"in": ["@faas.com", { | ||
"var": ["email"] | ||
}] | ||
} | ||
}, | ||
{ | ||
"fractionalEvaluation": [ "email", | ||
[ "red", 25 ], [ "blue", 25 ], [ "green", 25 ], [ "yellow", 25 ] | ||
] | ||
}, null | ||
] | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
### Fractional evaluations are sticky | ||
|
||
Fractional evaluations are "sticky" and deterministic meaning that the same email address will always belong to the same "bucket" and thus always receive the same color. | ||
|
||
This is true even if you run multiple flagd APIs completely independently. | ||
|
||
See this page for more information on [flagd fractional evaluation logic](https://github.com/open-feature/flagd/blob/main/docs/configuration/fractional_evaluation.md). | ||
|
||
## Other target specifiers | ||
|
||
The example above shows the `in` keyword being used, but flagd is also compatible with: | ||
|
||
- [starts_with](https://github.com/open-feature/flagd/blob/main/docs/configuration/string_comparison_evaluation.md#startswith-evaluation-configuration) | ||
- [ends_with](https://github.com/open-feature/flagd/blob/main/docs/configuration/string_comparison_evaluation.md#endswith-evaluation-configuration) | ||
- [sem_ver comparisons](https://github.com/open-feature/flagd/blob/main/docs/configuration/sem_ver_evaluation.md) | ||
|
||
## flagd OpenTelemetry | ||
|
||
flagd is fully compatible with OpenTelemetry: | ||
|
||
- flagd exposes metrics at `http://localhost:8014/metrics` | ||
- flagd can export metrics and traces to an OpenTelemetry collector. | ||
|
||
See the [flagd OpenTelemetry](opentelemetry.md) page for more information. |
Oops, something went wrong.