From 893134eb31d7a044418c1b88e77049baf36055db Mon Sep 17 00:00:00 2001 From: Thomas Poignant Date: Sun, 24 Mar 2024 20:47:58 +0100 Subject: [PATCH] Create a new documentation version v1.24.1 (#1668) Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: thomaspoignant <17908063+thomaspoignant@users.noreply.github.com> Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../version-v1.24.1/_category_.json | 5 + .../configure_flag/_category_.json | 10 + .../configure_flag/export_flags_usage.mdx | 93 +++++ .../configure_flag/flag_format.mdx | 394 ++++++++++++++++++ .../configure_flag/rollout/_category_.json | 11 + .../configure_flag/rollout/canary.mdx | 68 +++ .../rollout/experimentation.mdx | 107 +++++ .../configure_flag/rollout/progressive.mdx | 97 +++++ .../configure_flag/rollout/scheduled.mdx | 138 ++++++ .../configure_flag/rule_format.md | 159 +++++++ .../configure_flag/store_your_flags.mdx | 128 ++++++ .../experimental/_category_.json | 6 + .../version-v1.24.1/experimental/ofrep.md | 30 ++ website/versioned_docs/version-v1.24.1/faq.md | 52 +++ .../getting_started/_category_.json | 12 + .../getting_started/using-go-module.md | 62 +++ .../getting_started/using-openfeature.md | 130 ++++++ .../version-v1.24.1/go_module/_category_.json | 10 + .../go_module/configuration.md | 100 +++++ .../go_module/data_collection/_category_.json | 5 + .../go_module/data_collection/custom.md | 24 ++ .../go_module/data_collection/file.md | 38 ++ .../data_collection/google_cloud_storage.md | 46 ++ .../go_module/data_collection/index.md | 141 +++++++ .../go_module/data_collection/kafka.md | 32 ++ .../go_module/data_collection/log.md | 30 ++ .../go_module/data_collection/s3.md | 52 +++ .../go_module/data_collection/sqs.md | 31 ++ .../go_module/data_collection/webhook.md | 75 ++++ .../go_module/notifier/_category_.json | 5 + .../go_module/notifier/custom.md | 24 ++ .../go_module/notifier/index.md | 17 + .../go_module/notifier/slack.md | 33 ++ .../go_module/notifier/webhook.md | 114 +++++ .../go_module/store_file/_category_.json | 5 + .../go_module/store_file/custom.md | 38 ++ .../go_module/store_file/file.md | 31 ++ .../go_module/store_file/github.md | 40 ++ .../go_module/store_file/gitlab.md | 42 ++ .../store_file/google_cloud_storage.md | 31 ++ .../go_module/store_file/http.md | 33 ++ .../go_module/store_file/index.md | 18 + .../store_file/kubernetes_configmaps.md | 47 +++ .../go_module/store_file/mongodb.md | 55 +++ .../go_module/store_file/s3.md | 33 ++ .../version-v1.24.1/go_module/target_user.md | 185 ++++++++ .../versioned_docs/version-v1.24.1/index.md | 36 ++ .../openfeature_sdk/_category_.json | 6 + .../client_providers/_category_.json | 6 + .../client_providers/openfeature_android.mdx | 106 +++++ .../openfeature_javascript.mdx | 81 ++++ .../version-v1.24.1/openfeature_sdk/sdk.mdx | 89 ++++ .../server_providers/_category_.json | 6 + .../server_providers/openfeature_dotnet.mdx | 123 ++++++ .../server_providers/openfeature_go.mdx | 111 +++++ .../server_providers/openfeature_java.mdx | 148 +++++++ .../openfeature_javascript.mdx | 136 ++++++ .../server_providers/openfeature_python.md | 77 ++++ .../relay_proxy/_category_.json | 6 + .../relay_proxy/configure_relay_proxy.md | 246 +++++++++++ .../relay_proxy/deploy_relay_proxy.md | 60 +++ .../relay_proxy/getting_started.md | 61 +++ .../version-v1.24.1/relay_proxy/index.mdx | 20 + .../relay_proxy/install_relay_proxy.md | 31 ++ .../relay_proxy/monitor_relay_proxy.md | 55 +++ .../relay_proxy/relay_proxy_endpoints.md | 26 ++ .../version-v1.24.1/tooling/_category_.json | 6 + .../version-v1.24.1/tooling/autocomplete.md | 13 + .../version-v1.24.1/tooling/linter.mdx | 117 ++++++ .../version-v1.24.1/tooling/migrate_v0_v1.md | 59 +++ .../version-v1.24.1-sidebars.json | 8 + website/versions.json | 1 + 72 files changed, 4471 insertions(+) create mode 100644 website/versioned_docs/version-v1.24.1/_category_.json create mode 100644 website/versioned_docs/version-v1.24.1/configure_flag/_category_.json create mode 100644 website/versioned_docs/version-v1.24.1/configure_flag/export_flags_usage.mdx create mode 100644 website/versioned_docs/version-v1.24.1/configure_flag/flag_format.mdx create mode 100644 website/versioned_docs/version-v1.24.1/configure_flag/rollout/_category_.json create mode 100644 website/versioned_docs/version-v1.24.1/configure_flag/rollout/canary.mdx create mode 100644 website/versioned_docs/version-v1.24.1/configure_flag/rollout/experimentation.mdx create mode 100644 website/versioned_docs/version-v1.24.1/configure_flag/rollout/progressive.mdx create mode 100644 website/versioned_docs/version-v1.24.1/configure_flag/rollout/scheduled.mdx create mode 100644 website/versioned_docs/version-v1.24.1/configure_flag/rule_format.md create mode 100644 website/versioned_docs/version-v1.24.1/configure_flag/store_your_flags.mdx create mode 100644 website/versioned_docs/version-v1.24.1/experimental/_category_.json create mode 100644 website/versioned_docs/version-v1.24.1/experimental/ofrep.md create mode 100644 website/versioned_docs/version-v1.24.1/faq.md create mode 100644 website/versioned_docs/version-v1.24.1/getting_started/_category_.json create mode 100644 website/versioned_docs/version-v1.24.1/getting_started/using-go-module.md create mode 100644 website/versioned_docs/version-v1.24.1/getting_started/using-openfeature.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/_category_.json create mode 100644 website/versioned_docs/version-v1.24.1/go_module/configuration.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/data_collection/_category_.json create mode 100644 website/versioned_docs/version-v1.24.1/go_module/data_collection/custom.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/data_collection/file.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/data_collection/google_cloud_storage.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/data_collection/index.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/data_collection/kafka.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/data_collection/log.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/data_collection/s3.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/data_collection/sqs.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/data_collection/webhook.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/notifier/_category_.json create mode 100644 website/versioned_docs/version-v1.24.1/go_module/notifier/custom.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/notifier/index.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/notifier/slack.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/notifier/webhook.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/store_file/_category_.json create mode 100644 website/versioned_docs/version-v1.24.1/go_module/store_file/custom.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/store_file/file.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/store_file/github.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/store_file/gitlab.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/store_file/google_cloud_storage.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/store_file/http.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/store_file/index.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/store_file/kubernetes_configmaps.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/store_file/mongodb.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/store_file/s3.md create mode 100644 website/versioned_docs/version-v1.24.1/go_module/target_user.md create mode 100644 website/versioned_docs/version-v1.24.1/index.md create mode 100644 website/versioned_docs/version-v1.24.1/openfeature_sdk/_category_.json create mode 100644 website/versioned_docs/version-v1.24.1/openfeature_sdk/client_providers/_category_.json create mode 100644 website/versioned_docs/version-v1.24.1/openfeature_sdk/client_providers/openfeature_android.mdx create mode 100644 website/versioned_docs/version-v1.24.1/openfeature_sdk/client_providers/openfeature_javascript.mdx create mode 100644 website/versioned_docs/version-v1.24.1/openfeature_sdk/sdk.mdx create mode 100644 website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/_category_.json create mode 100644 website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_dotnet.mdx create mode 100644 website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_go.mdx create mode 100644 website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_java.mdx create mode 100644 website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_javascript.mdx create mode 100644 website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_python.md create mode 100644 website/versioned_docs/version-v1.24.1/relay_proxy/_category_.json create mode 100644 website/versioned_docs/version-v1.24.1/relay_proxy/configure_relay_proxy.md create mode 100644 website/versioned_docs/version-v1.24.1/relay_proxy/deploy_relay_proxy.md create mode 100644 website/versioned_docs/version-v1.24.1/relay_proxy/getting_started.md create mode 100644 website/versioned_docs/version-v1.24.1/relay_proxy/index.mdx create mode 100644 website/versioned_docs/version-v1.24.1/relay_proxy/install_relay_proxy.md create mode 100644 website/versioned_docs/version-v1.24.1/relay_proxy/monitor_relay_proxy.md create mode 100644 website/versioned_docs/version-v1.24.1/relay_proxy/relay_proxy_endpoints.md create mode 100644 website/versioned_docs/version-v1.24.1/tooling/_category_.json create mode 100644 website/versioned_docs/version-v1.24.1/tooling/autocomplete.md create mode 100644 website/versioned_docs/version-v1.24.1/tooling/linter.mdx create mode 100644 website/versioned_docs/version-v1.24.1/tooling/migrate_v0_v1.md create mode 100644 website/versioned_sidebars/version-v1.24.1-sidebars.json diff --git a/website/versioned_docs/version-v1.24.1/_category_.json b/website/versioned_docs/version-v1.24.1/_category_.json new file mode 100644 index 00000000000..c640b3bdf2d --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": false +} diff --git a/website/versioned_docs/version-v1.24.1/configure_flag/_category_.json b/website/versioned_docs/version-v1.24.1/configure_flag/_category_.json new file mode 100644 index 00000000000..93abd20b37d --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/configure_flag/_category_.json @@ -0,0 +1,10 @@ +{ + "position": 20, + "collapsible": true, + "collapsed": true, + "label": "Configure your feature flags", + "link": { + "type": "generated-index", + "title": "Configure your feature flags" + } +} diff --git a/website/versioned_docs/version-v1.24.1/configure_flag/export_flags_usage.mdx b/website/versioned_docs/version-v1.24.1/configure_flag/export_flags_usage.mdx new file mode 100644 index 00000000000..1cc3aa1b680 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/configure_flag/export_flags_usage.mdx @@ -0,0 +1,93 @@ +--- +sidebar_position: 40 +description: How to export evaluation data? +--- +import {Cards} from '@site/src/components/doc/cardv2'; +import { ConfigCardContent } from "@site/src/components/doc/configCardContent"; +import customlogo from '@site/static/docs/collectors/custom.png'; +import filelogo from '@site/static/docs/collectors/file.png'; +import googlelogo from '@site/static/docs/collectors/google.png'; +import loglogo from '@site/static/docs/collectors/log.png'; +import s3logo from '@site/static/docs/collectors/s3.png'; +import webhooklogo from '@site/static/docs/collectors/webhook.png'; +import sqslogo from '@site/static/docs/collectors/sqs.png'; +import kafkalogo from '@site/static/docs/collectors/kafka.png'; + + +# How to export evaluation data +GO Feature Flag allows for the collection of flag usage data. +During flag evaluation, the key, flag variation and other non-sensitive information used are collected and cached for a +configurable period of time. + +The usage data is then written to a file in a chosen format (`parquet`, `JSON` or `CSV`) at a specified interval and +exported to your desired location. This provides a single source for easy processing of the data. The feature can be +configured with options for file format, flush interval, and file location. + +To use, simply configure and use the feature flag as normal, and analyze the collected usage data. + +## Available exporters + + }, + { + logoImg: sqslogo, + title:"AWS SQS", + content: + }, + { + logoImg: kafkalogo, + title:"Kafka", + content: + }, + { + logoImg: googlelogo, + title:"Google Storage", + content: + }, + { + logoImg: webhooklogo, + title:"Webhook", + content: + }, + { + logoImg: filelogo, + title:"Local File", + content: + }, + { + logoImg: loglogo, + title:"Webhook", + content: + }, + { + logoImg: customlogo, + title:"Custom ...", + content: + }, +]} /> diff --git a/website/versioned_docs/version-v1.24.1/configure_flag/flag_format.mdx b/website/versioned_docs/version-v1.24.1/configure_flag/flag_format.mdx new file mode 100644 index 00000000000..2b0141fed06 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/configure_flag/flag_format.mdx @@ -0,0 +1,394 @@ +--- +sidebar_position: 20 +description: What is a flag and how you can create them. +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# How to configure a flag + +**GO Feature Flag** core feature is to centralize all your feature flags in a source file, and to avoid hosting and maintaining a backend server to manage them. + +Your file must be a valid `YAML`, `JSON` or `TOML` file with a list of flags +_(examples: [`YAML`](https://github.com/thomaspoignant/go-feature-flag/tree/main/testdata/flag-config.yaml), +[`JSON`](https://github.com/thomaspoignant/go-feature-flag/tree/main/testdata/flag-config.json), +[`TOML`](https://github.com/thomaspoignant/go-feature-flag/tree/main/testdata/flag-config.toml))_. + +:::tip +The easiest way to create your configuration file is to used +[**GO Feature Flag Editor** available at [https://editor.gofeatureflag.org](https://editor.gofeatureflag.org). + +If you prefer to do it manually please follow instruction bellow. +::: + +## Editor + +Creating the first version of the flag is not always pleasant, that's why we have created +[**GO Feature Flag Editor**](https://editor.gofeatureflag.org) a simple editor to create your files. + +## Example + +A flag configuration looks like: + + + + +```yaml +# This is your configuration for your first flag +first-flag: + variations: # All possible return value for your feature flag + A: false + B: true + targeting: # If you want to target a subset of your users in particular + - query: key eq "random-key" + percentage: + A: 0 + B: 100 + defaultRule: # When no targeting match we use the defaultRule + variation: A + metadata: + issue_link: https://github.com/thomaspoignant/go-feature-flag/issues/XXX + description: this is my first feature flag + +# A second example of a flag configuration +second-flag: + variations: + A: "valueA" + B: "valueB" + defaultValue: "a default value" + targeting: + - name: legacyRuleV0 + query: key eq "not-a-key" + percentage: + A: 10 + B: 90 + defaultRule: + name: legacyDefaultRule + variation: defaultValue + version: "12" + experimentation: + start: 2021-03-20T00:00:00.1-05:00 + end: 2021-03-21T00:00:00.1-05:00 +``` + + + + +```json +{ + "first-flag": { + "variations": { + "A": false, + "B": true + }, + "targeting": [ + { + "query": "key eq \"random-key\"", + "percentage": { + "A": 0, + "B": 100 + } + } + ], + "defaultRule": { + "variation": "A" + }, + "metadata": { + "issue_link": "https://github.com/thomaspoignant/go-feature-flag/issues/XXX", + "description": "this is my first feature flag" + } + }, + + "second-flag": { + "variations": { + "A": "valueA", + "B": "valueB", + "defaultValue": "a default value" + }, + "targeting": [ + { + "name": "legacyRuleV0", + "query": "key eq \"not-a-key\"", + "percentage": { + "A": 10, + "B": 90 + } + } + ], + "defaultRule": { + "name": "legacyDefaultRule", + "variation": "defaultValue" + }, + "version": "12", + "experimentation": { + "start": "2021-03-20T05:00:00.100Z", + "end": "2021-03-21T05:00:00.100Z" + } + } +} +``` + + + + +```toml +[first-flag.variations] +A = false +B = true + +[[first-flag.targeting]] +query = 'key eq "random-key"' + + [first-flag.targeting.percentage] + A = 0 + B = 100 + +[first-flag.defaultRule] +variation = "A" + +[first-flag.metadata] +issue_link = "https://github.com/thomaspoignant/go-feature-flag/issues/XXX" +description = "this is my first feature flag" + +[second-flag] +version = "12" + + [second-flag.variations] + A = "valueA" + B = "valueB" + defaultValue = "a default value" + + [[second-flag.targeting]] + name = "legacyRuleV0" + query = 'key eq "not-a-key"' + + [second-flag.targeting.percentage] + A = 10 + B = 90 + + [second-flag.defaultRule] + name = "legacyDefaultRule" + variation = "defaultValue" + + [second-flag.experimentation] + start = 2021-03-20T05:00:00.100Z + end = 2021-03-21T05:00:00.100Z +``` + + + + +## Format details + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+ flag-key + + Name of your flag. +
+ + It must be unique. +
+ On the example the flag keys are test-flag and{" "} + test-flag2. +
+
+ variations + +

Variations are all the variations available for this flag.

+

+ It is represented as a key/value element. The key is the name of the + variation and the value could be of any types available ( + string, float, int,{" "} + map, array, bool). +

+

You can have as many variations as needed.

+
+          

Some examples:

+
+ variationString: test +
+ variationBool: true +
+ variationInt: 1000 +
+ variationFloat: 1000.23 +
+ variationArray:
- item1 +
- item2 +
+ variationObj: +
item1: 123 +
item2: this is a string +
item3: false +
+
+
+ targeting +
+ (optional) +
+

+ Targeting contains the list of rules you have to target a subset of + your users. +
+ You can have as many target as needed. +

+

+ This field is an array and contains a list of rules. +

+

+ + See rules format to have more info on + how to write a rule. + +

+
+ defaultRule + +

+ DefaultRule is the rule that is applied if the user does not match in + any targeting. +

+

+ + See rules format to have more info on + how to write a rule. + +

+
+ trackEvents +
+ (optional) +
+

+ false if you don't want to export the data in your data + exporter. +

+

+ Default: true +

+
+ disable +
+ (optional) +
+

+ true if the flag is disabled. +

+

+ Default: false +

+
+ version +
+ (optional) +
+

+ The `version` is the version of your flag. +
+ This string is used to display the information in the notifiers and + data collection, you have to update it yourself. +

+

+ Default: "" +

+
+ metadata +
+ (optional) +
+

+ This field allows adding a wealth of information about a particular + feature flag, such as a configuration URL or the originating Jira + issue. +

+
+ scheduledRollout +
+ (optional) +
+

`scheduledRollout` allows to patch your flag over time.

+

+ You can add several steps that update the flag, this is typically + used if you want to gradually add more user in your flag. +

+

+ + See Scheduled rollout to have + more info on how to use it. + +

+
+ experimentation +
+ (optional) +
+

+ Experimentation allows you to configure a start date and an end date + for your flag. When the experimentation is not running, the flag will + serve the default value. +

+

+ + See Experimentation rollout{" "} + to have more info on how to use it. + +

+
+ +## Advanced configurations + +You can have advanced configurations for your flag for them to have specific behavior, such as: + +- [Specific rollout strategies](../category/rollout-strategies/) +- [Don't track a flag](../go_module/data_collection/index.md#dont-track-a-flag) diff --git a/website/versioned_docs/version-v1.24.1/configure_flag/rollout/_category_.json b/website/versioned_docs/version-v1.24.1/configure_flag/rollout/_category_.json new file mode 100644 index 00000000000..0128b230fcf --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/configure_flag/rollout/_category_.json @@ -0,0 +1,11 @@ +{ + "position": 30, + "collapsible": true, + "collapsed": true, + "label": "Rollout strategies", + "link": { + "type": "generated-index", + "title": "Rollout strategies", + "description": "A critical part of every new feature release is orchestrating the actual launch schedule between Product, Engineering, and Marketing teams. Delivering powerful user experiences typically requires software teams to manage complex releases and make manual updates at inconvenient times. But it doesn’t have to! Having a complex rollout strategy allows you to have lifecycle for your flags." + } +} diff --git a/website/versioned_docs/version-v1.24.1/configure_flag/rollout/canary.mdx b/website/versioned_docs/version-v1.24.1/configure_flag/rollout/canary.mdx new file mode 100644 index 00000000000..cca4d50e6be --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/configure_flag/rollout/canary.mdx @@ -0,0 +1,68 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Canary Release + +**Canary release** is a technique to reduce the risk of introducing a new software version in production by slowly rolling out the change to a small subset of users before rolling it out to the entire infrastructure and making it available to everybody. + +This is the easiest rollout strategy available. +You just have to select a percentage of your users in your flag, and the `True` behavior will apply to them. + +## Example + + + + +```yaml +canary-flag: + variations: + oldBehavior: false + canary: true + defaultRule: + # highlight-start + percentage: + oldBehavior: 99 + canary: 1 + # highlight-end +``` + + + + +```json + { + "canary-flag": { + "variations": { + "oldBehavior": false, + "canary": true + }, + "defaultRule": { +# highlight-start + "percentage": { + "oldBehavior": 99, + "canary": 1 + } +# highlight-end + } + } +} +``` + + + + + +```toml +[canary-flag.variations] +oldBehavior = false +canary = true + +# highlight-start +[canary-flag.defaultRule.percentage] +oldBehavior = 99 +canary = 1 +# highlight-end +``` + + + diff --git a/website/versioned_docs/version-v1.24.1/configure_flag/rollout/experimentation.mdx b/website/versioned_docs/version-v1.24.1/configure_flag/rollout/experimentation.mdx new file mode 100644 index 00000000000..f560898c68e --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/configure_flag/rollout/experimentation.mdx @@ -0,0 +1,107 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Experimentation rollout / A/B Testing +An **experimentation rollout** is when your flag is configured to be served only for a determined time. + +1. It means that before the rollout start date, the `default` value is served to all users. +2. Between the dates the flag is evaluated. +3. After the end date the `default` value is served to all users. + +## Example + + + + +```yaml +experimentation-flag: + variations: + variationA: A + variationB: B + defaultRule: + percentage: + variationA: 50 + variationB: 50 + # highlight-start + experimentation: + start: 2021-03-20T00:00:00.1-05:00 + end: 2021-03-21T00:00:00.1-05:00 + # highlight-end +``` + + + + +```json +{ + "experimentation-flag": { + "variations": { + "variationA": "A", + "variationB": "B" + }, + "defaultRule": { + "percentage": { + "variationA": 50, + "variationB": 50 + } + }, +# highlight-start + "experimentation": { + "start": "2021-03-20T05:00:00.100Z", + "end": "2021-03-21T05:00:00.100Z" + }, +# highlight-end + } +} +``` + + + + +```toml +[experimentation-flag.variations] +variationA = "A" +variationB = "B" + +[experimentation-flag.defaultRule.percentage] +variationA = 50 +variationB = 50 + +# highlight-start +[experimentation-flag.experimentation] +start = 2021-03-20T05:00:00.100Z +end = 2021-03-21T05:00:00.100Z +# highlight-end +``` + + + + +Check this [example](https://github.com/thomaspoignant/go-feature-flag/tree/main/examples/rollout_experimentation) to see how it works. + +## Configuration fields + +:::info +The dates are in the format supported natively by your flag file format. +::: + +| Field | Description | +|-------------|-------------------------------------------------| +| **`start`** | The date the flag will be started to be served. | +| **`end`** | The date the flag will be stopped to be served. | + +## A/B testing + +:::info +A/B test is the shorthand for a simple controlled experiment. +As the name implies, two versions (A and B) of a single variable are compared, which are identical except for one variation that might affect a user's behavior. +A/B tests are widely considered the simplest form of controlled experiment. + +_**(source wikipedia)**_ +::: + +To have a proper A/B testing solution with the module you should use the experimentation rollout combined with the [export of your data](../../go_module/data_collection/). + +This combination will allow to have your experimentation running for a dedicated time, and you will have the data to know exactly which user was on which version of the flag. + +To setup the duration of your A/B test you can use a tool [ab-test-duration-calculator](https://vwo.com/tools/ab-test-duration-calculator/) from vwo, that will help you to set up the test duration correctly. diff --git a/website/versioned_docs/version-v1.24.1/configure_flag/rollout/progressive.mdx b/website/versioned_docs/version-v1.24.1/configure_flag/rollout/progressive.mdx new file mode 100644 index 00000000000..58014688ebe --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/configure_flag/rollout/progressive.mdx @@ -0,0 +1,97 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Progressive rollout + +A **progressive rollout** allows you to increase the percentage of your flag over time. + +You can select a **release ramp** where the percentage of your flag will increase progressively between the start date +and the end date. + +## Example + + + + +```yaml +progressive-flag: + variations: + variationA: A + variationB: B + defaultRule: +# highlight-start + progressiveRollout: + initial: + variation: variationB + percentage: 0 + date: 2021-03-20T00:00:00.1-05:00 + end: + variation: variationB + percentage: 100 + date: 2021-03-21T00:00:00.1-05:00 +# highlight-end +``` + + + + +```json +{ + "progressive-flag": { + "variations": { + "variationA": "A", + "variationB": "B" + }, + "defaultRule": { +# highlight-start + "progressiveRollout": { + "initial": { + "variation": "variationB", + "percentage": 0, + "date": "2021-03-20T05:00:00.100Z" + }, + "end": { + "variation": "variationB", + "percentage": 100, + "date": "2021-03-21T05:00:00.100Z" + } + }, +# highlight-end + } + } +} +``` + + + + +```toml +[progressive-flag.variations] +variationA = "A" +variationB = "B" +# highlight-start +[progressive-flag.defaultRule.progressiveRollout.initial] +variation = "variationB" +percentage = 0 +date = 2021-03-20T05:00:00.100Z + +[progressive-flag.defaultRule.progressiveRollout.end] +variation = "variationB" +percentage = 100 +date = 2021-03-21T05:00:00.100Z +# highlight-end +``` + + + + +## Configuration fields + +:::info +The dates are in the format supported natively by your flag file format. +::: + +| Field | Description | +|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **`releaseRamp`** | It contains the time slot where we will progressively increase the percentage of the flag.
  • **Before** the `start` date we will serve the `percentage.initial` percentage of the flag.
  • **Between** `start` and `end` we will serve a percentage of the flag corresponding to the actual time.
  • **After** the `end` date we will serve the `percentage.end` percentage of the flag.

If you have no date in your `releaseRamp` we will not do any progressive rollout and use the top level percentage you have configured *(0% in our example)*.

| +| **`percentage`** | *(optional)*
It represents the ramp of progress, at which level the flag starts (`initial`) and ends (`end`).
**Default: `initial` = `0` and `end` = `100`** | diff --git a/website/versioned_docs/version-v1.24.1/configure_flag/rollout/scheduled.mdx b/website/versioned_docs/version-v1.24.1/configure_flag/rollout/scheduled.mdx new file mode 100644 index 00000000000..ebea39febb6 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/configure_flag/rollout/scheduled.mdx @@ -0,0 +1,138 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Scheduled rollout + +Scheduling introduces the ability for users to changes their flags for future points in time. +While this sounds deceptively straightforward, it unlocks the potential for users to create complex release strategies by scheduling the incremental steps in advance. + +For example, you may want to turn a feature ON for internal testing tomorrow and then enable it for your ‘beta’ user segment four days later. + +## Example + + + + +```yaml +scheduled-flag: + variations: + variationA: A + variationB: B + defaultRule: + name: legacyDefaultRule + percentage: + variationA: 100 + variationB: 0 +# highlight-start + scheduledRollout: + - date: 2020-04-10T00:00:00.1+02:00 + targeting: + - name: legacyRuleV0 + query: beta eq "true" + percentage: + variationA: 0 + variationB: 100 + + - date: 2022-05-12T15:36:00.1+02:00 + targeting: + - name: legacyRuleV0 + query: beta eq "false" +# highlight-end +``` + + + + +```json +{ + "scheduled-flag": { + "variations": { + "variationA": "A", + "variationB": "B" + }, + "defaultRule": { + "name": "legacyDefaultRule", + "percentage": { + "variationA": 100, + "variationB": 0 + } + }, + # highlight-start + "scheduledRollout": [ + { + "date": "2020-04-09T22:00:00.100Z", + "targeting": [ + { + "name": "legacyRuleV0", + "query": "beta eq \"true\"", + "percentage": { + "variationA": 0, + "variationB": 100 + } + } + ] + }, + { + "date": "2022-05-12T13:36:00.100Z", + "targeting": [ + { + "name": "legacyRuleV0", + "query": "beta eq \"false\"" + } + ] + } + ], + # highlight-end + } +} +``` + + + + +```toml +[scheduled-flag.variations] +variationA = "A" +variationB = "B" + +[scheduled-flag.defaultRule] +name = "legacyDefaultRule" + +[scheduled-flag.defaultRule.percentage] +variationA = 100 +variationB = 0 + +# highlight-start +[[scheduled-flag.scheduledRollout]] +date = 2020-04-09T22:00:00.100Z + +[[scheduled-flag.scheduledRollout.targeting]] +name = "legacyRuleV0" +query = 'beta eq "true"' + +[scheduled-flag.scheduledRollout.targeting.percentage] +variationA = 0 +variationB = 100 + +[[scheduled-flag.scheduledRollout]] +date = 2022-05-12T13:36:00.100Z + +[[scheduled-flag.scheduledRollout.targeting]] +name = "legacyRuleV0" +query = 'beta eq "false"' +# highlight-end +``` + + + + +## Configuration fields + +:::info +You can change any fields that are available on your flag. +Since your configuration has not been changed manually, it does not trigger any notifier. +::: + +| Field | Description | +|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **`steps`** | The only mandatory field in a **step** is the `date`.
**If no date is provided the step will be skipped.**

The other attributes of your `step` are what you want to update your flag, so every field available in the [flag format](../flag_format) can be updated.
The new value in a field will override the existing one. | diff --git a/website/versioned_docs/version-v1.24.1/configure_flag/rule_format.md b/website/versioned_docs/version-v1.24.1/configure_flag/rule_format.md new file mode 100644 index 00000000000..079556c2132 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/configure_flag/rule_format.md @@ -0,0 +1,159 @@ +--- +sidebar_position: 21 +description: How to create a rule to target specific users +--- + +# How to target specific users + +## Rule format + +A rule is a configuration that allows to serve a variation based on some conditions. + +### Format details + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
name
(optional)
Name of your rule.
This is needed when your are updating a rule using a scheduled rollout.
query +

+ Query represents an antlr query in the nikunjy/rules format. +
This field is mandatory in every rule used in the targeting field. +

+

See query format to have the syntax.

+

Note: if you use the field query in a defaultRule it will be ignored.

+
variation
(optional)
Name of the variation to return.
percentage
(optional)
+

Represents the percentage we should give to each variation.

+
+            percentage:
variationA: 10.59
variationB: 9.41
variationC: 80 +
+

The format is the name of the variation and the percentage for this one.

+

Note: If your total is not equal to 100%, this rule will be considered invalid.

+
progressiveRollout
(optional)
+

+ Allows you to ramp up the percentage of your flag over time. +

+

+ You can decide at which percentage you start and end with in your release ramp. + Before the start date we will serve the initial percentage and afterwards, we will serve the end percentage. +

+

See progressive rollout to have more info on how to use it.

+
disable
(optional)
+

Set to true if you want to disable the rule.

+

Default: true.

+
+ + +:::info +`variation`, `percentage` and `progressiveRollout` are optional but you **must have at least one of the three**. + +If you have more than one field we will use the first one in the order +`progressiveRollout` > `percentage` > `variation`. +::: + +### Query format + +The rule format is based on the [`nikunjy/rules`](https://github.com/nikunjy/rules) library. + +All the operations can be written in capitalized or lowercase characters (ex: `eq` or `EQ` can be used). +Logical Operations supported are `AND` & `OR`. + +Compare Expression and their definitions (`a|b` means you can use one of either `a` or `b`): + +| Operator | Description | +|:----------:|-----------------------------| +| `eq`, `==` | equals to | +| `ne`, `!=` | not equals to | +| `lt`, `<` | less than | +| `gt`, `>` | greater than | +| `le`, `<=` | less than equal to | +| `ge`, `>=` | greater than equal to | +| `co` | contains | +| `sw` | starts with | +| `ew` | ends with | +| `in` | in a list | +| `pr` | present | +| `not` | not of a logical expression | + +#### Examples + +- Select a specific user: `key eq "example@example.com"` +- Select all identified users: `anonymous ne true` +- Select a user with a custom property: `userId eq "12345"` +- Select on multiple criteria: + *All users with ids finishing by `@test.com` that have the role `backend engineer` in the `pro` environment for the + company `go-feature-flag`* + + ```bash + (key ew "@test.com") and (role eq "backend engineer") and (env eq "pro") and (company eq "go-feature-flag") + ``` + +## Environments + +When you initialise `go-feature-flag` you can set an [environment](../go_module/configuration/#option_environment) for the instance of this SDK. + +```go linenums="1" +ffclient.Init(ffclient.Config{ + // ... + Environment: "prod", + // ... +}) +``` + +When an environment is set, it adds a new field in your user called **`env`** that you can use in your queries. +It means that you can decide to activate a flag only for some **environment**. + +**Example of flag configuration based on the environment:** + +```yaml +my-flag: + variations: + A: "A" + B: "B" + C: "C" + targeting: + - name: Target pre environment + query: env eq "pre" + variation: A + - name: Target pro environment + query: env eq "pro" + variation: B + defaultRule: + variation: C +``` + +## Get the rule name in the metadata + +When you use a rule in your targeting, you can get the name of the rule in the metadata of the variation. +The information on what rule has been used to serve the variation is available in the metadata of the variation in the field called `evaluatedRuleName`. + +If you are interested about this information, you have to name your rules by adding the field `name` in your rule. This name will be extract and added in the `evaluatedRuleName` field of the metadata. diff --git a/website/versioned_docs/version-v1.24.1/configure_flag/store_your_flags.mdx b/website/versioned_docs/version-v1.24.1/configure_flag/store_your_flags.mdx new file mode 100644 index 00000000000..1ad2ded0575 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/configure_flag/store_your_flags.mdx @@ -0,0 +1,128 @@ +--- +sidebar_position: 10 +description: Where to store your flags' configuration? +--- +import {Cards} from '@site/src/components/doc/cardv2'; +import { ConfigCardContent } from "@site/src/components/doc/configCardContent"; +import httplogo from '@site/static/docs/retrievers/http.png'; +import customlogo from '@site/static/docs/retrievers/custom.png'; +import filelogo from '@site/static/docs/retrievers/file.png'; +import githublogo from '@site/static/docs/retrievers/github.png'; +import gitlablogo from '@site/static/docs/retrievers/gitlab.png'; +import googlelogo from '@site/static/docs/retrievers/google.png'; +import s3logo from '@site/static/docs/retrievers/s3.png'; +import k8slogo from '@site/static/docs/retrievers/k8s.png'; +import mongodblogo from '@site/static/docs/retrievers/mongodb.png'; + + +# Where to store your flags' configuration? +**GO Feature Flag** is a tool that makes it easy to implement feature flags in your application. One of the benefits of +using GO Feature Flag is that it is designed to be simple and lightweight. +To achieve this, the solution offers a variety of approach to store your flags' configuration. + +The easiest way to get started with GO Feature Flag is to store your flags' configuration in a file. +For this you can create one or more file(s) _(`YAML`, `TOML` or `JSON`)_ that contain(s) your feature +flags and their values. You can then upload this file(s) where you want, and GO Feature Flag will use it. +The way the solution achieves this is through the use of retrievers, which allow you to load your feature flag +configuration file from various sources. + +**Retrievers** are a core concept in GO Feature Flag. They are responsible for loading your feature flag configuration +from a specified location, such as a file on your local machine or a remote storage service. This allows you to +store your configuration in a location that works best for your workflow. + +**GO Feature Flag** supports a variety of retrievers out of the box, including `S3`, `Google Cloud Storage`, `Github`, +`HTTP`, `Kubernetes config maps`, `Local file` ... +But you can also implement your own custom retriever if needed. + +Using retrievers in **GO Feature Flag** is straightforward. You specify which retriever to use in your configuration +file, along with any required configuration options. GO Feature Flag will then use the specified retriever to load your +configuration and will evaluate your feature flags based on this configuration. + +## Available retrievers + + + }, + { + logoImg: s3logo, + title:"AWS S3", + content: + }, + { + logoImg: googlelogo, + title:"Google Storage", + content: + }, + { + logoImg: httplogo, + title:"HTTP/HTTPS", + content: + }, + { + logoImg: githublogo, + title:"GitHub", + content: + }, + { + logoImg: gitlablogo, + title:"Gitlab", + content: + }, + { + logoImg: filelogo, + title:"Local File", + content: + }, + { + logoImg: mongodblogo, + title:"MongoDB", + content: + }, + { + logoImg: customlogo, + title:"Custom ...", + content: + }, +]} /> + + + +## Using multiple retrievers +Sometimes, you might need to store your feature flags in different locations. +In such cases, you can configure multiple retrievers to retrieve the flags from different sources within your GO Feature +Flag instance. + +To set this up, you need to configure the [`Retrievers`](../go_module/configuration#configuration-fields) field to consume from different retrievers. +What this does is that it calls all the retrievers in parallel and applies them in the order you have provided. + +Keep in mind that if a flag is defined in multiple retrievers, it can be overridden by a later flag. For instance, +if you have a flag named _`my-feature-flag`_ in the first file and another flag with the same name in the second file, the second configuration will take precedence. diff --git a/website/versioned_docs/version-v1.24.1/experimental/_category_.json b/website/versioned_docs/version-v1.24.1/experimental/_category_.json new file mode 100644 index 00000000000..6d9f8d64449 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/experimental/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 200, + "label":"Experimental Features", + "collapsible": true, + "collapsed": true +} diff --git a/website/versioned_docs/version-v1.24.1/experimental/ofrep.md b/website/versioned_docs/version-v1.24.1/experimental/ofrep.md new file mode 100644 index 00000000000..c29f1c8b4e2 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/experimental/ofrep.md @@ -0,0 +1,30 @@ +# OpenFeature Remote Evaluation Protocol (OFREP) + +![Experimental](https://img.shields.io/badge/Status-Experimental-red.svg) +⚠️ Note that this a work in progress and the protocol is subject to change. ⚠️ + +OpenFeature Remote Flag Evaluation Protocol is an API specification for feature flagging that allows the use of generic +providers to connect to any feature flag management systems that supports the protocol. + +Currently, the protocol is in the early stages of development and is not yet ready for production use, but GO Feature Flag +is supporting the protocol and is the first implementation of the protocol. +We are part of the leading team in the protocol, and we try to follow the specification during the early stages of the protocol +to allow people to try it and be able to develop the providers. + +## How to test it? + +The OFREP implementation is part of the GO Feature Flag Relay Proxy. +We have a new API endpoints `/ofrep/v1/evaluate/flags/{key}` and `/ofrep/v1/evaluate/flags` that you can use to test the protocol. + +You just have to start the GO Feature Flag Relay Proxy (starting from version `v1.24.0`) and use the API to evaluate your flags. +For this, follow the instruction on how to use the relay-proxy [here](../relay_proxy/getting_started.md). + +### Want to start even faster? +```shell +curl https://gist.githubusercontent.com/thomaspoignant/181a067291a04bd1fbb55468629625d2/raw/eacfc2ae1036c1cfef669b41ec7b54c119639c0c/goff-proxy.yaml -o goff-proxy.yaml +docker run -p 1031:1031 -v $(pwd)/goff-proxy.yaml:/goff/goff-proxy.yaml thomaspoignant/go-feature-flag:latest +``` + +This will launch a GO Feature Flag Relay Proxy with a configuration file that will retrieve the flags from the test server. + +Swagger is enabled, so you can directly go to http://localhost:1031/swagger/index.html to test the OFREP endpoints (the API Key to use is `apikey1`). diff --git a/website/versioned_docs/version-v1.24.1/faq.md b/website/versioned_docs/version-v1.24.1/faq.md new file mode 100644 index 00000000000..18da7977bca --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/faq.md @@ -0,0 +1,52 @@ +--- +sidebar_position: 100 +--- +# Frequently Asked Questions + +### Why Use Feature Flags? +This one of most common question I get. +Feature flags are a software development technique that allows the toggling of specific functionalities on and off at runtime without the need to deploy new code. + +It allows you to decouple **deploy** and **release**, giving you better control and more experimentation over the full lifecycle of features. + +--- + +### What is the lifecycle of a flag? +Managing the lifecycle of feature flags is crucial to prevent cluttering your codebase with obsolete elements. Here's a step-by-step guide: + +1. **Creation**: Initiate by adding the flag to your configuration file, setting it to 0% to avoid impacting users. +2. **Evaluation**: Implement the flag evaluation in your code (refer to [variation](./go_module/target_user.md#variation)). +3. **Deployment**: Deploy your application with the variation check in place. +4. **Rollout**: Gradually enable the flag for users. +5. **Completion**: Once the feature reaches 100% visibility, eliminate the variation call from your code. +6. **Clean-Up**: Deploy your application sans the variation check. +7. **Removal**: Finally, delete the flag from your configuration file. + +--- + +### What happens if my configuration file is not reachable/deleted? +If while you are on production and for some reason your flag file becomes unreachable, we will be able to serve the users based on the last version of the file we were able to read. We will continue to try reading the file based on the `pollingInterval` you have configured. + +If you start a new instance and the file is not reachable to module, it will fail to initialize except if you have set the option `StartWithRetrieverError` in the config. With this option, we will serve the SDK the default value *(the 3rd param in your variation)* until the flag becomes available again. + +--- + +### What is the best rollout strategy? +The lib offers numerous rollout strategies, with no single "best" approach as it heavily depends on the context of your feature release. +Some strategies include: + +- **Simple Cut-Off**: For non-critical releases, transitioning the flag from 0% to 100% immediately for all users might be suitable. +- **Progressive Rollout**: For releases that might impact infrastructure, a gradual rollout can mitigate risks by incrementally increasing user exposure. +- **Targeted Release**: To affect only a specific user segment, applying rules to your flag can be effective. + +You have an endless list of rollout strategies depending on what is your feature. + +--- + +### How do we ensure that users affected by the feature flags are not always the same? + +To avoid always have the same users getting affected by a flag, we compute the hash that allows us to determine if the user is part of the percentage that is not computed only based on the user key but a combination of the user key and the flag name. + +It guarantees that the user will be always in the same group but depending on the flag. + +--- diff --git a/website/versioned_docs/version-v1.24.1/getting_started/_category_.json b/website/versioned_docs/version-v1.24.1/getting_started/_category_.json new file mode 100644 index 00000000000..3bbc107bfb3 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/getting_started/_category_.json @@ -0,0 +1,12 @@ +{ + "position": 10, + "label":"Getting Started", + "collapsible": true, + "collapsed": true, + "link": { + "type": "generated-index", + "title": "Getting Started", + "description": "GO Feature Flag can be used in 2 different ways. You can use it as a GO module directly inside your code or by using an Open-feature SDK. To use the Open-feature SDKs, you will need to deploy a relay proxy inside your architecture." + + } +} diff --git a/website/versioned_docs/version-v1.24.1/getting_started/using-go-module.md b/website/versioned_docs/version-v1.24.1/getting_started/using-go-module.md new file mode 100644 index 00000000000..736dc4db918 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/getting_started/using-go-module.md @@ -0,0 +1,62 @@ +--- +sidebar_position: 20 +description: Use the module in your GO application with nothing to install. +--- +# Using the GO module + +## Installation +```bash +go get github.com/thomaspoignant/go-feature-flag +``` + +## Create a feature flag configuration + +Create a new `YAML` file containing your first flag configuration. + +```yaml title="flag-config.goff.yaml" +# 20% of the users will use the variation "my-new-feature" +test-flag: + variations: + my-new-feature: true + my-old-feature: false + defaultRule: + percentage: + my-new-feature: 20 + my-old-feature: 80 +``` + +This flag split the usage of this flag, 20% will use the variation `my-new-feature` and 80% the variation `my-old-feature`. + +## SDK Initialisation +First, you need to initialize the `ffclient` with the location of your backend file. +```go linenums="1" +err := ffclient.Init(ffclient.Config{ + PollingInterval: 3 * time.Second, + Retriever: &fileretriever.Retriever{ + Path: "flag-config.goff.yaml", + }, +}) +defer ffclient.Close() +``` +*This example will load a file from your local computer and will refresh the flags every 3 seconds (if you omit the +PollingInterval, the default value is 60 seconds).* + +:::tip +This is a basic configuration to test locally, in production it is better to use a remote place to store your feature flag configuration file. + +Look at the list of available options in the [**Store your feature flag file** page](../go_module/store_file/). +::: + +## Evaluate your flags +Now you can evaluate your flags anywhere in your code. + +```go linenums="1" +user := ffcontext.NewEvaluationContext("user-unique-key") +hasFlag, _ := ffclient.BoolVariation("test-flag", user, false) +if hasFlag { + // flag "test-flag" is true for the user +} else { + // flag "test-flag" is false for the user +} +``` +You can find more examples in the [examples/](https://github.com/thomaspoignant/go-feature-flag/tree/main/examples) directory. diff --git a/website/versioned_docs/version-v1.24.1/getting_started/using-openfeature.md b/website/versioned_docs/version-v1.24.1/getting_started/using-openfeature.md new file mode 100644 index 00000000000..f98836d08a8 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/getting_started/using-openfeature.md @@ -0,0 +1,130 @@ +--- +sidebar_position: 10 +description: Deploy the relay proxy and use the OpenFeature SDKs +--- +# Using Open Feature SDKs + +:::note +OpenFeature provides a shared, standardized feature flagging client - _an SDK_ - which can be plugged into various 3rd-party feature flagging providers. +Whether you're using an open-source system or a commercial product, whether it's self-hosted or cloud-hosted, OpenFeature provides a consistent, unified API for developers to use feature flagging in their applications. +_[Documentation](https://docs.openfeature.dev)_ +::: + +GO Feature Flag believes in **Open-Source** and **standardization**, this is the reason why we have decided not implementing any custom SDK and rely only on **Open Feature**. + +To be compatible with Open Feature, **GO Feature Flag** is providing a lightweight self-hosted API server *(called [relay proxy](../relay_proxy))* that is using the GO Feature Flag module internally. +When the **relay proxy** is running in your infrastructure, you can use the **Open Feature SDKs** in combination with **GO Feature Flag providers** to evaluate your flags. + +This schema is an overview on how **Open Feature** is working, you can have more information about all the concepts in the **[Open Feature documentation](https://docs.openfeature.dev)**. +![](/docs/openfeature/concepts.jpg) + +## Create a feature flag configuration + +Create a new `YAML` file containing your first flag configuration. + +```yaml title="flag-config.goff.yaml" +# only admins will eval to true +flag-only-for-admin: + variations: + is-admin: true + not-admin: false + defaultRule: + variation: not-admin + targeting: + - name: check admin + query: admin eq true + variation: is-admin +``` + +This flag split users in 2 groups. Those who were configured with `admin` attribute set to `true` will resolve to the variation `is-admin`. Otherwise, they will resolve to variation `not-admin`. + +## Create a relay proxy configuration file + +Create a new `YAML` file containing the configuration of your relay proxy. + +```yaml title="goff-proxy.yaml" +listen: 1031 +pollingInterval: 1000 +startWithRetrieverError: false +retriever: + kind: file + path: /goff/flag-config.goff.yaml +exporter: + kind: log +``` + +## Install the relay proxy + +We will run the **relay proxy** locally to make the API available. +The default port will be `1031`. + +```shell +# Launch the container +docker run \ + -p 1031:1031 \ + -v $(pwd)/flag-config.goff.yaml:/goff/flag-config.goff.yaml \ + -v $(pwd)/goff-proxy.yaml:/goff/goff-proxy.yaml \ + thomaspoignant/go-feature-flag-relay-proxy:latest + +``` + +_If you don't want to use docker to install the **relay proxy** you can follow the [documentation](../relay_proxy/install_relay_proxy.md)_. + +## Use Open Feature SDK + +_In this example we are using the javascript SDK, but it is still relevant for all the languages_. + +### Install dependencies + +```shell +npm i @openfeature/server-sdk @openfeature/go-feature-flag-provider +``` + +### Init your Open Feature client + +In your app initialization you have to create a client using the Open Feature SDK and initialize it. + +```javascript +const {OpenFeature} = require("@openfeature/server-sdk"); +const {GoFeatureFlagProvider} = require("@openfeature/go-feature-flag-provider"); + + +// init Open Feature SDK with GO Feature Flag provider +const goFeatureFlagProvider = new GoFeatureFlagProvider({ + endpoint: 'http://localhost:1031/' // DNS of your instance of relay proxy +}); +// Sets the default feature flag provider +OpenFeature.setProvider(goFeatureFlagProvider); +// Gets the client that is bound to default provider +const featureFlagClient = OpenFeature.getClient(); +``` + +### Evaluate your flag + +Now you can evaluate your flags anywhere in your code using this client. + +```javascript +// Context of your flag evaluation. +// With GO Feature Flag you MUST have a targetingKey that is a unique identifier of the user. +const userContext = { + targetingKey: '1d1b9238-2591-4a47-94cf-d2bc080892f1', // user unique identifier (mandatory) + firstname: 'john', + lastname: 'doe', + email: 'john.doe@gofeatureflag.org', + admin: true, // this field is used in the targeting rule of the flag "flag-only-for-admin" + // ... +}; + +(async () => { + const adminFlag = await featureFlagClient.getBooleanValue('flag-only-for-admin', false, userContext); + if (adminFlag) { + // flag "flag-only-for-admin" is true for the user + console.log("new feature for admin!"); + } else { + // flag "flag-only-for-admin" is false for the user + console.log("not an admin, no feature"); + } +})(); +``` + +Try changing the `admin` attribute in the `userContext` from `true` to `false` to see different executions flows running. diff --git a/website/versioned_docs/version-v1.24.1/go_module/_category_.json b/website/versioned_docs/version-v1.24.1/go_module/_category_.json new file mode 100644 index 00000000000..1cfccab866c --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/_category_.json @@ -0,0 +1,10 @@ +{ + "position": 60, + "label":"Use as a GO module", + "collapsible": true, + "collapsed": true, + "link": { + "type": "generated-index", + "title": "Use as a GO module" + } +} diff --git a/website/versioned_docs/version-v1.24.1/go_module/configuration.md b/website/versioned_docs/version-v1.24.1/go_module/configuration.md new file mode 100644 index 00000000000..7e2a0a8a1fa --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/configuration.md @@ -0,0 +1,100 @@ +--- +sidebar_position: 10 +description: How to configure the GO module to use it directly in your code. +--- + +# Configuration +`go-feature-flag` needs to be initialized to be used. +During the initialization you must give a [`ffclient.Config{}`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#Config) configuration object. + +[`ffclient.Config{}`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#Config) is the only location where you can put the configuration. + +## Configuration fields + +| Field | Description | +|-------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Retriever` | The configuration retriever you want to use to get your flag file
*See [Store your flag file](./store_file/index.md) for the configuration details*.

*This field is optional if `Retrievers`* is configured. | +| `Retrievers` | `Retrievers` is exactly the same thing as `Retriever` but you can configure more than 1 source for your flags.
All flags are retrieved in parallel, but we are applying them in the order you provided them _(it means that a flag can be overridden by another flag)_.
*See [Store your flag file](./store_file/index.md) for the configuration details*.

*This field is optional if `Retrievers`* is configured. | +| `Context` | *(optional)*
The context used by the retriever.
Default: **`context.Background()`** | +| `Environment` | *(optional)*
The environment the app is running under, can be checked in feature flag rules.
Default: `""`
*Check [**"environments"** section](../configure_flag/flag_format/#environments) to understand how to use this parameter.* | +| `DataExporter` | *(optional)*
DataExporter defines the method for exporting data on the usage of your flags.
*see [export data section](data_collection/index.md) for more details*. | +| `FileFormat` | *(optional)*
Format of your configuration file. Available formats are `yaml`, `toml` and `json`, if you omit the field it will try to unmarshal the file as a `yaml` file.
Default: **`YAML`** | +| `Logger` | *(optional)*
Logger is used to log what `go-feature-flag` is doing.
If no logger is provided the module will not log anything.
Default: **No log** | +| `Notifiers` | *(optional)*
List of notifiers to call when your flag file has been changed.
*See [notifiers section](./notifier/index.md) for more details*. | +| `PollingInterval` | (optional) Duration to wait before refreshing the flags.
The minimum polling interval is 1 second.
Default: **60 * time.Second** | +| `EnablePollingJitter` | (optional) Set to true if you want to avoid having true periodicity when retrieving your flags. It is useful to avoid having spike on your flag configuration storage in case your application is starting multiple instance at the same time.
We ensure a deviation that is maximum ±10% of your polling interval.
Default: **false** | +| `StartWithRetrieverError` | *(optional)* If **true**, the SDK will start even if we did not get any flags from the retriever. It will serve only default values until the retriever returns the flags.
The init method will not return any error if the flag file is unreachable.
Default: **false** | +| `Offline` | *(optional)* If **true**, the SDK will not try to retrieve the flag file and will not export any data. No notifications will be sent either.
Default: **false** | +| `EvaluationContextEnrichment` | *(optional)* It is a free `map[string]interface{}` field that will be merged with the evaluation context sent during the evaluations. It is useful to add common attributes to all the evaluation, such as a server version, environment, ...
All those fields will be included in the custom attributes of the evaluation context.
If in the evaluation context you have a field with the same name, it will be overriden by the `evaluationContextEnrichment`.
Default: **nil** | + +## Example +```go +ffclient.Init(ffclient.Config{ + PollingInterval: 3 * time.Second, + Logger: log.New(file, "/tmp/log", 0), + Context: context.Background(), + Environment: os.Getenv("MYAPP_ENV"), + Retriever: &fileretriever.Retriever{Path: "testdata/flag-config.goff.yaml"}, + FileFormat: "yaml", + Notifiers: []notifier.Notifier{ + &webhooknotifier.Notifier{ + EndpointURL: " https://example.com/hook", + Secret: "Secret", + Meta: map[string]string{ + "app.name": "my app", + }, + }, + }, + DataExporter: ffclient.DataExporter{ + FlushInterval: 10 * time.Second, + MaxEventInMemory: 1000, + Exporter: &file.Exporter{ + OutputDir: "/output-data/", + }, + }, + StartWithRetrieverError: false, +}) +``` + +## Multiple configuration flag files +`go-feature-flag` comes ready to use out of the box by calling the `Init` function and, it will be available everywhere. +Since most applications will want to use a single central flag configuration, the package provides this. It is similar to a singleton. + +In all the examples above, they demonstrate using `go-feature-flag` in its singleton style approach. + +### Working with multiple go-feature-flag + +You can also create many `go-feature-flag` clients to use in your application. + +Each will have its own unique set of configurations and flags. Each can read from a different config file and from different places. +All the functions that `go-feature-flag` package supports are mirrored as methods on a [`GoFeatureFlag`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#GoFeatureFlag). + +#### Example + +```go showLineNumbers +x, err := ffclient.New(Config{ Retriever: &httpretriever.Retriever{{URL: "http://example.com/flag-config.goff.yaml",}}) +defer x.Close() + +y, err := ffclient.New(Config{ Retriever: &httpretriever.Retriever{{URL: "http://example.com/test2.goff.yaml",}}) +defer y.Close() + +user := ffcontext.NewEvaluationContext("user-key") +x.BoolVariation("test-flag", user, false) +y.BoolVariation("test-flag", user, false) + +// ... +``` + +When working with multiple [`GoFeatureFlag`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#GoFeatureFlag), it is up to the user to keep track of different [`GoFeatureFlag`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#GoFeatureFlag) instances. + +## Offline mode +In some situations, you might want to stop making remote calls and fall back to default values for your feature flags. +For example, if your software is both cloud-hosted and distributed to customers to run on-premise, it might make sense +to fall back to defaults when running on-premise. + +You can do this by setting `Offline` mode in the client's Config. + +## Advanced configuration + +- [Export data from your flag variations](./data_collection/index.md) +- [Be notified when your flags change](./notifier/index.md) diff --git a/website/versioned_docs/version-v1.24.1/go_module/data_collection/_category_.json b/website/versioned_docs/version-v1.24.1/go_module/data_collection/_category_.json new file mode 100644 index 00000000000..31a74b81af7 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/data_collection/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 40, + "collapsible": true, + "collapsed": true +} diff --git a/website/versioned_docs/version-v1.24.1/go_module/data_collection/custom.md b/website/versioned_docs/version-v1.24.1/go_module/data_collection/custom.md new file mode 100644 index 00000000000..d747728b497 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/data_collection/custom.md @@ -0,0 +1,24 @@ +--- +sidebar_position: 30 +--- + +# Custom exporter +To create a custom exporter you must have a `struct` that implements the [`exporter.Exporter`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/internal/exporter#Exporter) interface. + + +```go +type Exporter interface { + // Export will send the data to the exporter. + Export(context.Context, *log.Logger, []exporter.FeatureEvent) error + + // IsBulk return false if we should directly send the data as soon as it is produced + // and true if we collect the data to send them in bulk. + IsBulk() bool +} +``` +`Export` is called asynchronously with a list of `exporter.FeatureEvent` that have been collected. +It is your responsibility to store them where you want. + +`IsBulk` function should return `false` if the exporter can handle the results in stream mode. +If you decide to manage it in streaming mode, everytime we call a variation the `Export` function will be called +with only on event in the list. diff --git a/website/versioned_docs/version-v1.24.1/go_module/data_collection/file.md b/website/versioned_docs/version-v1.24.1/go_module/data_collection/file.md new file mode 100644 index 00000000000..1e16c602575 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/data_collection/file.md @@ -0,0 +1,38 @@ +--- +sidebar_position: 3 +--- + +# File Exporter +The file exporter will collect the data and create a new file in a specific folder everytime we send the data. +This file should be in the local instance. + +Check this [complete example](https://github.com/thomaspoignant/go-feature-flag/tree/main/examples/data_export_file) to see how to export the data in a file. + +## Configuration example +```go showLineNumbers +ffclient.Config{ + // ... + DataExporter: ffclient.DataExporter{ + // ... + Exporter: &fileexporter.Exporter{ + OutputDir: "/output-data/", + Format: "csv", + FileName: "flag-variation-{{ .Hostname}}-{{ .Timestamp}}.{{ .Format}}", + CsvTemplate: "{{ .Kind}};{{ .ContextKind}};{{ .UserKey}};{{ .CreationDate}};{{ .Key}};{{ .Variation}};{{ .Value}};{{ .Default}};{{ .Source}}\n" + }, + }, + // ... +} +``` + +## Configuration fields + +| Field | Description | +|---|---| +|`OutputDir` | OutputDir is the location of the directory to store the exported files.
It should finish with a `/`. | +|`Format` | _(Optional)_ Format is the output format you want in your exported file.
Available format: **`JSON`**, **`CSV`**, **`Parquet`**.
**Default: `JSON`** | +|`Filename` | _(Optional)_ Filename is the name of your output file.
You can use a templated config to define the name of your exported files.
Available replacements are `{{ .Hostname}}`, `{{ .Timestamp}}` and `{{ .Format}}`
**Default: `flag-variation-{{ .Hostname}}-{{ .Timestamp}}.{{ .Format}}`**| +|`CsvTemplate` | _(Optional)_ CsvTemplate is used if your output format is CSV.
This field will be ignored if you are using format other than CSV.
You can decide which fields you want in your CSV line with a go-template syntax, please check [internal/exporter/feature_event.go](https://github.com/thomaspoignant/go-feature-flag/blob/main/internal/exporter/feature_event.go) to see the available fields.
**Default:** `{{ .Kind}};{{ .ContextKind}};{{ .UserKey}};{{ .CreationDate}};{{ .Key}};{{ .Variation}};{{ .Value}};{{ .Default}}\n` | +| `ParquetCompressionCodec` | _(Optional)_ ParquetCompressionCodec is the parquet compression codec for better space efficiency. [Available options](https://github.com/apache/parquet-format/blob/master/Compression.md)
**Default: `SNAPPY`** |` + +Check the [godoc for full details](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/exporter/fileexporter). diff --git a/website/versioned_docs/version-v1.24.1/go_module/data_collection/google_cloud_storage.md b/website/versioned_docs/version-v1.24.1/go_module/data_collection/google_cloud_storage.md new file mode 100644 index 00000000000..6cf249ba2c0 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/data_collection/google_cloud_storage.md @@ -0,0 +1,46 @@ +--- +sidebar_position: 2 +--- + +# Google Cloud Storage Exporter + +The **Google Cloud Storage exporter** will collect the data and create a new file in a specific folder everytime we send the data. + +Everytime the `FlushInterval` or `MaxEventInMemory` is reached, a new file will be added to Google Cloud Storage. + +:::info +If for some reason the Google Cloud Storage upload failed, we will keep the data in memory and retry to add it the next time we reach `FlushInterval` or `MaxEventInMemory`. +::: + +Check this [complete example](https://github.com/thomaspoignant/go-feature-flag/tree/main/examples/data_export_googlecloudstorage) to see how to export the data in S3. + +## Configuration example +```go showLineNumbers +ffclient.Config{ + // ... + DataExporter: ffclient.DataExporter{ + // ... + Exporter: &gcstorageexporter.Exporter{ + Bucket: "test-goff", + Format: "json", + Path: "yourPath", + Filename: "flag-variation-{{ .Timestamp}}.{{ .Format}}", + Options: []option.ClientOption{}, // Your google cloud SDK options + }, + }, + // ... +} +``` + +## Configuration fields +| Field | Description | +|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Bucket ` | Name of your Google Cloud Storage Bucket. | +| `CsvTemplate` | *(optional)* CsvTemplate is used if your output format is CSV. This field will be ignored if you are using format other than CSV. You can decide which fields you want in your CSV line with a go-template syntax, please check [internal/exporter/feature_event.go](https://github.com/thomaspoignant/go-feature-flag/blob/main/internal/exporter/feature_event.go) to see what are the fields available.
**Default:** `{{ .Kind}};{{ .ContextKind}};{{ .UserKey}};{{ .CreationDate}};{{ .Key}};{{ .Variation}};{{ .Value}};{{ .Default}};{{ .Source}}\n` | +| `Filename` | *(optional)* Filename is the name of your output file. You can use a templated config to define the name of your exported files.
Available replacements are `{{ .Hostname}}`, `{{ .Timestamp}`} and `{{ .Format}}`
Default: `flag-variation-{{ .Hostname}}-{{ .Timestamp}}.{{ .Format}}` | +| `Format` | *(optional)* Format is the output format you want in your exported file. Available formats are **`JSON`**, **`CSV`**, **`Parquet`**. *(Default: `JSON`)* | +| `Options` | *(optional)* An instance of `option.ClientOption` that configures your access to Google Cloud.
Check [this documentation for more info](https://cloud.google.com/docs/authentication). | +| `Path ` | *(optional)* The location of the directory in your bucket. | +| `ParquetCompressionCodec` | *(optional)* ParquetCompressionCodec is the parquet compression codec for better space efficiency. [Available options](https://github.com/apache/parquet-format/blob/master/Compression.md) *(Default: `SNAPPY`)* |` + +Check the [godoc for full details](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/exporter/gcstorageexporter). diff --git a/website/versioned_docs/version-v1.24.1/go_module/data_collection/index.md b/website/versioned_docs/version-v1.24.1/go_module/data_collection/index.md new file mode 100644 index 00000000000..8c27a7368ff --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/data_collection/index.md @@ -0,0 +1,141 @@ +--- +sidebar_position: 0 +--- + +# Export data + +If you want to export data about how your flags are used, you can use the **`DataExporter`**. +It collects all the variations events and can save these events on several locations: + +- [File](file.md) *- create local files with the variation usages.* +- [Log](log.md) *- use your logger to write the variation usages.* +- [S3](s3.md) *- export your variation usages to S3.* +- [Webhook](webhook.md) *- export your variation usages by calling a webhook.* +- [Google Cloud Storage](google_cloud_storage.md) *- export your variation usages by calling a webhook.* +- [Kafka](kafka.md) *- export your variation usages by producing messages to a Kafka topic.* + +If the existing exporter does not work with your system you can extend the system and use a [custom exporter](custom.md). + +## Data format + +Currently, we are supporting only feature events. +They represent individual flag evaluations and are considered "full fidelity" events. + +### Example + +```json showLineNumbers +{ + "kind": "feature", + "contextKind": "anonymousUser", + "userKey": "ABCD", + "creationDate": 1618228297, + "key": "test-flag", + "variation": "Default", + "value": false, + "default": false, + "source": "SERVER" +} +``` + +### Configuration fields + +| Field | Description | +|--------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **`kind`** | The kind for a feature event is feature. A feature event will only be generated if the trackEvents attribute of the flag is set to true. | +| **`contextKind`** | The kind of context which generated an event. This will only be "**anonymousUser**" for events generated on behalf of an anonymous user or the reserved word "**user**" for events generated on behalf of a non-anonymous user. | +| **`userKey`** | The key of the user object used in a feature flag evaluation. | +| **`creationDate`** | When the feature flag was requested at Unix epoch time in milliseconds. | +| **`key`** | The key of the feature flag requested. | +| **`variation`** | The variation of the flag requested. Available values are:
**True**: if the flag was evaluated to True
**False**: if the flag was evaluated to False
**Default**: if the flag was evaluated to Default
**SdkDefault**: if something wrong happened and the SDK default value was used. | +| **`value`** | The value of the feature flag returned by feature flag evaluation. | +| **`source`** | Where the event is generated. This is set to SERVER when the event is evaluated from the relay-proxy and PROVIDER_CACHE when it is evaluated from the cache. +| **`default`** | (Optional) This value is set to true if feature flag evaluation failed, in which case, the value returned is the default value passed to variation. | + +Events are collected and send in bulk to avoid spamming your exporter *(see details in [how to configure data export](#how-to-configure-data-export)*) + +## How to configure data export? + +In your `ffclient.Config` add the `DataExporter` field and configure your export location. + +To avoid spamming your location everytime you have a variation called, `go-feature-flag` is storing in memory all the events and sends them in bulk to the exporter. +You can decide the threshold on when to send the data with the properties `FlushInterval` and `MaxEventInMemory`. The first threshold hit will export the data. + +If there are some flags that you don't want to export, you can use `trackEvents` fields on these specific flags to disable the data export *(see [flag file format](../../configure_flag/flag_format.mdx))*. + +### Example + +```go showLineNumbers +ffclient.Config{ + // ... + DataExporter: ffclient.DataExporter{ + FlushInterval: 10 * time.Second, + MaxEventInMemory: 1000, + Exporter: &fileexporter.Exporter{ + OutputDir: "/output-data/", + }, + }, + // ... +} +``` + +### Configuration fields + +| Field | Description | +|--------------------|-------------| +| `Exporter` | The configuration of the exporter you want to use. All the exporters are available in the `exporter` package. | +| `FlushInterval` | *(optional)*
Time to wait before exporting the data.
**Default: 60 seconds**. | +| `MaxEventInMemory` | *(optional)*
If `MaxEventInMemory` is reach before the `FlushInterval` a intermediary export will be done
**Default: 100000**. | + +## Don't track a flag + +By default, all flags are trackable, and their data is exported. + +If you want to exclude a specific flag from the data export, you can set the property `trackEvents` to `false` on your flag, and you will have no export for it. + +### YAML + +```yaml +test-flag: + percentage: 50 + true: "B" + false: "A" + default: "Default" + trackEvents: false +``` + +### JSON + +
+ JSON example + +```json +{ + "test-flag": { + "percentage": 50, + "true": "B", + "false": "A", + "default": "Default", + # highlight-next-line + "trackEvents": false + } +} +``` + +
+ +### TOML + +
+ TOML example + +```toml +[test-flag] +percentage = 50.0 +true = "B" +false = "A" +default = "Default" +# highlight-next-line +trackEvents = false +``` + +
diff --git a/website/versioned_docs/version-v1.24.1/go_module/data_collection/kafka.md b/website/versioned_docs/version-v1.24.1/go_module/data_collection/kafka.md new file mode 100644 index 00000000000..ace9e6ebd73 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/data_collection/kafka.md @@ -0,0 +1,32 @@ +--- +sidebar_position: 6 +--- + +# Kafka Exporter +The **Kafka exporter** produces messages to a Kafka topic for each event generated. + +## Configuration example +```go +ffclient.Config{ + // ... + DataExporter: ffclient.DataExporter{ + // ... + Exporter: &kafkaexporter.Exporter{ + Settings: kafkaexporter.Settings{ + Topic: "go-feature-flag-events", + Addresses: []string{"cluster1", "cluster2"}, + }, + }, + }, + // ... +} +``` + +## Configuration fields +| Field | Description | +|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Topic ` | Name of the topic to publish messages | +| `Addresses ` | The list of addresses for the Kafka boostrap servers | +| `Config ` | (Optional) An instance of `*sarama.Config` that holds additional settings for the producer, such as timeouts, TLS settings, etc. If not populated, a default will be used by calling `sarama.NewConfig()` | | | + +Check the [godoc for full details](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/exporter/kafkaexporter). diff --git a/website/versioned_docs/version-v1.24.1/go_module/data_collection/log.md b/website/versioned_docs/version-v1.24.1/go_module/data_collection/log.md new file mode 100644 index 00000000000..47a78ad5669 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/data_collection/log.md @@ -0,0 +1,30 @@ +--- +sidebar_position: 5 +--- + +# Log Exporter +The log exporter is here mostly for backward compatibility *(originally every variation were logged, but it can be a lot of data for a default configuration)*. +It will use your logger `ffclient.Config.Logger` to log every variation changes. + +You can configure your output log with the `Format` field. +It uses a [go template](https://golang.org/pkg/text/template/) format. + +## Configuration example +```go showLineNumbers +ffclient.Config{ + // ... + DataExporter: ffclient.DataExporter{ + Exporter: &logsexporter.Exporter{ + LogFormat: "[{{ .FormattedDate}}] user=\"{{ .UserKey}}\", flag=\"{{ .Key}}\", value=\"{{ .Value}}\"", + }, + }, + // ... +} +``` + +## Configuration fields +| Field | Description | +|-------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `LogFormat` | *(optional)*
LogFormat is the [template](https://golang.org/pkg/text/template/) configuration of the output format of your log.
You can use all the key from the `exporter.FeatureEvent` + a key called `FormattedDate` that represents the date with the **RFC 3339** Format.

**Default: `[{{ .FormattedDate}}] user="{{ .UserKey}}", flag="{{ .Key}}", value="{{ .Value}}"`** | + +Check the [godoc for full details](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/exporter/logsexporter). diff --git a/website/versioned_docs/version-v1.24.1/go_module/data_collection/s3.md b/website/versioned_docs/version-v1.24.1/go_module/data_collection/s3.md new file mode 100644 index 00000000000..cd086189312 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/data_collection/s3.md @@ -0,0 +1,52 @@ +--- +sidebar_position: 1 +--- + +# S3 Exporter + +The **S3 exporter** will collect the data and create a new file in a specific folder everytime we send the data. + +Everytime the `FlushInterval` or `MaxEventInMemory` is reached a new file will be added to S3. + +:::info +If for some reason the S3 upload fails, we will keep the data in memory and retry to add the next time we reach `FlushInterval` or `MaxEventInMemory`. +::: + +![export in S3 screenshot](/docs/data_collection/s3-exporter.png) + + +Check this [complete example](https://github.com/thomaspoignant/go-feature-flag/tree/main/examples/data_export_s3) to see how to export the data in S3. + +## Configuration example +```go +awsConfig, _ := config.LoadDefaultConfig(context.Background()) +ffclient.Config{ + // ... + DataExporter: ffclient.DataExporter{ + // ... + Exporter: &s3exporterv2.Exporter{ + Format: "csv", + FileName: "flag-variation-{{ .Hostname}}-{{ .Timestamp}}.{{ .Format}}", + CsvTemplate: "{{ .Kind}};{{ .ContextKind}};{{ .UserKey}};{{ .CreationDate}};{{ .Key}};{{ .Variation}};{{ .Value}};{{ .Default}};{{ .Source}}\n", + Bucket: "my-bucket", + S3Path: "/go-feature-flag/variations/", + Filename: "flag-variation-{{ .Timestamp}}.{{ .Format}}", + AwsConfig: &awsConfig, + }, + }, + // ... +} +``` + +## Configuration fields +| Field | Description | +|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Bucket ` | Name of your S3 Bucket. | +| `AwsConfig ` | An instance of `aws.Config` that configures your access to AWS *(see [this documentation for more info](https://aws.github.io/aws-sdk-go-v2/docs/configuring-sdk/))*. | +| `CsvTemplate` | *(optional)* CsvTemplate is used if your output format is CSV. This field will be ignored if you are using format other than CSV. You can decide which fields you want in your CSV line with a go-template syntax, please check [internal/exporter/feature_event.go](https://github.com/thomaspoignant/go-feature-flag/blob/main/internal/exporter/feature_event.go) to see what are the fields available.
**Default:** `{{ .Kind}};{{ .ContextKind}};{{ .UserKey}};{{ .CreationDate}};{{ .Key}};{{ .Variation}};{{ .Value}};{{ .Default}};{{ .Source}}\n` | +| `Filename` | *(optional)* Filename is the name of your output file. You can use a templated config to define the name of your exported files.
Available replacements are `{{ .Hostname}}`, `{{ .Timestamp}}` and `{{ .Format}}`
Default: `flag-variation-{{ .Hostname}}-{{ .Timestamp}}.{{ .Format}}` | +| `Format` | *(optional)* Format is the output format you want in your exported file. Available formats are **`JSON`**, **`CSV`**, **`Parquet`**. *(Default: `JSON`)* | +| `S3Path ` | *(optional)* The location of the directory in S3. | +| `ParquetCompressionCodec` | *(optional)* ParquetCompressionCodec is the parquet compression codec for better space efficiency. [Available options](https://github.com/apache/parquet-format/blob/master/Compression.md) *(Default: `SNAPPY`)* |` + +Check the [godoc for full details](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/exporter/s3exporterv2). diff --git a/website/versioned_docs/version-v1.24.1/go_module/data_collection/sqs.md b/website/versioned_docs/version-v1.24.1/go_module/data_collection/sqs.md new file mode 100644 index 00000000000..56affe5ce4e --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/data_collection/sqs.md @@ -0,0 +1,31 @@ +--- +sidebar_position: 6 +--- + +# SQS Exporter + +The **SQS exporter** will collect the data and create an event in the queue for each evaluation we receive. + +## Configuration example +```go +ffclient.Config{ + // ... + cfg, _ := config.LoadDefaultConfig(context.TODO()) + DataExporter: ffclient.DataExporter{ + // ... + Exporter: &sqsexporter.Exporter{ + QueueURL: "https://sqs.eu-west-1.amazonaws.com/XXX/test-queue", + AwsConfig: &cfg, + }, + }, + // ... +} +``` + +## Configuration fields +| Field | Description | +|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `QueueURL ` | URL of your SQS queue.
_You can find it in your AWS console._ | +| `AwsConfig ` | An instance of `aws.Config` that configures your access to AWS *(see [this documentation for more info](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html))*. | + +Check the [godoc for full details](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/exporter/sqsexporter). diff --git a/website/versioned_docs/version-v1.24.1/go_module/data_collection/webhook.md b/website/versioned_docs/version-v1.24.1/go_module/data_collection/webhook.md new file mode 100644 index 00000000000..112000510e7 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/data_collection/webhook.md @@ -0,0 +1,75 @@ +--- +sidebar_position: 4 +--- + +# Webhook Exporter + +The **Webhook exporter** will collect the data and send it via an HTTP POST request to the specified endpoint. +Everytime the `FlushInterval` or `MaxEventInMemory` is reached, a new call is performed. + +:::info +If for some reason the call failed, we will keep the data in memory and retry to add the next time we reach `FlushInterval` or `MaxEventInMemory`. +::: + +## Configuration example +```go showLineNumbers +ffclient.Config{ + // ... + DataExporter: ffclient.DataExporter{ + // ... + Exporter: &webhookexporter.Exporter{ + EndpointURL: " https://webhook.url/", + Secret: "secret-for-signing", + Meta: map[string]string{ + "extraInfo": "info", + }, + Headers: map[string][]string{ + "Authorization": {"Bearer auth_token"}, + }, + }, + }, + // ... +} +``` +## Configuration fields +| Field | Description | +|----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `EndpointURL ` | EndpointURL of your webhook | +| `Secret ` | *(optional)*
Secret used to sign your request body and fill the `X-Hub-Signature-256` header.
See [signature section](#signature) for more details. | +| `Meta` | *(optional)*
Add all the information you want to see in your request. | +| `Headers` | *(optional)*
List of Headers to send to the endpoint | + + +## Webhook format +If you have configured a webhook, a `POST` request will be sent to the `EndpointURL` with a body in this format: + +```json +{ + "meta": { + "hostname": "server01", + // ... + }, + "events": [ + { + "kind": "feature", + "contextKind": "anonymousUser", + "userKey": "14613538188334553206", + "creationDate": 1618909178, + "key": "test-flag", + "variation": "Default", + "value": false, + "default": false, + "source": "SERVER" + }, + // ... + ] +} +``` + +## Signature +This header **`X-Hub-Signature-256`** is sent if the webhook is configured with a **`secret`**. +This is the **HMAC hex digest** of the request body, and is generated using the **SHA-256** hash function and the **secret as the HMAC key**. + +:::caution +The recommendation is to always use the `Secret` and on your API/webhook always verify the signature key to be sure that you don't get into a man-in-the-middle attack. +::: diff --git a/website/versioned_docs/version-v1.24.1/go_module/notifier/_category_.json b/website/versioned_docs/version-v1.24.1/go_module/notifier/_category_.json new file mode 100644 index 00000000000..69bc4e31aa2 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/notifier/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 50, + "collapsible": true, + "collapsed": true +} diff --git a/website/versioned_docs/version-v1.24.1/go_module/notifier/custom.md b/website/versioned_docs/version-v1.24.1/go_module/notifier/custom.md new file mode 100644 index 00000000000..f8e2ebcde23 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/notifier/custom.md @@ -0,0 +1,24 @@ +--- +sidebar_position: 30 +--- + +# Custom Notifier + +To create a custom notifier you must have a `struct` that implements the +[`notifier.Notifier`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/notifier/notifier) interface. + +In parameter you will receive a `notifier.DiffCache` struct that will tell you what has changed in your flag configuration. + +```go +import ( + ffclient "github.com/thomaspoignant/go-feature-flag" + "github.com/thomaspoignant/go-feature-flag/notifier/notifier" + "sync" +) + +type Notifier struct{} +func (c *Notifier) Notify(diff notifier.DiffCache) error { + // ... + // do whatever you want here +} +``` diff --git a/website/versioned_docs/version-v1.24.1/go_module/notifier/index.md b/website/versioned_docs/version-v1.24.1/go_module/notifier/index.md new file mode 100644 index 00000000000..3cad29c1332 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/notifier/index.md @@ -0,0 +1,17 @@ +--- +sidebar_position: 1 +--- + +# Notify flag changes +If you want to be informed when a flag has changed, you can configure a [**notifier**](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#NotifierConfig). + +A notifier will send one notification to the targeted system to inform them that a new flag configuration has been loaded. + +:::info +`go-feature-flag` can handle more than one notifier at a time. +::: + +Available notifiers are: + +- [Slack](slack.md) - Get a slack message with the changes. +- [Webhook](webhook.md) - Call an API with the changes. diff --git a/website/versioned_docs/version-v1.24.1/go_module/notifier/slack.md b/website/versioned_docs/version-v1.24.1/go_module/notifier/slack.md new file mode 100644 index 00000000000..4d2f9304f80 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/notifier/slack.md @@ -0,0 +1,33 @@ +--- +sidebar_position: 1 +--- + +# Slack Notifier +The **Slack** notifier allows you to get notification on your favorite slack channel when an instance of `go-feature-flag` is detecting changes in the configuration file. + +
+ +## Configure Slack Notification +1. First, you need to create an incoming webhook on your slack instance. + *You can follow this [documentation to see how to do it](https://api.slack.com/messaging/webhooks#getting_started)* +2. Copy your webhook URL. + It should look like: `https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX`. +3. In your init method add a slack notifier + +```go {5}showLineNumbers +ffclient.Config{ + // ... + Notifiers: []notifier.Notifier{ + &slacknotifier.Notifier{ + SlackWebhookURL: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX", + }, + // ... + }, +} +``` + +### Configuration fields + +| Field | Description | +|---|---| +|`SlackWebhookURL` | The complete URL of your incoming webhook configured in Slack. | diff --git a/website/versioned_docs/version-v1.24.1/go_module/notifier/webhook.md b/website/versioned_docs/version-v1.24.1/go_module/notifier/webhook.md new file mode 100644 index 00000000000..5fdb60a2cf0 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/notifier/webhook.md @@ -0,0 +1,114 @@ +--- +sidebar_position: 2 +--- + +# Webhook Notifier +The **Webhook notifier** will perform an HTTP POST request to the specified endpoint everytime a change in the flags is detected. + +The format of the call is specified in the [format section](#format) and you can [sign the body](#signature) to trust the data you are receiving. + +## Configure the webhook notifier + +```go +ffclient.Config{ + // ... + Notifiers: []notifier.Notifier{ + &webhooknotifier.Notifier{ + EndpointURL: " https://example.com/hook", + Secret: "Secret", + Meta: map[string]string{ + "app.name": "my app", + }, + Headers: map[string][]string{ + "Authorization": {"Bearer auth_token"}, + }, + }, + // ... + }, +} +``` + +## Configuration fields +| Field | Description | +|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `EndpointURL` | The complete URL of your API *(we will send a POST request to this URL, [see format](#format))* | +| `Secret` | *(optional)*
A secret key you can share with your webhook. We will use this key to sign the request *(see [signature section](#signature) for more details)*. | +| `Meta` | *(optional)*
A list of key value that will be added in your request, this is super useful if you want to add information on the current running instance of your app.

**By default the hostname is always added in the meta information.** | +| `Headers` | *(optional)*
The list of Headers to send to the endpoint. | + +## Format +If you have configured a webhook, a `POST` request will be sent to the `EndpointURL` with a body in this format: + +```json +{ + "meta": { + "hostname": "server01", + // ... + }, + "flags": { + "deleted": {}, // map of your deleted flags + "added": {}, // map of your added flags + "updated": { + "flag-name": { // an object that contains old and new value + "old_value": {}, + "new_value": {} + } + } + } +} +``` + +### Example + +```json +{ + "meta":{ + "hostname": "server01" + }, + "flags":{ + "deleted": { + "test-flag": { + "rule": "key eq \"random-key\"", + "percentage": 100, + "true": true, + "false": false, + "default": false + } + }, + "added": { + "test-flag3": { + "percentage": 5, + "true": "test", + "false": "false", + "default": "default" + } + }, + "updated": { + "test-flag2": { + "old_value": { + "rule": "key eq \"not-a-key\"", + "percentage": 100, + "true": true, + "false": false, + "default": false + }, + "new_value": { + "disable": true, + "rule": "key eq \"not-a-key\"", + "percentage": 100, + "true": true, + "false": false, + "default": false + } + } + } + } +} +``` + +## Signature +This header **`X-Hub-Signature-256`** is sent if the webhook is configured with a secret. This is the HMAC hex digest of the request body, and is generated using the SHA-256 hash function and the secret as the HMAC key. + +:::caution +The recommendation is to always use the `Secret` and on your API/webook always verify the signature key to be sure that you don't get into a man-in-the-middle attack. +::: diff --git a/website/versioned_docs/version-v1.24.1/go_module/store_file/_category_.json b/website/versioned_docs/version-v1.24.1/go_module/store_file/_category_.json new file mode 100644 index 00000000000..5a330427a1b --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/store_file/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 30, + "collapsible": true, + "collapsed": true +} diff --git a/website/versioned_docs/version-v1.24.1/go_module/store_file/custom.md b/website/versioned_docs/version-v1.24.1/go_module/store_file/custom.md new file mode 100644 index 00000000000..7f9ac091261 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/store_file/custom.md @@ -0,0 +1,38 @@ +--- +sidebar_position: 30 +--- + +# Custom Retriever + +## Simple retriever +To create a custom retriever you must have a `struct` that implements the [`Retriever`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/retriever/#Retriever) interface. + +```go showLineNumbers +type Retriever interface { + Retrieve(ctx context.Context) ([]byte, error) +} +``` + +The `Retrieve` function is supposed to load the file and to return a `[]byte` of your flag configuration file. + +You can check existing `Retriever` *([file](https://github.com/thomaspoignant/go-feature-flag/blob/main/retriever/fileretriever/retriever.go), +[s3](https://github.com/thomaspoignant/go-feature-flag/blob/main/retriever/s3retriever/retriever.go), ...)* to have an idea on how to do build your own. + +## Initializable retriever +Sometimes you need to initialize your retriever before using it. +For example, if you want to connect to a database, you need to initialize the connection before using it. + +To help you with that, you can use the [`InitializableRetriever`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/retriever/#InitializableRetriever) interface. + +The only difference with the `Retriever` interface is that the `Init` func of your retriever will be called at the start of the application and the `Shutdown` func will be called when closing GO Feature Flag. + +```go +type InitializableRetriever interface { + Retrieve(ctx context.Context) ([]byte, error) + Init(ctx context.Context, logger *log.Logger) error + Shutdown(ctx context.Context) error + Status() retriever.Status +} +``` +To avoid any issue to call the `Retrieve` function before the `Init` function, you have to manage the status of your retriever. +GO Feature Flag will try to call the `Retrieve` function only if the status is `RetrieverStatusReady`. diff --git a/website/versioned_docs/version-v1.24.1/go_module/store_file/file.md b/website/versioned_docs/version-v1.24.1/go_module/store_file/file.md new file mode 100644 index 00000000000..402609fdacc --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/store_file/file.md @@ -0,0 +1,31 @@ +--- +sidebar_position: 25 +--- + +# File +The [**File Retriever**](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/retriever/fileretriever/#Retriever) will read a local file to get your flags. + +:::tip +Using a file to store your flags is not recommend, except if it is in a shared folder for all your services. +::: + +## Example +```go showLineNumbers +import "github.com/thomaspoignant/go-feature-flag/retriever/file" +// ... + +err := ffclient.Init(ffclient.Config{ + PollingInterval: 3 * time.Second, + Retriever: &fileretriever.Retriever{ + Path: "file-example.yaml", + }, +}) +defer ffclient.Close() +``` + +## Configuration fields +To configure your File retriever: + +| Field | Description | +|---|---| +|**`Path`**| location of your file on the file system.| diff --git a/website/versioned_docs/version-v1.24.1/go_module/store_file/github.md b/website/versioned_docs/version-v1.24.1/go_module/store_file/github.md new file mode 100644 index 00000000000..e28bbbd9f7f --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/store_file/github.md @@ -0,0 +1,40 @@ +--- +sidebar_position: 6 +--- + +# GitHub + +The [**GitHub Retriever**](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/retriever/githubretriever/#Retriever) +will perform an HTTP Request with your GitHub configuration to get your flags. + +:::tip +GitHub has rate limits, be sure to correctly set your `PollingInterval` to avoid reaching the limit. +::: + +## Example + +```go showLineNumbers +err := ffclient.Init(ffclient.Config{ + PollingInterval: 3 * time.Second, + Retriever: &githubretriever.Retriever{ + RepositorySlug: "thomaspoignant/go-feature-flag", + Branch: "main", + FilePath: "testdata/flag-config.goff.yaml", + GithubToken: "XXXX", + Timeout: 2 * time.Second, + }, +}) +defer ffclient.Close() +``` + +## Configuration fields + +To configure the access to your GitHub file: + +| Field | Description | +|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **`RepositorySlug`** | Your GitHub slug `org/repo-name`. | +| **`FilePath`** | The path of your file. | +| **`Branch`** | *(optional)*
The branch where your file is.
Default: `main` | +| **`GithubToken`** | *(optional)*
Github token is used to access a private repository, you need the `repo` permission *([how to create a GitHub token](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token))*. | +| **`Timeout`** | *(optional)*
Timeout for the HTTP call
Default: 10 seconds | diff --git a/website/versioned_docs/version-v1.24.1/go_module/store_file/gitlab.md b/website/versioned_docs/version-v1.24.1/go_module/store_file/gitlab.md new file mode 100644 index 00000000000..50aa7745713 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/store_file/gitlab.md @@ -0,0 +1,42 @@ +--- +sidebar_position: 6 +--- + +# GitLab + +The [**GitLab Retriever**](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/retriever/gitlabretriever/#Retriever) +will perform an HTTP Request to the GitLab API to get your flags. + +:::tip +GitLab has rate limits, be sure to correctly set your `PollingInterval` to avoid reaching the limit. +::: + +## Example + +```go showLineNumbers +err := ffclient.Init(ffclient.Config{ + PollingInterval: 3 * time.Second, + Retriever: &gitlab.Retriever{ + RepositorySlug: "thomaspoignant/go-feature-flag", + Branch: "main", + FilePath: "testdata/flag-config.goff.yaml", + GitlabToken: "XXXX", + Timeout: 2 * time.Second, + BaseURL: "https://gitlab.com", + }, +}) +defer ffclient.Close() +``` + +## Configuration fields + +To configure the access to your GitLab file: + +| Field | Description | +|----------------------|-------------------------------------------------------------------------------------------| +| **`BaseURL`** | *(optional)*
The domain name of your Gitlab instance
Default: https://gitlab.com | +| **`RepositorySlug`** | Your Gitlab slug `org/repo-name`. | +| **`FilePath`** | The path of your file. | +| **`Branch`** | *(optional)*
The branch where your file is.
Default: `main` | +| **`GitlabToken`** | *(optional)*
GitLab token is used to access a private repository | +| **`Timeout`** | *(optional)*
Timeout for the HTTP call
Default: 10 seconds | diff --git a/website/versioned_docs/version-v1.24.1/go_module/store_file/google_cloud_storage.md b/website/versioned_docs/version-v1.24.1/go_module/store_file/google_cloud_storage.md new file mode 100644 index 00000000000..23f8c8d5159 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/store_file/google_cloud_storage.md @@ -0,0 +1,31 @@ +--- +sidebar_position: 5 +--- + +# Google Cloud Storage + +The [**Google Cloud Storage Retriever**](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/retriever/gcstorageretriever/#Retriever) will use the [google-cloud-storage package](https://pkg.go.dev/cloud.google.com/go/storage) and [google-api-options package](https://pkg.go.dev/google.golang.org/api/option) to access your flag in Google Cloud Storage. + +## Example + +```go +err := ffclient.Init(ffclient.Config{ + PollingInterval: 3 * time.Second, + Retriever: &gcstorageretriever.Retriever{ + Options: []option.ClientOption{option.WithoutAuthentication()}, + Bucket: "2093u4pkasjc3", + Object: "flags.yaml", + } +}) +defer ffclient.Close() +``` + +## Configuration fields + +To configure your Google Cloud Storage file location: + +| Field | Description | +|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **`Bucket`** | The name of your bucket. | +| **`Object`** | The name of your object in your bucket. | +| **`Option`** | An instance of `option.ClientOption` that configures your access to Google Cloud.
Check [this documentation for more info](https://cloud.google.com/docs/authentication). | diff --git a/website/versioned_docs/version-v1.24.1/go_module/store_file/http.md b/website/versioned_docs/version-v1.24.1/go_module/store_file/http.md new file mode 100644 index 00000000000..1b2da3679d0 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/store_file/http.md @@ -0,0 +1,33 @@ +--- +sidebar_position: 2 +--- + +# HTTP endpoint + +The [__HTTP Retriever__](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/retriever/httpretriever/#Retriever) +will perform an HTTP Request with your configuration to get your flags. + +## Example + +```go showLineNumbers +err := ffclient.Init(ffclient.Config{ + PollingInterval: 3 * time.Second, + Retriever: &httpretriever.Retriever{ + URL: "http://example.com/flag-config.goff.yaml", + Timeout: 2 * time.Second, + }, +}) +defer ffclient.Close() +``` + +## Configuration fields + +To configure your HTTP endpoint: + +| Field | Description | +|---------------|-----------------------------------------------------------------------------------------------------------------| +| __`URL`__ | Location to retrieve the file
_(ex: [http://mydomain.io/flag.yaml](http://mydomain.io/flag.yaml))_. | +| __`Method`__ | the HTTP method you want to use
_(default is GET)_. | +| __`Body`__ | _(optional)_
If you need a body to get the flags. | +| __`Header`__ | _(optional)_
Header you should pass while calling the endpoint _(useful for authorization)_. | +| __`Timeout`__ | _(optional)_
Timeout for the HTTP call
(default is 10 seconds). | diff --git a/website/versioned_docs/version-v1.24.1/go_module/store_file/index.md b/website/versioned_docs/version-v1.24.1/go_module/store_file/index.md new file mode 100644 index 00000000000..5c7ae2ab90c --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/store_file/index.md @@ -0,0 +1,18 @@ +--- +sidebar_position: 1 +--- + +# Retrieve your feature flags configuration +The module supports different ways of retrieving the flag file. +Available retrievers are: + +- [S3 Bucket](./s3.md) +- [HTTP endpoint](./http.md) +- [Github](./github.md) +- [Gitlab](./gitlab.md) +- [File](./file.md) +- [Kubernetes configmap](./kubernetes_configmaps.md) +- [Google Cloud storage](./google_cloud_storage.md) + +To retrieve a file you need to provide a [retriever](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/retriever/#Retriever) in your `ffclient.Config{}` during the initialization. +If the existing retriever does not work with your system you can extend the system and use a [custom retriever](custom.md). diff --git a/website/versioned_docs/version-v1.24.1/go_module/store_file/kubernetes_configmaps.md b/website/versioned_docs/version-v1.24.1/go_module/store_file/kubernetes_configmaps.md new file mode 100644 index 00000000000..75806bb6e5e --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/store_file/kubernetes_configmaps.md @@ -0,0 +1,47 @@ +--- +sidebar_position: 4 +--- + +# Kubernetes configmaps +A ConfigMap is an API object used to store non-confidential data in key-value pairs inside kubernetes. +GO Feature Flag can read directly in a configmap in your namespace. + +The [**Kubernetes Retriever**](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/retriever/k8sretriever/#Retriever) +will access flags in a Kubernetes ConfigMap via the [Kubernetes Go Client](https://github.com/kubernetes/client-go). + + +## Add your config file as configmap + +```shell +kubectl create configmap goff --from-file=examples/retriever_configmap/flags.yaml +``` + +## Configuration Example +```go showLineNumbers +import ( + restclient "k8s.io/client-go/rest" +) + +config, _ := restclient.InClusterConfig() +err = ffclient.Init(ffclient.Config{ + PollingInterval: 3 * time.Second, + Retriever: &k8sretriever.Retriever{ + Path: "file-example.yaml", + Namespace: "default" + ConfigMapName: "my-configmap" + Key: "somekey.yml" + ClientConfig: &config + }, +}) +defer ffclient.Close() +``` + +## Configuration fields +To configure your retriever: + +| Field | Description | +|---------------------|----------------------------------------------------| +| **`Namespace`** | The namespace of the ConfigMap. | +| **`ConfigMapName`** | The name of the ConfigMap. | +| **`Key`** | The key within the ConfigMap storing the flags. | +| **`ClientConfig`** | The configuration object for the Kubernetes client | diff --git a/website/versioned_docs/version-v1.24.1/go_module/store_file/mongodb.md b/website/versioned_docs/version-v1.24.1/go_module/store_file/mongodb.md new file mode 100644 index 00000000000..dae6c6c94b7 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/store_file/mongodb.md @@ -0,0 +1,55 @@ +--- +sidebar_position: 7 +--- + +# MongoDB +The `mongodbRetriever` will use the mongoDB database to get your flags. + +## Example +```go linenums="1" +awsConfig, _ := config.LoadDefaultConfig(context.Background()) +err := ffclient.Init(ffclient.Config{ + PollingInterval: 3 * time.Second, + Retriever: &mongodbretriever.Retriever{ + Collection: "featureFlags", + Database: "appConfig", + URI: "mongodb://root:example@127.0.0.1:27017/", + }, +}) +defer ffclient.Close() +``` + +## Expected format +If you use MongoDB to store your flags, you need a specific format to store your flags. + +We expect the flag to be stored in JSON format as defined in the [flag format](../../configure_flag/flag_format#format-details), +but you should also add a new field called `flag` containing the name of the flag. + +The retriever will read all the flags from the collection. + +### Example: +```json +{ + "flag": "new-admin-access", + "variations": { + "default_var": false, + "false_var": false, + "true_var": true + }, + "defaultRule": { + "percentage": { + "false_var": 70, + "true_var": 30 + } + } +} +``` + +## Configuration fields +To configure your mongodb retriever: + +| Field | Description | +|------------------|-------------------------------------------------------------| +| **`Collection`** | Name of the collection where your flags are stored | +| **`Database`** | Name of the mongo database where the collection is located. | +| **`URI`** | Connection URI of your mongoDB instance. | diff --git a/website/versioned_docs/version-v1.24.1/go_module/store_file/s3.md b/website/versioned_docs/version-v1.24.1/go_module/store_file/s3.md new file mode 100644 index 00000000000..c339b0ddc11 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/store_file/s3.md @@ -0,0 +1,33 @@ +--- +sidebar_position: 3 +--- + +# S3 Bucket +The [**S3 Retriever v2**](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag@v1.23.1/retriever/s3retrieverv2) will use the [aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) to access your flag in an S3 bucket. + +The [**S3 Retriever v1**](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag@v1.23.1/retriever/s3retriever) will use the deprecated [aws-sdk-go](https://github.com/aws/aws-sdk-go) to access your flag in an S3 bucket. + +[AWS has announce end-of-support for AWS SDK for Go v1](https://aws.amazon.com/blogs/developer/announcing-end-of-support-for-aws-sdk-for-go-v1-on-july-31-2025/), and it's recommended to migrate from S3 Retriever v1 to v2. + +## Example +```go showLineNumbers +awsConfig, _ := config.LoadDefaultConfig(context.Background()) +err := ffclient.Init(ffclient.Config{ + PollingInterval: 3 * time.Second, + Retriever: &s3retrieverv2.Retriever{ + Bucket: "tpoi-test", + Item: "flag-config.goff.yaml", + AwsConfig: &awsConfig, + }, +}) +defer ffclient.Close() +``` + +## Configuration fields +To configure your S3 file location: + +| Field | Description | +|-----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **`Bucket`** | The name of your bucket. | +| **`Item`** | The location of your file in the bucket. | +| **`AwsConfig`** | An instance of `aws.Config` that configure your access to AWS
*check [this documentation for more info](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html)*. | diff --git a/website/versioned_docs/version-v1.24.1/go_module/target_user.md b/website/versioned_docs/version-v1.24.1/go_module/target_user.md new file mode 100644 index 00000000000..8d2a274840b --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/go_module/target_user.md @@ -0,0 +1,185 @@ +--- +sidebar_position: 20 +description: How to select who should have the flag activated. +--- +# Performing flag evaluations + +## Users +Feature flag targeting and rollouts are all determined by the user you pass to your **Variation** calls. +The SDK defines a [`User`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/ffuser#User) struct and a [`UserBuilder`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/ffuser#UserBuilder) to make this easy. + +Here's an example: + +```go showLineNumbers +// User with only a key +user1 := ffcontext.NewEvaluationContext("user1-key") + +// User with a key plus other attributes +user2 = ffcontext.NewEvaluationContextBuilder("user2-key"). + AddCustom("firstname", "John"). + AddCustom("lastname", "Doe"). + AddCustom("email", "john.doe@example.com"). + Build() +``` + +The most common attribute is the user's key and **this is the only mandatory user attribute.** +The key should also uniquely identify each user. You can use a primary key, an e-mail address, or a hash, as long as the same user always has the same key. +**We recommend using a hash if possible.** +All the other attributes are optional. + +:::info +Custom attributes are one of the most powerful features. +They let you have rules on these attributes and target users according to any data that you want. +::: + +## Anonymous users +You can also distinguish logged-in users from anonymous users in the SDK, as follows: + +```go showLineNumbers +// User with only a key +user1 := ffcontext.NewAnonymousEvaluationContext("user1-key") + +// User with a key plus other attributes +user2 = ffcontext.NewEvaluationContextBuilder("user2-key"). + Anonymous(true). + AddCustom("firstname", "John"). + AddCustom("lastname", "Doe"). + AddCustom("email", "john.doe@example.com"). + Build() +``` +You will still need to generate a unique key for anonymous users. Session IDs or UUIDs work best for this. + +Anonymous users work just like regular users, this information just helps you to add a rule to target a specific population. + +## Variation +The Variation methods determine whether a flag is enabled or not for a specific user. +There is a Variation method for each type: +[`BoolVariation`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#BoolVariation) , [`IntVariation`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#IntVariation) +, [`Float64Variation`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#Float64Variation) +, [`StringVariation`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#StringVariation) +, [`JSONArrayVariation`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#JSONArrayVariation) +, [`JSONVariation`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#JSONVariation) + +```go showLineNumbers +result, _ := ffclient.BoolVariation("your.feature.key", user, false) + +// result is now true or false depending on the setting of +// this boolean feature flag +``` +Variation methods take the feature **flag key**, a **user**, and a **default value**. + +The default value is returned when an error is encountered _(`ffclient` not initialized, variation with wrong type, flag does not exist ...)._ + +In the example, if the flag `your.feature.key` does not exist, result will be `false`. +Not that you will always have a usable value in the result. + +## Variation details +If you want more information about your flag evaluation, you can use the variation details functions. +There is a Variation method for each type: +[`BoolVariationDetails`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#BoolVariationDetails) +, [`IntVariation`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#IntVariationDetails) +, [`Float64VariationDetails`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#Float64VariationDetails) +, [`StringVariationDetails`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#StringVariationDetails) +, [`JSONArrayVariationDetails`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#JSONArrayVariationDetails) +, [`JSONVariationDetails`](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag#JSONVariationDetails) + +You can use these functions the same way as the other variation functions BUT it will return a generic object `model.VariationResult[]` containing your result. +This object will contain these fields: + +| field | type | description | +|-----------------|-------------------------|--------------------------------------------------------------------------------| +| `TrackEvents` | `bool` | `true` if this evaluation was tracked. | +| `VariationType` | `string` | The name of the variation used to get this value. | +| `Failed` | `bool` | `true` if an error occurred during the evaluation. | +| `Version` | `string` | The **version** of the flag used to do the evaluation. | +| `Reason` | `flag.ResolutionReason` | The reason used for this evaluation. | +| `ErrorCode` | `flag.ErrorCode` | Error code in case we have an error. | +| `Value` | `` | Value of the flag in the expected type. | +| `Cacheable` | `bool` | `true` if it can be cached (by user or for everyone depending on the reason). | + + +### Reason +GO Feature Flag can furnish you with diverse reasons in the variation details, giving you insight into the evaluation process of your feature flag. +Here is the full list of reason available: + +| Reason | description | +|-------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `TARGETING_MATCH` | The resolved value was the result of a dynamic evaluation, such as a rule or specific user-targeting. _(ex: serve variation A if username is Thomas)_ | +| `TARGETING_MATCH_SPLIT` | The resolved value was the result of a dynamic evaluation, that is serving a percentage. _(ex: serve variation A to 10% of users with the username Thomas)_ | +| `SPLIT` | The resolved value was the result of pseudorandom assignment. _(ex: serve variation A to 10% of all the users.)_ | +| `DISABLED` | Indicates that the feature flag is disabled | +| `DEFAULT` | The resolved value was the result of the flag being disabled in the management system. | +| `STATIC` | Indicates that the feature flag evaluated to a static value, for example, the default value for the flag. _(Note: Typically means that no dynamic evaluation has been executed for the feature flag)_ | +| `UNKNOWN` | Indicates that an unknown issue occurred during evaluation | +| `ERROR` | Indicates that an error occurred during evaluation *(Note: The `errorCode` field contains the details of this error)* | +| `OFFLINE` | Indicates that GO Feature Flag is currently evaluating in offline mode. | + + +## Get all flags for a specific user +If you want to send the information about a specific user to the front-end, you will need a snapshot of all the flags of this user at a specific time. + +The method `ffclient.AllFlagsState` returns a snapshot of flag values and metadata. +The function is evaluating all available flags for the user and returns a `flagstate.AllFlagsState` object containing the information you need. + +```go showLineNumbers +user := ffcontext.NewEvaluationContext("example") +// AllFlagsState will give you the value for all the flags available. +allFlagsState := ffclient.AllFlagsState(u) + +// If you want to send it to the front-end you can Marshal it by calling MarshalJSON() +forFE, err := allFlagsState.MarshalJSON() +``` + +The `MarshalJSON()` function will return something like below, that can be directly used by your front-end application. +```json showLineNumbers +{ + "flags": { + "test-flag0": { + "value": true, + "timestamp": 1622209328, + "variationType": "True", + "trackEvents": true + }, + "test-flag1": { + "value": "true", + "timestamp": 1622209328, + "variationType": "True", + "trackEvents": true + }, + "test-flag2": { + "value": 1, + "timestamp": 1622209328, + "variationType": "True", + "trackEvents": true + }, + "test-flag3": { + "value": [ + "yo", + "ya" + ], + "timestamp": 1622209328, + "variationType": "True", + "trackEvents": true + }, + "test-flag4": { + "value": { + "test": "yo" + }, + "timestamp": 1622209328, + "variationType": "True", + "trackEvents": true + }, + "test-flag5": { + "value": 1.1, + "timestamp": 1622209328, + "variationType": "True", + "trackEvents": false + } + }, + "valid": true +} +``` + +:::caution +There is no tracking done when evaluating all the flag at once. +::: diff --git a/website/versioned_docs/version-v1.24.1/index.md b/website/versioned_docs/version-v1.24.1/index.md new file mode 100644 index 00000000000..a1f1e8f0a41 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/index.md @@ -0,0 +1,36 @@ +--- +title: Home +description: go-feature-flag is a simple and complete feature flag solution, without any complex backend system to install. You need only a file as your backend. +sidebar_position: 1 +--- + +

+ go-feature-flag logo +

+ +## What is GO Feature Flag? +GO Feature Flag is a completely open-source, simple and lightweight feature flag solution. + +The solution has been built for application of feature flags in your code without the need of any vendor. + +**GO Feature Flag** was initially developed for the GO language, but with the new standardisation of feature flags by [Openfeature](https://openfeature.dev/) project, it now supports multiple languages _(`JAVA`, `typescript`, `javascript`, ...)_ with a simple server to host. + +:::info +If you are not familiar with feature flags, also called feature toggles, you can read this [article from Martin Fowler](https://www.martinfowler.com/articles/feature-toggles.html) +where he explains why this is a great pattern. + +I've also written an [article](https://medium.com/better-programming/feature-flags-and-how-to-iterate-quickly-7e3371b9986) which explains why feature flags can accelerate your iteration cycle. +::: + +## What can I do with GO Feature Flag? + +- Storing your configuration flags file on various locations (`HTTP`, `S3`, `Kubernetes`, [_see full list_](configure_flag/store_your_flags.mdx)). +- Configuring your flags in various [format](configure_flag/flag_format.mdx) (`JSON`, `TOML` and `YAML`). +- Adding complex [rules](configure_flag/flag_format.mdx#rule-format) to target your users. +- Use complex rollout strategy for your flags : + - [Run A/B testing experimentation](configure_flag/rollout/experimentation.mdx). + - [Progressively rollout a feature](configure_flag/rollout/progressive.mdx). + - [Schedule your flag updates](configure_flag/rollout/scheduled.mdx). +- Exporting your flags usage data ([`s3`](go_module/data_collection/s3.md), [`log`](go_module/data_collection/log.md), [`file`](go_module/data_collection/file.md), [_see full list_](configure_flag/export_flags_usage.mdx)). +- Getting notified when a flag has been changed ([`webhook`](go_module/notifier/webhook.md) and [`slack`](go_module/notifier/slack.md)). +- **Cross-Language Support:** Available for use across several programming languages. diff --git a/website/versioned_docs/version-v1.24.1/openfeature_sdk/_category_.json b/website/versioned_docs/version-v1.24.1/openfeature_sdk/_category_.json new file mode 100644 index 00000000000..fcfbd961686 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/openfeature_sdk/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 40, + "label":"Use with OpenFeature", + "collapsible": true, + "collapsed": true +} diff --git a/website/versioned_docs/version-v1.24.1/openfeature_sdk/client_providers/_category_.json b/website/versioned_docs/version-v1.24.1/openfeature_sdk/client_providers/_category_.json new file mode 100644 index 00000000000..0e8feb86373 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/openfeature_sdk/client_providers/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 20, + "label":"Client Providers", + "collapsible": true, + "collapsed": true +} diff --git a/website/versioned_docs/version-v1.24.1/openfeature_sdk/client_providers/openfeature_android.mdx b/website/versioned_docs/version-v1.24.1/openfeature_sdk/client_providers/openfeature_android.mdx new file mode 100644 index 00000000000..a407b84adef --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/openfeature_sdk/client_providers/openfeature_android.mdx @@ -0,0 +1,106 @@ +--- +sidebar_position: 51 +title: Android / Kotlin +description: How to use the OpenFeature Kotlin SDK for your Android application +--- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + +![Static Badge](https://img.shields.io/badge/status-experimental-red) + +This OpenFeature provider has a Kotlin implementation for Android to communicate with the GO Feature +Flag Server. + +The OpenFeature Kotlin is experimental, and the provider is also experimental. +We don't recommend using this in production yet. + +## About this provider + +[GO Feature Flag](https://gofeatureflag.org) provider allows you to connect to your GO Feature Flag +instance with the OpenFeature Kotlin SDK. + +This is a client provider made for Android, we do not recommend using it in a server environment. +If you want to use it in a server environment, you should use +the [`Java` provider](/docs/openfeature_sdk/server_providers/openfeature_java). + +## Install the provider + + + + + ```json + implementation("org.gofeatureflag.openfeature:gofeatureflag-kotlin-provider:0.0.1-beta.1") + ``` + + + + + ```xml + + org.gofeatureflag.openfeature + gofeatureflag-kotlin-provider + :0.0.1-beta.1 + + ``` + + + + +## How to use the provider? + +```kotlin +val evaluationContext = ImmutableContext( + targetingKey = "0a23d9a5-0a8f-42c9-9f5f-4de3afd6cf99", + attributes = mutableMapOf( + "region" to Value.String("us-east-1"), + "email" to Value.String("john.doe@gofeatureflag.org") + ) +) + +OpenFeatureAPI.setProvider( + GoFeatureFlagProvider( + options = GoFeatureFlagOptions( + endpoint = "http://localhost:1031" + ) + ), evaluationContext +) + +val client = OpenFeatureAPI.getClient("my-client") +if (client.getBooleanValue("my-flag", false)) { + println("my-flag is enabled") +} +OpenFeatureAPI.shutdown() +``` + +### Available options + +| Option name | Type | Default | Description | +|--------------------|--------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| endpoint | String | | endpoint is the URL where your GO Feature Flag server is located. | +| timeout | Long | 10000 | (optional) timeout is the time in millisecond we wait for an answer from the server. | +| maxIdleConnections | Int | 1000 | (optional) maxIdleConnections is the maximum number of connexions in the connexion pool. | +| keepAliveDuration | Long | 7200000 | (optional) keepAliveDuration is the time in millisecond we keep the connexion open. | +| apiKey | String | | (optional) If GO Feature Flag is configured to authenticate the requests, you should provide an API Key to the provider. Please ask the administrator of the relay proxy to provide an API Key. | +| retryDelay | Long | 300 | (optional) delay in millisecond to wait before retrying to connect the websocket | + +### Reconnection + +If the connection to the GO Feature Flag instance fails, the provider will attempt to reconnect. + +### Event streaming + +Event streaming is not implemented yet in the GO Feature Flag provider. + +## Features status + +| Status | Feature | Description | +|--------|--------------------|--------------------------------------------------------------------------------------| +| ✅ | Flag evaluation | It is possible to evaluate all the type of flags | +| ✅ | Cache invalidation | Websocket mechanism is in place to refresh the cache in case of configuration change | +| ❌ | Logging | Not supported by the SDK | +| ❌ | Flag Metadata | Not supported by the SDK | +| ❌ | Event Streaming | Not implemented | +| ❌ | Unit test | Not implemented | + +Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌ diff --git a/website/versioned_docs/version-v1.24.1/openfeature_sdk/client_providers/openfeature_javascript.mdx b/website/versioned_docs/version-v1.24.1/openfeature_sdk/client_providers/openfeature_javascript.mdx new file mode 100644 index 00000000000..8141ea7e4a0 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/openfeature_sdk/client_providers/openfeature_javascript.mdx @@ -0,0 +1,81 @@ +--- +sidebar_position: 51 +title: Javascript / Typescript +description: How to use the OpenFeature Javascript web SDK for your client application +--- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Javascript / Typescript SDK usage +This page describes how to use the OpenFeature Javascript web SDK for your client application. + +## About this provider +[GO Feature Flag](https://gofeatureflag.org) provider allows you to connect to your GO Feature Flag instance with the `@openfeature/web-sdk`. + +The main difference between this provider and [`@openfeature/go-feature-flag-provider`](https://www.npmjs.com/package/@openfeature/go-feature-flag-provider) is that it uses a **static evaluation context**. +This provider is more sustainable for client-side implementation. + +If you want to know more about this pattern, I encourage you to read this [blog post](https://openfeature.dev/blog/catering-to-the-client-side/). + +## Install the provider + +```shell +npm install @openfeature/go-feature-flag-web-provider @openfeature/web-sdk +``` + +## How to use the provider? +```typescript +const evaluationCtx: EvaluationContext = { + targetingKey: 'user-key', + email: 'john.doe@gofeatureflag.org', + name: 'John Doe', +}; + +const goFeatureFlagWebProvider = new GoFeatureFlagWebProvider({ + endpoint: endpoint, + // ... +}, logger); + +await OpenFeature.setContext(evaluationCtx); // Set the static context for OpenFeature +OpenFeature.setProvider(goFeatureFlagWebProvider); // Attach the provider to OpenFeature +const client = await OpenFeature.getClient(); + +// You can now use the client to use your flags +if(client.getBooleanValue('my-new-feature', false)){ + //... +} + +// You can add handlers to know what happen in the provider +client.addHandler(ProviderEvents.Ready, () => { ... }); +client.addHandler(ProviderEvents.Error, () => { //... }); +client.addHandler(ProviderEvents.Stale, () => { //... }); +client.addHandler(ProviderEvents.ConfigurationChanged, () => { //... }); +``` + +### Available options +| Option name | Type | Default | Description | +|-------------------------------|--------|----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| endpoint | string | | endpoint is the URL where your GO Feature Flag server is located. | +| apiTimeout | number | 0 = no timeout | (optional) timeout is the time in millisecond we wait for an answer from the server. | +| apiKey | string | | (optional) If GO Feature Flag is configured to authenticate the requests, you should provide an API Key to the provider. Please ask the administrator of the relay proxy to provide an API Key. | +| websocketRetryInitialDelay | number | 100 | (optional) initial delay in millisecond to wait before retrying to connect the websocket | +| websocketRetryDelayMultiplier | number | 2 | (optional) multiplier of websocketRetryInitialDelay after each failure _(example: 1st connection retry will be after 100ms, second after 200ms, third after 400ms ...)_ | +| websocketMaxRetries | number | 10 | (optional) maximum number of retries before considering the websocket unreachable | + +### Reconnection +If the connection to the GO Feature Flag instance fails, the provider will attempt to reconnect with an exponential back-off. +The `websocketMaxRetries` can be specified to customize reconnect behavior. + +### Event streaming +The `GoFeatureFlagWebProvider` receives events from GO Feature Flag with changes. +Combined with the event API in the web SDK, this allows for subscription to flag value changes in clients. + +```typescript +client.addHandler(ProviderEvents.ConfigurationChanged, (ctx: EventDetails) => { + // do something when the configuration has changed. + // ctx.flagsChanged contains the list of changed flags. +}); +``` + +## Contribute to the provider +You can find the source of the provider in the [`open-feature/js-sdk-contrib`](https://github.com/open-feature/js-sdk-contrib/tree/main/libs/providers/go-feature-flag-web) repository. \ No newline at end of file diff --git a/website/versioned_docs/version-v1.24.1/openfeature_sdk/sdk.mdx b/website/versioned_docs/version-v1.24.1/openfeature_sdk/sdk.mdx new file mode 100644 index 00000000000..863d6552c7b --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/openfeature_sdk/sdk.mdx @@ -0,0 +1,89 @@ +--- +sidebar_position: 1 +description: Use GO Feature Flag with Openfeature SDKs +--- +import { Cards } from "@site/src/components/doc/cardv2"; +import { SdkCardContent} from "@site/src/components/doc/sdkCardContent"; + +# SDKs + +**GO Feature Flag** stands out as a feature flag solution, distinct from others, due to our decision to fully support the [`Openfeature`](https://openfeature.dev) CNCF project. + +The benefit of choosing OpenFeature lies in its framework-agnostic nature. When utilizing OpenFeature SDKs, you minimize the effort required for switching to a different feature flag provider. This flexibility empowers you to make changes without being tied down to a particular vendor. + +To show our commitment to this initiative, **GO Feature Flag has opted not to develop any custom SDKs and instead relies entirely on OpenFeature SDKs**. +In order to seamlessly integrate with our solution, we offer [`providers`](https://docs.openfeature.dev/docs/reference/concepts/provider) for GO Feature Flag in multiple programming languages. + +Rest assured, working with OpenFeature SDKs alongside GO Feature Flag providers is as straightforward as using any other feature flag solution. The added advantage is that you now adhere to a standard approach and avoid any vendor lock-in! + +## Server Providers + + }, + { + logoCss: "devicon-nodejs-plain colored", + title:"Node.JS", + badges:["Server"], + docLink: "./server_providers/openfeature_javascript", + content: + }, + { + logoCss: "devicon-java-plain colored", + title:"Java / Kotlin", + badges:["Server"], + docLink: "./server_providers/openfeature_java", + content: + }, + { + logoCss: "devicon-dot-net-plain-wordmark colored", + title:".Net", + badges:["Server"], + docLink: "./server_providers/openfeature_javascript", + content: + }, + { + logoCss: "devicon-python-plain colored", + title:"Python", + badges:["Server"], + docLink: "./server_providers/openfeature_python", + content: + } +]}/> + +## Client Providers + + }, + { + logoCss: "devicon-android-plain colored", + title:"Android / Kotlin", + badges:["Client"], + docLink: "./client_providers/openfeature_android", + warningBadges: ["experimental"], + content: + } +]}/> + +## How OpenFeature and GO Feature Flag are working together? + +To use the OpenFeature SDKs you need what we call a provider. +A **provider** is responsible for performing flag evaluations. It provides an abstraction between **GO Feature Flag** and the OpenFeature SDK. + +A provider needs a backend service to perform the flag evaluation. This is why we have introduced the [**relay proxy**](../relay_proxy). +This component retrieve your feature flag configuration file using the GO module and exposes APIs to get your flags variations. + +![](/docs/openfeature/concepts.jpg) + +With this simple architecture you have a central component _(the relay proxy)_ that is in charge of the flag evaluation, while the SDKs and providers are responsible to communicate with the relay proxy. + +This supports different languages the same way and facilitates you to use GO Feature Flag with all your favorite languages. diff --git a/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/_category_.json b/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/_category_.json new file mode 100644 index 00000000000..9fc0ead18b5 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 10, + "label":"Server Providers", + "collapsible": true, + "collapsed": true +} diff --git a/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_dotnet.mdx b/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_dotnet.mdx new file mode 100644 index 00000000000..6a89b43a649 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_dotnet.mdx @@ -0,0 +1,123 @@ +--- +sidebar_position: 52 +title: .NET +description: How to use the OpenFeature .Net SDK +--- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + +# .Net SDK usage + +## Install dependencies + +The first things we will do is install the **Open Feature SDK** and the **GO Feature Flag provider**. + + + + +```shell +dotnet add package OpenFeature.Contrib.GOFeatureFlag +``` + + + + +```shell +NuGet\Install-Package OpenFeature.Contrib.GOFeatureFlag +``` + + + + +```xml + +``` + + + + +```shell +paket add OpenFeature.Contrib.GOFeatureFlag +``` + + + + +```shell +// Install OpenFeature.Contrib.GOFeatureFlag as a Cake Addin +#addin nuget:?package=OpenFeature.Contrib.GOFeatureFlag + +// Install OpenFeature.Contrib.GOFeatureFlag as a Cake Tool +#tool nuget:?package=OpenFeature.Contrib.GOFeatureFlag +``` + + + + + +## Initialize your Open Feature client + +To evaluate the flags you need to have an Open Feature configured in you app. +This code block shows you how you can create a client that you can use in your application. + + + + +```csharp +using OpenFeature; +using OpenFeature.Contrib.GOFeatureFlag; + +// ... + +var goFeatureFlagProvider = new GoFeatureFlagProvider(new GoFeatureFlagProviderOptions +{ + Endpoint = "http://localhost:1031/", + Timeout = new TimeSpan(1000 * TimeSpan.TicksPerMillisecond) +}); +Api.Instance.SetProvider(goFeatureFlagProvider); +var client = Api.Instance.GetClient("my-app"); +``` + + + + +## Evaluate your flag + +This code block explain how you can create an `EvaluationContext` and use it to evaluate your flag. + +:::note +In this example we are evaluating a `boolean` flag, but other types are also available. + +**Refer to the [Open Feature documentation](https://docs.openfeature.dev/docs/reference/concepts/evaluation-api#basic-evaluation) to know more about it.** +::: + + + + +```csharp +// Context of your flag evaluation. +// With GO Feature Flag you MUST have a targetingKey that is a unique identifier of the user. +var userContext = EvaluationContext.Builder() + .Set("targetingKey", "1d1b9238-2591-4a47-94cf-d2bc080892f1") // user unique identifier (mandatory) + .Set("firstname", "john") + .Set("lastname", "doe") + .Set("email", "john.doe@gofeatureflag.org") + .Set("admin", true) // this field is used in the targeting rule of the flag "flag-only-for-admin" + .Set("anonymous", false) + .Build(); + +var adminFlag = await client.GetBooleanValue("flag-only-for-admin", false, userContext); +if (adminFlag) { + // flag "flag-only-for-admin" is true for the user +} else { + // flag "flag-only-for-admin" is false for the user +} +``` + + + + +## Contribute to the provider +You can find the source of the provider in the [`open-feature/dotnet-sdk-contrib`](https://github.com/open-feature/dotnet-sdk-contrib/tree/main/src/OpenFeature.Contrib.Providers.GOFeatureFlag) repository. \ No newline at end of file diff --git a/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_go.mdx b/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_go.mdx new file mode 100644 index 00000000000..e47a35e513e --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_go.mdx @@ -0,0 +1,111 @@ +--- +sidebar_position: 20 +title: GO +description: How to use the OpenFeature GO SDK +--- + +# GO SDK usage + +## Install dependencies + +The first things we will do is install the **Open Feature SDK** and the **GO Feature Flag provider**. + +```shell +go get github.com/open-feature/go-sdk +go get github.com/open-feature/go-sdk-contrib/providers/go-feature-flag +``` + +## Initialize your Open Feature provider + +Despite other providers, this GO provider can be used with the **relay proxy** or standalone +using the **GO Feature Flag module**. + +### Using the relay proxy + +If you want to use the provider with the **relay proxy** you should set the field `Endpoint` in the options. +By default it will use a default `HTTPClient` with a **timeout** configured at **10000** milliseconds. You can change +this configuration by providing your own configuration of the `HTTPClient`. + +#### Example +```go +options := gofeatureflag.ProviderOptions{ + Endpoint: "http://localhost:1031", + HTTPClient: &http.Client{ + Timeout: 1 * time.Second, + }, +} +provider, _ := gofeatureflag.NewProvider(options) +``` + +### Using the GO module _(standalone version)_ +If you want to use the provider in standalone mode using the GO module, you should set the field `GOFeatureFlagConfig` +in the options. + +You can check the [GO Feature Flag documentation website](https://docs.gofeatureflag.org) to look how to configure the +GO module. + +#### Example +```go +options := gofeatureflag.ProviderOptions{ + GOFeatureFlagConfig: &ffclient.Config{ + PollingInterval: 10 * time.Second, + Context: context.Background(), + Retriever: &fileretriever.Retriever{ + Path: "../testutils/module/flags.yaml", + }, + }, +} +provider, _ := gofeatureflag.NewProvider(options) +``` + +## Initialize your Open Feature client + +To evaluate the flags you need to have an Open Feature configured in you app. +This code block shows you how you can create a client that you can use in your application. + +```go +import ( + // ... + gofeatureflag "github.com/open-feature/go-sdk-contrib/providers/go-feature-flag/pkg" + of "github.com/open-feature/go-sdk/pkg/openfeature" +) + +// ... + +options := gofeatureflag.ProviderOptions{ + Endpoint: "http://localhost:1031", +} +provider, err := gofeatureflag.NewProvider(options) +of.SetProvider(provider) +client := of.NewClient("my-app") +``` + +## Evaluate your flag + +This code block explain how you can create an `EvaluationContext` and use it to evaluate your flag. + + +> In this example we are evaluating a `boolean` flag, but other types are also available. +> +> **Refer to the [Open Feature documentation](https://docs.openfeature.dev/docs/reference/concepts/evaluation-api#basic-evaluation) to know more about it.** + +```go +evaluationCtx := of.NewEvaluationContext( + "1d1b9238-2591-4a47-94cf-d2bc080892f1", + map[string]interface{}{ + "firstname", "john", + "lastname", "doe", + "email", "john.doe@gofeatureflag.org", + "admin", true, + "anonymous", false, + }) +adminFlag, _ := client.BoolValue(context.TODO(), "flag-only-for-admin", false, evaluationCtx) +if adminFlag { + // flag "flag-only-for-admin" is true for the user +} else { + // flag "flag-only-for-admin" is false for the user +} +``` + +## Contribute to the provider +You can find the source of the provider in the [`open-feature/go-sdk-contrib`](https://github.com/open-feature/go-sdk-contrib/tree/main/providers/go-feature-flag) repository. \ No newline at end of file diff --git a/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_java.mdx b/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_java.mdx new file mode 100644 index 00000000000..1078f877f49 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_java.mdx @@ -0,0 +1,148 @@ +--- +sidebar_position: 40 +title: Java +description: How to use the OpenFeature JAVA SDK +--- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# JAVA SDK usage + +## Install dependencies + +The first things we will do is install the **Open Feature SDK** and the **GO Feature Flag provider**. + + + + +```xml + + dev.openfeature + javasdk + [0,) + + + dev.openfeature.contrib.providers + go-feature-flag + [0,) + +``` + + + + +```gradle +implementation group: 'dev.openfeature', name: 'javasdk', version: '0.+' +implementation group: 'dev.openfeature.contrib.providers', name: 'go-feature-flag', version: '0.+' +``` + + + + + +## Initialize your Open Feature client +To evaluate the flags you need to have an Open Feature configured in you app. +This code block shows you how you can create a client that you can use in your application. + + + + +```java +import dev.openfeature.contrib.providers.gofeatureflag.GoFeatureFlagProvider; +import dev.openfeature.contrib.providers.gofeatureflag.GoFeatureFlagProviderOptions; +import dev.openfeature.sdk.EvaluationContext; +import dev.openfeature.sdk.MutableContext; +import dev.openfeature.sdk.OpenFeatureAPI; + +// ... + +GoFeatureFlagProviderOptions options = GoFeatureFlagProviderOptions.builder().endpoint("http://localhost:1031/").build(); +GoFeatureFlagProvider provider = new GoFeatureFlagProvider(options); + +OpenFeatureAPI.getInstance().setProvider(provider); +OpenFeatureAPI api = OpenFeatureAPI.getInstance(); +Client featureFlagClient = api.getClient(); +``` + + + + +```kotlin +import dev.openfeature.contrib.providers.gofeatureflag.GoFeatureFlagProvider +import dev.openfeature.contrib.providers.gofeatureflag.GoFeatureFlagProviderOptions +import dev.openfeature.sdk.EvaluationContext +import dev.openfeature.sdk.MutableContext +import dev.openfeature.sdk.OpenFeatureAPI + +// ... + +val options = GoFeatureFlagProviderOptions.builder().endpoint("http://localhost:1031/").build() +val provider = GoFeatureFlagProvider(options) + +OpenFeatureAPI.getInstance().provider = provider +// wait for the provider to be ready +val api = OpenFeatureAPI.getInstance() +val featureFlagClient = api.client +``` + + + + + +## Evaluate your flag + +This code block explain how you can create an `EvaluationContext` and use it to evaluate your flag. + +:::note +In this example we are evaluating a `boolean` flag, but other types are available. + +**Refer to the [Open Feature documentation](https://docs.openfeature.dev/docs/reference/concepts/evaluation-api#basic-evaluation) to know more about it.** +::: + + + + +```java +// Context of your flag evaluation. +// With GO Feature Flag you MUST have a targetingKey that is a unique identifier of the user. +EvaluationContext userContext = new MutableContext("1d1b9238-2591-4a47-94cf-d2bc080892f1") + .add("firstname", "john") + .add("lastname", "doe") + .add("email","john.doe@gofeatureflag.org") + .add("admin", true) + .add("anonymous", false); + +Boolean adminFlag = featureFlagClient.getBooleanValue("flag-only-for-admin", false, userContext); +if (adminFlag) { + // flag "flag-only-for-admin" is true for the user +} else { + // flag "flag-only-for-admin" is false for the user +} +``` + + + + +```kotlin +// Context of your flag evaluation. +// With GO Feature Flag you MUST have a targetingKey that is a unique identifier of the user. +val userContext: EvaluationContext = MutableContext("1d1b9238-2591-4a47-94cf-d2bc080892f1") + .add("firstname", "john") + .add("lastname", "doe") + .add("email", "john.doe@gofeatureflag.org") + .add("admin", true) + .add("anonymous", false) + +val adminFlag = featureFlagClient.getBooleanValue("bool_targeting_match", false, userContext) +if (adminFlag) { + // flag "flag-only-for-admin" is true for the user +} else { + // flag "flag-only-for-admin" is false for the user +} +``` + + + + +## Contribute to the provider +You can find the source of the provider in the [`open-feature/java-sdk-contrib`](https://github.com/open-feature/java-sdk-contrib/tree/main/providers/go-feature-flag) repository. \ No newline at end of file diff --git a/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_javascript.mdx b/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_javascript.mdx new file mode 100644 index 00000000000..2788a325465 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_javascript.mdx @@ -0,0 +1,136 @@ +--- +sidebar_position: 51 +title: Node.js +description: How to use the OpenFeature Javascript SDK +--- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + +# Node.js + +## Install dependencies + +The first things we will do is install the **Open Feature SDK** and the **GO Feature Flag provider**. + + + + +```shell +yarn add @openfeature/server-sdk @openfeature/go-feature-flag-provider +``` + + + + +```shell +npm i @openfeature/server-sdk @openfeature/go-feature-flag-provider +``` + + + + +## Initialize your Open Feature client + +To evaluate the flags you need to have an Open Feature configured in your app. +This code block shows you how you can create a client that you can use in your application. + + + + +```javascript +const {OpenFeature} = require("@openfeature/server-sdk"); +const {GoFeatureFlagProvider} = require("@openfeature/go-feature-flag-provider"); + + +// init Open Feature SDK with GO Feature Flag provider +const goFeatureFlagProvider = new GoFeatureFlagProvider({ + endpoint: 'http://localhost:1031/' // DNS of your instance of relay proxy +}); +OpenFeature.setProvider(goFeatureFlagProvider); +const featureFlagClient = OpenFeature.getClient('my-app') +``` + + + + + +```typescript +import {EvaluationContext, OpenFeature} from "@openfeature/server-sdk"; +import {GoFeatureFlagProvider} from "@openfeature/go-feature-flag-provider"; + + +// init Open Feature SDK with GO Feature Flag provider +const goFeatureFlagProvider: GoFeatureFlagProvider = new GoFeatureFlagProvider({ +endpoint: 'http://localhost:1031/' +}); +OpenFeature.setProvider(goFeatureFlagProvider); +const featureFlagClient = OpenFeature.getClient('my-app'); +``` + + + + +## Evaluate your flag + +This code block explains how you can create an `EvaluationContext` and use it to evaluate your flag. + +:::note +In this example, we are evaluating a `boolean` flag, but other types are also available. + +**Refer to the [Open Feature documentation](https://docs.openfeature.dev/docs/reference/concepts/evaluation-api#basic-evaluation) to know more about it.** +::: + + + + +```javascript +// Context of your flag evaluation. +// With GO Feature Flag you MUST have a targetingKey that is a unique identifier of the user. +const userContext = { + targetingKey: '1d1b9238-2591-4a47-94cf-d2bc080892f1', // user unique identifier (mandatory) + firstname: 'john', + lastname: 'doe', + email: 'john.doe@gofeatureflag.org', + admin: true, // this field is used in the targeting rule of the flag "flag-only-for-admin" + // ... +}; + +const adminFlag = await featureFlagClient.getBooleanValue('flag-only-for-admin', false, userContext); +if (adminFlag) { + // flag "flag-only-for-admin" is true for the user +} else { + // flag "flag-only-for-admin" is false for the user +} +``` + + + + + +```typescript +// Context of your flag evaluation. +// With GO Feature Flag you MUST have a targetingKey that is a unique identifier of the user. +const userContext: EvaluationContext = { + targetingKey: '1d1b9238-2591-4a47-94cf-d2bc080892f1', // user unique identifier + firstname: 'john', + lastname: 'doe', + email: 'john.doe@gofeatureflag.org', + admin: true, // this field is used in the targeting rule of the flag "flag-only-for-admin" + // ... +}; + +const adminFlag = await featureFlagClient.getBooleanValue('flag-only-for-admin', false, userContext); +if (adminFlag) { + // flag "flag-only-for-admin" is true for the user +} else { + // flag "flag-only-for-admin" is false for the user +} +``` + + + + +## Contribute to the provider +You can find the source of the provider in the [`open-feature/js-sdk-contrib`](https://github.com/open-feature/js-sdk-contrib/tree/main/libs/providers/go-feature-flag) repository. diff --git a/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_python.md b/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_python.md new file mode 100644 index 00000000000..59618787491 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/openfeature_sdk/server_providers/openfeature_python.md @@ -0,0 +1,77 @@ +--- +sidebar_position: 51 +title: Python +description: How to use the OpenFeature Python SDK with GO Feature Flag +--- + +# Python Provider + +## Install dependencies + +The first things we will do is install the **Open Feature SDK** and the **GO Feature Flag provider**. + +```shell +pip install gofeatureflag-python-provider +``` + +## Initialize your Open Feature client + +To evaluate the flags you need to have an Open Feature configured in you app. +This code block shows you how you can create a client that you can use in your application. + +```python +from gofeatureflag_python_provider.provider import GoFeatureFlagProvider +from gofeatureflag_python_provider.options import GoFeatureFlagOptions +from openfeature import api +from openfeature.evaluation_context import EvaluationContext + +// ... + +goff_provider = GoFeatureFlagProvider( + options=GoFeatureFlagOptions(endpoint="https://gofeatureflag.org/") +) +api.set_provider(goff_provider) +client = api.get_client(name="test-client") +``` + +## Evaluate your flag + +This code block explains how you can create an `EvaluationContext` and use it to evaluate your flag. + + +> In this example, we are evaluating a `boolean` flag, but other types are also available. +> +> **Refer to the [Open Feature documentation](https://docs.openfeature.dev/docs/reference/concepts/evaluation-api#basic-evaluation) to know more about it.** + +```python +// Context of your flag evaluation. +// With GO Feature Flag you MUST have a targetingKey that is a unique identifier of the user. +evaluation_ctx = EvaluationContext( + targeting_key="d45e303a-38c2-11ed-a261-0242ac120002", + attributes={ + "email": "john.doe@gofeatureflag.org", + "firstname": "john", + "lastname": "doe", + "anonymous": False, + "professional": True, + "rate": 3.14, + "age": 30, + "company_info": {"name": "my_company", "size": 120}, + "labels": ["pro", "beta"], + }, +) + +admin_flag = client.get_boolean_value( + flag_key=flag_key, + default_value=default_value, + evaluation_context=ctx, + ) + +if admin_flag: + # flag "flag-only-for-admin" is true for the user +else: + # flag "flag-only-for-admin" is false for the user +``` + +## Contribute to the provider +You can find the source of the provider in the [`repository`](https://github.com/thomaspoignant/go-feature-flag/tree/main/openfeature/providers/python-provider). \ No newline at end of file diff --git a/website/versioned_docs/version-v1.24.1/relay_proxy/_category_.json b/website/versioned_docs/version-v1.24.1/relay_proxy/_category_.json new file mode 100644 index 00000000000..f4abdc44a43 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/relay_proxy/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 50, + "label":"Use the relay proxy", + "collapsible": true, + "collapsed": true +} diff --git a/website/versioned_docs/version-v1.24.1/relay_proxy/configure_relay_proxy.md b/website/versioned_docs/version-v1.24.1/relay_proxy/configure_relay_proxy.md new file mode 100644 index 00000000000..d89d6d20e8d --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/relay_proxy/configure_relay_proxy.md @@ -0,0 +1,246 @@ +--- +sidebar_position: 30 +title: Configuration +description: How to configure the relay proxy to serve your feature flags. +--- + +# Configure the relay proxy + +## Getting Started +The configuration of the **relay proxy** is based on a configuration file that you have to provide. + +The only mandatory information you need to start the server is to provide where to retrieve your feature flags configuration. + +```yaml +retriever: + kind: file + path: /goff/flags.yaml # Location of your feature flag files +``` + +## Global configuration + +:::tip Use environment variables. +You can override file configurations using environment variables. + +Note that all environment variables should be uppercase. +If you want to replace a nested fields, please use `_` to separate each field _(ex: `RETRIEVER_KIND`)_. +::: + + +| Field name | Type | Default | Description | +|-------------------------------|---------------------------|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `retriever` | [retriever](#retriever) | **none** | **(mandatory)** This is the configuration on how to retrieve the configuration of the files.

_Note: this field is mandatory only if `retrievers` is not set._ | | +| `retrievers` | [[]retriever](#retriever) | **none** | **(mandatory)** Exactly the same things as `retriever` except that you can provide more than 1 retriever.

_Note: this field is mandatory only if `retriever` is not set._ | +| `listen` | int | `1031` | This is the port used by the relay proxy when starting the HTTP server. | +| `pollingInterval` | int | `60000` | This is the time interval **in millisecond** when the relay proxy is reloading the configuration file.
The minimum time accepted is 1000 millisecond. | +| `enablePollingJitter` | boolean | `false` | Set to true if you want to avoid having true periodicity when retrieving your flags. It is useful to avoid having spike on your flag configuration storage in case your application is starting multiple instance at the same time.
We ensure a deviation that is maximum ±10% of your polling interval.
Default: false | +| `hideBanner` | boolean | `false` | Should we display the beautiful **go-feature-flag** banner when starting the relay proxy | +| `enableSwagger` | boolean | `false` | Enables Swagger for testing the APIs directly. If you are enabling Swagger you will have to provide the `host` configuration and the Swagger UI will be available at `http://:/swagger/`. | +| `host` | string | `localhost` | This is the DNS you will use to access the relay proxy. This field is used by Swagger to query the API at the right place. | +| `restApiTimeout` | int | `5000` | Timeout in milliseconds for API calls. | +| `debug` | boolean | `false` | If `true`, it enables detailed logs for troubleshooting. In case of an error, it will be also visible in the body. | +| `fileFormat` | string | `yaml` | This is the format of your `go-feature-flag` configuration file. Acceptable values are `yaml`, `json`, `toml`. | +| `startWithRetrieverError` | boolean | `false` | By default the **relay proxy** will crash if it is not able to retrieve the flags from the configuration.
If you don't want your relay proxy to crash, you can set `startWithRetrieverError` to true. Until the flag is retrievable the relay proxy will only answer with default values. | +| `exporter` | [exporter](#exporter) | **none** | Exporter is the configuration used to export data. | +| `notifier` | [notifier](#notifier) | **none** | Notifiers is the configuration on where to notify a flag change. | +| `apiKeys` | []string | **none** | List of authorized API keys. Each request will need to provide one of authorized key inside `Authorization` header with format `Bearer `.

_Note: there will be no authorization when this config is not set._ | +| `evaluationContextEnrichment` | object | **none** | It is a free field that will be merged with the evaluation context sent during the evaluation. It is useful to add common attributes to all the evaluations, such as a server version, environment, etc.

These fields will be included in the custom attributes of the evaluation context.

If in the evaluation context you have a field with the same name, it will be overriden by the `evaluationContextEnrichment`. | +| `openTelemetryOtlpEndpoint` | string | **none** | Endpoint of your OpenTelemetry OTLP collector, used to send traces to it and you will be able to forward them to your OpenTelemetry solution with the appropriate provider. | +| `kafka` | object | **none** | Settings for the Kafka exporter. Mandatory when using the 'kafka' exporter type, and ingored otherwise. | + + + + +## type `retriever` + +`go-feature-flag` supports different kind of retriever types such as S3, Google store, etc ... +In this section we will present all the available retriever configurations available. + +### S3 + +| Field name | Type | Default | Description | +|------------|--------|----------|---------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`s3`**.
_This field is mandatory and describes which retriever you are using._ | +| `bucket` | string | **none** | **(mandatory)** This is the name of your S3 bucket _(ex: `my-featureflag-bucket`)_. | +| `item` | string | **none** | **(mandatory)** Path to the file inside the bucket _(ex: `config/flag/my-flags.yaml`)_. | + + +### GitHub + +| Field name | Type | Default | Description | +|------------------|--------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`github`**.
_This field is mandatory and describes which retriever you are using._ | +| `repositorySlug` | string | **none** | **(mandatory)** The repository slug of the GitHub repository where your file is located _(ex: `thomaspoignant/go-feature-flag`)_. | +| `path` | string | **none** | **(mandatory)** Path to the file inside the repository _(ex: `config/flag/my-flags.yaml`)_. | +| `branch` | string | `main` | The branch we should check in the repository. | +| `token` | string | **none** | Github token used to access a private repository, you need the repo permission ([how to create a GitHub token](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token)). | +| `timeout` | string | `10000` | Timeout in millisecond used when calling GitHub. | + +### GitLab + +| Field name | Type | Default | Description | +|------------------|--------|----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`gitlab`**.
_This field is mandatory and describes which retriever you are using._ | +| `repositorySlug` | string | **none** | **(mandatory)** The repository slug of the GitLab repository where your file is located _(ex: `thomaspoignant/go-feature-flag`)_. | +| `path` | string | **none** | **(mandatory)** Path to the file inside the repository _(ex: `config/flag/my-flags.yaml`)_. | +| `baseUrl` | string | `https://gitlab.com` | The base URL of your GitLab instance. | +| `branch` | string | `main` | The branch we should check in the repository. | +| `token` | string | **none** | GitLab personal access token used to access a private repository ([Create a personal access token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token)). | +| `timeout` | string | `10000` | Timeout in millisecond used when calling GitLab. | + + +### File + +| Field name | Type | Default | Description | +|------------|--------|----------|----------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`file`**.
_This field is mandatory and describes which retriever you are using._ | +| `path` | string | **none** | **(mandatory)** Path to the file in your local computer _(ex: `/goff/my-flags.yaml`)_. | + + +### HTTP + +| Field name | Type | Default | Description | +|------------|---------------------|----------|----------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`http`**.
_This field is mandatory and describes which retriever you are using._ | +| `url` | string | **none** | **(mandatory)** Location to retrieve the file. | +| `method` | string | `GET` | The HTTP Method you are using to call the HTTP endpoint. | +| `body` | string | **none** | The HTTP Body you are using to call the HTTP endpoint. | +| `headers` | map[string][]string | **none** | The HTTP headers used when calling the HTTP endpoint (useful for authorization). | +| `timeout` | string | `10000` | Timeout in millisecond when calling the HTTP endpoint. | + + +### Google Storage + +| Field name | Type | Default | Description | +|------------|--------|----------|-------------------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`googleStorage`**.
_This field is mandatory and describes which retriever you are using._ | +| `bucket` | string | **none** | **(mandatory)** This is the name of your Google Storage bucket _(ex: `my-featureflag-bucket`)_. | +| `object` | string | **none** | **(mandatory)** Path to the file inside the bucket _(ex: `config/flag/my-flags.yaml`)_. | + + +### Kubernetes ConfigMap + +_Note that relay proxy is only supporting this while running inside the kubernetes cluster._ + +| Field name | Type | Default | Description | +|-------------|--------|----------|---------------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`configmap`**.
_This field is mandatory and describes which retriever you are using._ | +| `namespace` | string | **none** | **(mandatory)** This is the name of the namespace where your **configmap** is located _(ex: `default`)_. | +| `configmap` | string | **none** | **(mandatory)** Name of the **configmap** we should read _(ex: `feature-flag`)_. | +| `key` | string | **none** | **(mandatory)** Name of the `key` in the **configmap** which contains the flag. | + +### MongoDB + +_To understand the format in which a flag needs to be configured in MongoDB, check the [example](https://github.com/thomaspoignant/go-feature-flag/examples/retriever_mongodb) available._ + +| Field name | Type | Default | Description | +|-------------|--------|----------|---------------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`mongodb`**.
_This field is mandatory and describes which retriever you are using._ | +| `uri` | string | **none** | **(mandatory)** This is the MongoDB URI used in order to connect to the MongoDB instance. | +| `database` | string | **none** | **(mandatory)** Name of the **database** where flags are stored. | +| `collection` | string | **none** | **(mandatory)** Name of the **collection** where flags are stored. | + + + +## type `exporter` + +### Webhook + +| Field name | Type | Default | Description | +|--------------------|---------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`webhook`**.
_This field is mandatory and describes which retriever you are using._ | +| `endpointUrl` | string | **none** | **(mandatory)** EndpointURL of your webhook. | +| `flushInterval` | int | `60000` | The interval in millisecond between 2 calls to the webhook _(if the `maxEventInMemory` is reached before the flushInterval we will call the webhook before)_. | +| `maxEventInMemory` | int | `100000` | If we hit that limit we will call the webhook. | +| `secret` | string | **none** | Secret used to sign your request body and fill the `X-Hub-Signature-256` header.
See [signature section](https://thomaspoignant.github.io/go-feature-flag/latest/data_collection/webhook/#signature) for more details. | +| `meta` | map[string]string | **none** | Add all the information you want to see in your request. | +| `headers` | map[string][]string | **none** | Add all the headers you want to add while calling the endpoint | + + +### File + +| Field name | Type | Default | Description | +|--------------------|--------|-----------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`file`**.
_This field is mandatory and describes which retriever you are using._ | +| `outputDir` | string | **none** | **(mandatory)** OutputDir is the location of the directory where to store the exported files. It should finish with a `/`. | +| `flushInterval` | int | `60000` | The interval in millisecond between 2 calls to the webhook _(if the `maxEventInMemory` is reached before the flushInterval we will call the webhook before)_. | +| `maxEventInMemory` | int | `100000` | If we hit that limit we will call the webhook. | +| `format` | string | `JSON` | Format is the output format you want in your exported file. Available format: `JSON`, `CSV`, `Parquet`. | +| `filename` | string | `flag-variation-{{ .Hostname}}-{{ .Timestamp}}.{{ .Format}}` | You can use a templated config to define the name of your exported files. Available replacements are `{{ .Hostname}}`, `{{ .Timestamp}}` and `{{ .Format}` | +| `csvTemplate` | string | `{{ .Kind}};{{ .ContextKind}};{{ .UserKey}};{{ .CreationDate}};{{ .Key}};{{ .Variation}};{{ .Value}};{{ .Default}};{{ .Source}}\n` | CsvTemplate is used if your output format is CSV.
This field will be ignored if you are using format other than CSV.
You can decide which fields you want in your CSV line with a go-template syntax, please check [`internal/exporter/feature_event.go`](https://github.com/thomaspoignant/go-feature-flag/blob/main/internal/exporter/feature_event.go) to see the fields available. |` +| `parquetCompressionCodec` | string | `SNAPPY` | ParquetCompressionCodec is the parquet compression codec for better space efficiency. [Available options](https://github.com/apache/parquet-format/blob/master/Compression.md) |` + + +### Log + +| Field name | Type | Default | Description | +|--------------------|--------|-------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`log`**.
_This field is mandatory and describes which retriever you are using._ | +| `flushInterval` | int | `60000` | The interval in millisecond between 2 calls to the webhook _(if the `maxEventInMemory` is reached before the flushInterval, we will call the webhook before)_. | +| `maxEventInMemory` | int | `100000` | If we hit that limit we will call the webhook. | +| `logFormat` | string | `[{{ .FormattedDate}}] user="{{ .UserKey}}", flag="{{ .Key}}", value="{{ .Value}}"` | LogFormat is the [template](https://golang.org/pkg/text/template/) configuration of the output format of your log.
You can use all the key from the exporter.FeatureEvent + a key called FormattedDate that represent the date with the RFC 3339 Format. | + +### S3 + +| Field name | Type | Default | Description | +|--------------------|--------|-----------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`s3`**.
_This field is mandatory and describes which retriever you are using._ | +| `bucket` | string | **none** | **(mandatory)** Name of your S3 Bucket. | +| `flushInterval` | int | `60000` | The interval in millisecond between 2 calls to the webhook _(if the `maxEventInMemory` is reached before the flushInterval we will call the webhook before)_. | +| `maxEventInMemory` | int | `100000` | If we hit that limit we will call the webhook. | +| `format` | string | `JSON` | Format is the output format you want in your exported file. Available format: `JSON`, `CSV`, `Parquet`. | +| `filename` | string | `flag-variation-{{ .Hostname}}-{{ .Timestamp}}.{{ .Format}}` | You can use a config template to define the name of your exported files. Available replacements are `{{ .Hostname}}`, `{{ .Timestamp}}` and `{{ .Format}` | +| `csvTemplate` | string | `{{ .Kind}};{{ .ContextKind}};{{ .UserKey}};{{ .CreationDate}};{{ .Key}};{{ .Variation}};{{ .Value}};{{ .Default}};{{ .Source}}\n` | CsvTemplate is used if your output format is CSV.
This field will be ignored if you are using format other than CSV.
You can decide which fields you want in your CSV line with a go-template syntax, please check [`internal/exporter/feature_event.go`](https://github.com/thomaspoignant/go-feature-flag/blob/main/internal/exporter/feature_event.go) to see what are the fields available. |` +| `path` | string | **bucket root level** | The location of the directory in S3. | +| `parquetCompressionCodec` | string | `SNAPPY` | ParquetCompressionCodec is the parquet compression codec for better space efficiency. [Available options](https://github.com/apache/parquet-format/blob/master/Compression.md) |` + +### Google Storage + +| Field name | Type | Default | Description | +|--------------------|--------|-----------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`s3`**.
_This field is mandatory and describes which retriever you are using._ | +| `bucket` | string | **none** | **(mandatory)** Name of your Google Cloud Storage Bucket. | +| `flushInterval` | int | `60000` | The interval in millisecond between 2 calls to the webhook _(if the `maxEventInMemory` is reached before the flushInterval we will call the webhook before)_. | +| `maxEventInMemory` | int | `100000` | If we hit that limit we will call the webhook. | +| `format` | string | `JSON` | Format is the output format you want in your exported file. Available format: `JSON`, `CSV`, `Parquet`. | +| `filename` | string | `flag-variation-{{ .Hostname}}-{{ .Timestamp}}.{{ .Format}}` | You can use a templated config to define the name of your exported files. Available replacement are `{{ .Hostname}}`, `{{ .Timestamp}}` and `{{ .Format}` | +| `csvTemplate` | string | `{{ .Kind}};{{ .ContextKind}};{{ .UserKey}};{{ .CreationDate}};{{ .Key}};{{ .Variation}};{{ .Value}};{{ .Default}};{{ .Source}}\n` | CsvTemplate is used if your output format is CSV.
This field will be ignored if you are using format other than CSV.
You can decide which fields you want in your CSV line with a go-template syntax, please check [`internal/exporter/feature_event.go`](https://github.com/thomaspoignant/go-feature-flag/blob/main/internal/exporter/feature_event.go) to see what are the fields available. |` +| `path` | string | **bucket root level** | The location of the directory in S3. | +| `parquetCompressionCodec` | string | `SNAPPY` | ParquetCompressionCodec is the parquet compression codec for better space efficiency. [Available options](https://github.com/apache/parquet-format/blob/master/Compression.md) |` + +### SQS + +| Field name | Type | Default | Description | +|---------------------------|--------|-----------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`sqs`**.
_This field is mandatory and describes which retriever you are using._ | +| `queueUrl` | string | **none** | **(mandatory)** URL of your SQS queue.
_You can find it in your AWS console._ | + +### Kafka + +| Field name | Type | Default | Description | +|------------------|----------|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `kafka.topic` | string | **none** | **(mandatory)** Kafka topic to bind to. | +| `kafka.addresses` | []string | **none** | **(mandatory)** List of bootstrap addresses for the Kafka cluster. | +| `kafka.config` | object | _see description_ | This field allows fine tuning of the Kafka reader. This object should contain the [Sarama configuration](https://pkg.go.dev/github.com/IBM/sarama#Config) that the reader will use. On empty, a sensible default is created using [sarama.NewConfig()](https://pkg.go.dev/github.com/IBM/sarama#NewConfig) | + + + + +## type `notifier` + +### Slack + +| Field name | Type | Default | Description | +|-------------------|--------|----------|-----------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`slack`**.
_This field is mandatory and describe which retriever you are using._ | +| `slackWebhookUrl` | string | **none** | **(mandatory)** The complete URL of your incoming webhook configured in Slack. | + +### Webhook + +| Field name | Type | Default | Description | +|---------------|---------------------|------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `kind` | string | **none** | **(mandatory)** Value should be **`webhook`**.
_This field is mandatory and describes which retriever you are using._ | +| `endpointUrl` | string | **none** | **(mandatory)** The complete URL of your API (we will send a POST request to this URL, see [format](https://thomaspoignant.github.io/go-feature-flag/latest/notifier/webhook/#format) | +| `secret` | string | **none** | Secret used to sign your request body and fill the `X-Hub-Signature-256` header.
See [signature section](https://thomaspoignant.github.io/go-feature-flag/latest/data_collection/webhook/#signature) for more details. | +| `meta` | map[string]string | **none** | Add all the information you want to see in your request. | +| `headers` | map[string][]string | **none** | Add all the headers you want to add while calling the endpoint | diff --git a/website/versioned_docs/version-v1.24.1/relay_proxy/deploy_relay_proxy.md b/website/versioned_docs/version-v1.24.1/relay_proxy/deploy_relay_proxy.md new file mode 100644 index 00000000000..04686a78ebc --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/relay_proxy/deploy_relay_proxy.md @@ -0,0 +1,60 @@ +--- +sidebar_position: 70 +title: Deployment +description: Deploy the relay proxy. +--- + +# Deploy the relay proxy + +## Deploy in Kubernetes using Helm +The relay proxy can be deployed in Kubernetes using a helm chart. +Helm is an invaluable tool for configuring and deploying applications to a Kubernetes environment. + +Below are the steps for installing a Helm Chart from a **GO Feature Flag** Helm repository. + +### Prerequisites + +- Access to a Kubernetes cluster +- Helm CLI installed on the client machine + +### Step 1: Prepare and Configure the Repository + +Add the repository to Helm with the Helm repository add command and provide a name and the repository URL. For example: + +```shell +helm repo add go-feature-flag https://charts.gofeatureflag.org/ +``` + +### Step 2: Install the Chart + +Install the Helm Chart with the Helm install command and provide the custom repository name, the chart name and any necessary values files. +You can look at the [helm doc](https://github.com/thomaspoignant/go-feature-flag/blob/main/cmd/relayproxy/helm-charts/relay-proxy/README.md) to know exactly what you can change in the values.yaml file. + +```shell +helm install go-feature-flag/relay-proxy -f values.yaml +``` + +### Step 3: Verify The Chart Installation + +Verify the Helm Chart installation with the Helm list command. For example: + +```shell +helm list +``` + +## Deploy as AWS Lambda +The GO Feature Flag relay proxy can easily be launched as an AWS Lambda function. +To do this, simply set the `startAsAwsLambda` option in your configuration file to `true`, like so: + +```yaml +# ... +startAsAwsLambda: true +``` + +Once you've updated your configuration file, you can deploy your function in AWS and configure it to be accessible +via HTTP. This can be achieved by creating an API Gateway or an Application Load Balancer (ALB) and linking it to +your Lambda function. + +By configuring your GO Feature Flag relay proxy to run as an AWS Lambda function, you can take advantage of many +benefits of serverless computing, including automatic scaling, reduced infrastructure costs, and simplified +deployment and management. \ No newline at end of file diff --git a/website/versioned_docs/version-v1.24.1/relay_proxy/getting_started.md b/website/versioned_docs/version-v1.24.1/relay_proxy/getting_started.md new file mode 100644 index 00000000000..00b57d3d5ee --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/relay_proxy/getting_started.md @@ -0,0 +1,61 @@ +--- +sidebar_position: 19 +title: Getting started +description: Getting started with the relay proxy. +--- + +# Getting started + +Before starting your **relay proxy** you will need to create a minimal configuration file. + +```yaml +# this is a minimal config containing only where your flag file is located +retriever: + kind: http + url: https://raw.githubusercontent.com/thomaspoignant/go-feature-flag/main/examples/retriever_file/flags.yaml +``` + +After that you can launch the **relay proxy** by using this command: +```shell +go-feature-flag-relay-proxy --config=/path/to/your/configfile +``` + +The **relay proxy** will read the configuration file and retrieve all the flags. +After that you can use all the available endpoints _(see **Service endpoints** section)_ and get the variations for your users. + + +## Deployment options + +A common way to run **go-feature-flag relay proxy** is to use the Docker Container. +An image is available on Docker Hub [`thomaspoignant/go-feature-flag`](https://hub.docker.com/r/thomaspoignant/go-feature-flag). + +You can also run it as a service in your application following the [**Installation**](install_relay_proxy) page. + +```shell +docker run -v $(pwd)/goff-proxy.yaml:/goff/goff-proxy.yaml thomaspoignant/go-feature-flag-relay-proxy:latest +``` + +## Specifying a configuration + +To configure the relay proxy you should provide a configuration file when launching the instance. + +The easiest way to provide the file is to use the option `--config=/path_to_your_file.yaml`. +But if you don't provide this option, the relay proxy will look in these folders if a file named `goff-proxy.yaml` is available. + +- **current folder** +- `/goff/` +- `/etc/opt/goff/` + +To learn how to configure the relay proxy, read [Configuration](./configure_relay_proxy). + +## Exporting metrics and traces + +To export the data you can use all the capabilities of `go-feature-flag` SDK. +To configure it please refer to the [type `exporter` section](./configure_relay_proxy#exporter) of the configuration documentation. + +## Service endpoints +The Relay Proxy defines many HTTP/HTTPS endpoints. +Most of these are proxies for GO Feature Flag services, to be used by SDKs that connect to the Relay Proxy. +Others are specific to the Relay Proxy, such as for monitoring its status. + +Please refer to [endpoints documentation](./relay_proxy_endpoints) to get the full details on available REST API endpoints. diff --git a/website/versioned_docs/version-v1.24.1/relay_proxy/index.mdx b/website/versioned_docs/version-v1.24.1/relay_proxy/index.mdx new file mode 100644 index 00000000000..10049d55642 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/relay_proxy/index.mdx @@ -0,0 +1,20 @@ +--- +title: Use the relay proxy +description: GO Feature Flag Relay Proxy is a powerful tool that allows developers to easily integrate feature flagging functionality into their applications. It is a simple API service that can be called directly through the API or via the available OpenFeature providers. The service wraps the GO Feature Flag golang module to evaluate your flags and allows it to be used with all the available languages. +--- + +import DocCardList from '@theme/DocCardList'; + +# Use the relay proxy + +The GO Feature Flag Relay Proxy serves as the **backend** for your feature flag solution, housing all the necessary logic for feature flag management. + +It provides APIs to enable remote access to the GO Feature Flag system. While you have the option to interact directly with these APIs, it is recommended to use the **Openfeature SDK** and the appropriate **provider** for your programming language for a seamless experience. + +The relay proxy is designed to be **simple, lightweight, and stateless**. It operates without the need for any databases or complex systems, as it loads feature flag configuration files from a specified location and stores them in memory. Periodic polling ensures the proxy stays up-to-date with any changes in the configuration. This straightforward setup makes installation and usage incredibly easy and hassle-free. + +![](/docs/relay_proxy/arch.png) + +--- + + \ No newline at end of file diff --git a/website/versioned_docs/version-v1.24.1/relay_proxy/install_relay_proxy.md b/website/versioned_docs/version-v1.24.1/relay_proxy/install_relay_proxy.md new file mode 100644 index 00000000000..6b176b25e76 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/relay_proxy/install_relay_proxy.md @@ -0,0 +1,31 @@ +--- +sidebar_position: 20 +title: Installation +description: Relay proxy is the component that will evaluate the flags, this page explain how to install it. +--- + +# Install the relay proxy + +## When should I use the GO Feature Flag Relay Proxy? +- If you want to access your feature flag using an API instead of the [`thomaspoignant/go-feature-flag`](https://github.com/thomaspoignant/go-feature-flag) SDK. +- If you are not using GOlang to build your application. +- If you want to reduce the number of accesses to your configuration flag by centralizing them. + + +## Install using Homebrew (mac and linux) +```shell +brew install go-feature-flag +``` + +## Install using Scoop (windows) +```shell +scoop install go-feature-flag +``` + +## Install using docker +```shell +docker pull thomaspoignant/go-feature-flag:latest +``` +:::info +More info in the [dockerhub page](https://hub.docker.com/r/thomaspoignant/go-feature-flag). +::: diff --git a/website/versioned_docs/version-v1.24.1/relay_proxy/monitor_relay_proxy.md b/website/versioned_docs/version-v1.24.1/relay_proxy/monitor_relay_proxy.md new file mode 100644 index 00000000000..5d13662fa2d --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/relay_proxy/monitor_relay_proxy.md @@ -0,0 +1,55 @@ +--- +sidebar_position: 80 +title: Monitoring / Tracing +description: Monitoring and Tracing of the relay proxy. +--- + +## Tracing + +The **relay proxy** is able to trace the requests it is handling. This is done by using OpenTelemetry. + +### Configuration +To configure the tracing, you need to set in the configuration the endpoint to your OTLP collector. +```yaml +# ... +openTelemetryOtlpEndpoint: http://localhost:4318 +# ... +``` + +All your requests will be traced and sent to the collector with the service name **`go-feature-flag`**. + +:::note +If you want to try the OpenTelemetry integration locally, follow this [README](https://github.com/thomaspoignant/go-feature-flag/tree/main/cmd/relayproxy/testdata/opentelemetry) +to setup Jaeger and see your traces. +::: + +## Monitoring + +The **relay proxy** offers some endpoints for you to be able to see how it behaves. + +### `/health` +Making a **GET** request to the URL path `/health` will tell you if the relay proxy is ready to +serve traffic. + +This is useful especially for loadbalancer to know that they can send traffic to the service. + +### `/info` +Making a **GET** request to the URL path `/info` will give you information about the actual state +of the relay proxy. + +### `/metrics` +This endpoint is providing metrics about the relay proxy in the prometheus format. + +## Use specific port for the monitoring +You can configure a different port for the monitoring endpoints. +This is useful if you want to expose the monitoring endpoints on a different port than the main service. + +```yaml +# ... +monitoringPort: 1032 +# ... +``` + +:::note +By default the monitoring endpoints are exposed on the same port as the main service. +::: diff --git a/website/versioned_docs/version-v1.24.1/relay_proxy/relay_proxy_endpoints.md b/website/versioned_docs/version-v1.24.1/relay_proxy/relay_proxy_endpoints.md new file mode 100644 index 00000000000..192c186e1d0 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/relay_proxy/relay_proxy_endpoints.md @@ -0,0 +1,26 @@ +--- +sidebar_position: 60 +title: API endpoints +description: Description of the available endpoints in the relay proxy. +--- + +# Relay proxy endpoints + +The most updated documentation about the relay proxy endpoints is the Swagger docs _(see [Swagger section](#swagger) to see how to access to the documentation)_. + +### Swagger +Swagger endpoint is serving a [swagger UI](https://swagger.io/tools/swagger-ui/) to test your REST endpoints. +By default, this endpoint is not exposed, you need to have this configuration in your **relay proxy** configuration file: + +```yaml +# ... + +enableSwagger: true +host: my-proxy-domain.com # the DNS to access the proxy +``` + +When enabled, you can go to the `/swagger/` endpoint with your browser, and you will have access to the Swagger UI for the relay proxy. + +## [OpenAPI documentation](/API_relayproxy) + +If you don't want to install the relay proxy to check the endpoints, you can go to this [**OpenAPI documentation**](/API_relayproxy) directly. diff --git a/website/versioned_docs/version-v1.24.1/tooling/_category_.json b/website/versioned_docs/version-v1.24.1/tooling/_category_.json new file mode 100644 index 00000000000..f7b6b1dd4b9 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/tooling/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 60, + "label":"Tools", + "collapsible": true, + "collapsed": true +} diff --git a/website/versioned_docs/version-v1.24.1/tooling/autocomplete.md b/website/versioned_docs/version-v1.24.1/tooling/autocomplete.md new file mode 100644 index 00000000000..8455c0aba31 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/tooling/autocomplete.md @@ -0,0 +1,13 @@ +--- +sidebar_position: 20 +title: Auto-complete +description: Flag configuration auto-complete +--- + +# Flag configuration auto-complete + +GO Feature Flag offers a way to have auto-completion while creating a flag file. + +To achieve this we publish a `jsonschema` on [schemastore](https://www.schemastore.org). The store is used by all major IDEs such as `vscode`, `intelliJ`, and others. + +To enable it, you just have to use the extension `.goff.yaml` for your configuration file, and it will be automatically available for you _(example: `flag.goff.yaml`)_. diff --git a/website/versioned_docs/version-v1.24.1/tooling/linter.mdx b/website/versioned_docs/version-v1.24.1/tooling/linter.mdx new file mode 100644 index 00000000000..cfd67c57079 --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/tooling/linter.mdx @@ -0,0 +1,117 @@ +--- +sidebar_position: 10 +title: Linter +description: Lint your configuration file +--- + + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Lint your configuration file + +Ensuring the accuracy of your configuration is vital for the **GO Feature Flag** to function as expected. +This is why we have introduced the `go-feature-flag-lint`, a command line tool that validates whether a flag file can be parsed by **GO Feature Flag**. + +:::tip +We recommend you to use this command line in your CI/CD pipelines to avoid any unforeseen issues. +::: + +## Install the linter + +### Install using Homebrew (mac and linux) +```shell +brew tap thomaspoignant/homebrew-tap +brew install go-feature-flag-lint +``` + +### Install using Scoop (windows) +```shell +scoop bucket add org https://github.com/go-feature-flag/scoop.git +scoop install go-feature-flag-lint +``` + +### Install using Docker +```shell +docker pull thomaspoignant/go-feature-flag-lint:latest +``` + +## Use the linter + +```shell +./go-feature-flag-lint \ + --input-format=yaml \ + --input-file=/input/my-go-feature-flag-config.goff.yaml +``` + +The command line has 2 arguments you should specify. + +| param | description | +|------------------|-------------------------------------------------------------------------------------------------------------------| +| `--input-file` | **(mandatory)** The location of your configuration file. | +| `--input-format` | **(mandatory)** The format of your current configuration file.
Available formats are `yaml`, `json`, `toml`. | + +## Use the linter in your CI (continuous integration) + + + +You can run `go-feature-flag-lint` using GitHub actions: + + + + +```yaml +name: "Build" +on: + push: + branches: + - main + pull_request: + types: [ opened, synchronize, reopened ] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: docker://thomaspoignant/go-feature-flag-lint:latest + with: + args: --input-file=/github/workspace/path/to/your/config.yaml --input-format=yaml +``` + + + + +```yaml +version: 2.1 +jobs: + build: + docker: + - image: cimg/base:2022.05 + + steps: + - checkout + - run: curl -L $(curl -s https://api.github.com/repos/thomaspoignant/go-feature-flag/releases/latest | jq -r '.assets[] | select(.name|match("Linux_x86_64.tar.gz$")) | .browser_download_url' | grep 'go-feature-flag-lint') --output release.tar.gz && tar -zxvf release.tar.gz + - run: ./go-feature-flag-lint --input-format=yaml --input-file=flag-config.goff.yaml # please put the right file name +``` + + + + +```yaml +image: ubuntu +lint-job: + stage: build + + before_script: + - apt-get -qq update + - apt-get install -y jq curl + + script: + - curl -L $(curl -s https://api.github.com/repos/thomaspoignant/go-feature-flag/releases/latest | jq -r '.assets[] | select(.name|match("Linux_x86_64.tar.gz$")) | .browser_download_url' | grep 'go-feature-flag-lint') --output release.tar.gz && tar -zxvf release.tar.gz + - ./go-feature-flag-lint --input-format=yaml --input-file=flag-config.goff.yaml # please put the right file name +``` + + + + diff --git a/website/versioned_docs/version-v1.24.1/tooling/migrate_v0_v1.md b/website/versioned_docs/version-v1.24.1/tooling/migrate_v0_v1.md new file mode 100644 index 00000000000..7e17a8e65ef --- /dev/null +++ b/website/versioned_docs/version-v1.24.1/tooling/migrate_v0_v1.md @@ -0,0 +1,59 @@ +--- +sidebar_position: 90 +description: How to migrate from v0.x.x to v1.x.x +--- + +# Migrate from v0.x.x to v1.x.x + +:::info +Version `v1.0.0` has introduced a new flag format that push the limits of **GO Feature Flag** even further. +**NOTE:** The flag format from all the versions `v0.x.x` are still compatible and supported by the `v1.0.0`. +::: + +A command line is available to help you to convert your actual configuration file to the version `v1.x.x`. + + +## Install the migration command line + +### Install using Homebrew (mac and linux) +```shell +brew tap thomaspoignant/homebrew-tap +brew install go-feature-flag-migration-cli +``` + +### Install using Scoop (windows) +```shell +scoop bucket add org https://github.com/go-feature-flag/scoop.git +scoop install go-feature-flag-migration-cli +``` + +### Install using Docker +```shell +docker pull thomaspoignant/go-feature-flag-migration-cli:latest +``` + +## Use the migration command line + +```shell +./go-feature-flag-migration-cli \ + --input-format=yaml \ + --input-file=/config/my-go-feature-flag-config-v0.x.x.yaml \ + --output-format=yaml \ + --output-file=/config/my-go-feature-flag-config-v1.x.x.yaml +``` + +The command line has 4 arguments you should specify. + +- `input-format`: Format of your input file (`YAML`, `JSON` or `TOML`). +- `input-file`: Location of the flag file you want to convert. +- `output-format`: Format of your output file (`YAML`, `JSON` or `TOML`). +- `output-file`: Location of the converted flag file. + + +## Update your flag file + +When your file is ready, you just have to replace your file in the location where GO Feature Flag is retrieves it. + +:::tip +If for any reason your file is not readable by GO Feature Flag, it will not break anything, we will keep the latest version we have in memory. +::: diff --git a/website/versioned_sidebars/version-v1.24.1-sidebars.json b/website/versioned_sidebars/version-v1.24.1-sidebars.json new file mode 100644 index 00000000000..caea0c03ba6 --- /dev/null +++ b/website/versioned_sidebars/version-v1.24.1-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/website/versions.json b/website/versions.json index 3a76c20125f..4761b722e31 100644 --- a/website/versions.json +++ b/website/versions.json @@ -1,4 +1,5 @@ [ + "v1.24.1", "v1.24.0", "v1.23.1", "v1.23.0",