Skip to content

Commit

Permalink
docs: initial docs commit (#782)
Browse files Browse the repository at this point in the history
Signed-off-by: Adam Gardner <[email protected]>
  • Loading branch information
agardnerIT authored Aug 4, 2023
1 parent b11775f commit 8a0ac35
Show file tree
Hide file tree
Showing 24 changed files with 1,767 additions and 1 deletion.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ pkg/eval/flagd-definitions.json
core-coverage.out
go.work
go.work.sum
bin/
bin/

# built documentation
site
54 changes: 54 additions & 0 deletions mkdocs.yml
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'
10 changes: 10 additions & 0 deletions netlify.toml
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
"""
660 changes: 660 additions & 0 deletions poetry.lock

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions pyproject.toml
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"
1 change: 1 addition & 0 deletions runtime.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.11
63 changes: 63 additions & 0 deletions web-docs/concepts/architecture.md
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.
197 changes: 197 additions & 0 deletions web-docs/concepts/index.md
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.
Loading

0 comments on commit 8a0ac35

Please sign in to comment.