From c872587eb897f7d7ea87369faa1ae237a10ac48d Mon Sep 17 00:00:00 2001 From: Thomas Poignant Date: Wed, 20 Jul 2022 11:14:29 +0200 Subject: [PATCH 1/4] fix HTML issues Signed-off-by: Thomas Poignant --- README.md | 2 +- docs/index.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 348ee15b0f1..44d058676e7 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Go version License Mentioned in Awesome Go - Join us on slack + Join us on slack

**Feature flags with no complex system to maintain!** diff --git a/docs/index.md b/docs/index.md index 16750baa321..28edfbcf553 100644 --- a/docs/index.md +++ b/docs/index.md @@ -17,8 +17,8 @@ description: go-feature-flag is a simple and complete feature flag solution, wi GoDoc Go version License - Mentioned in Awesome Go - Join us on slack + Mentioned in Awesome Go + Join us on slack

# go-feature-flag From bf4d99235a3d64496c5e7e7c2a085e48c0914e26 Mon Sep 17 00:00:00 2001 From: Thomas Poignant Date: Wed, 20 Jul 2022 15:24:26 +0200 Subject: [PATCH 2/4] fix some issues Signed-off-by: Thomas Poignant --- CONTRIBUTING.md | 10 +- SECURITY.md | 1 + docs/data_collection/index.md | 97 ++++++----- docs/data_collection/s3.md | 9 +- docs/faq.md | 20 +-- docs/flag_file/github.md | 21 ++- docs/flag_file/google_cloud_storage.md | 16 +- docs/flag_file/http.md | 20 ++- docs/flag_format.md | 230 +++++++++++++------------ docs/index.md | 2 +- docs/notifier/custom.md | 4 +- docs/notifier/index.md | 1 + docs/notifier/slack.md | 9 +- docs/notifier/webhook.md | 21 ++- docs/rollout/progressive.md | 111 ++++++------ docs/rollout/scheduled.md | 118 ++++++------- 16 files changed, 370 insertions(+), 320 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 45b82171b11..77754103de3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,11 +4,13 @@ When contributing to this repository, please first discuss the change you wish t Please note we have a [code of conduct](CODE_OF_CONDUCT.md), please follow it in all your interactions with the project. # Pull Request Process + 1. Ensure any install or build dependencies are removed before the end of the layer when doing a build. 2. Please mention the issue in your PR description. 3. Expect to be taken seriously, if there are some feedbacks, feel free to discuss about it, your opinion can be better than mine. # Coding standards + A library is easier to use, and easier for contributors to work on if it has a consistent, unified style, approach, and layout. We are using [pre-commit](https://pre-commit.com/) to lint before each commit, I would recommend you to use it. @@ -17,9 +19,11 @@ pre-commit install ``` ## Tests + Every feature or bug should come with an associate test to keep the coverage as high as possible. ## Documentation + We are maintaining 2 documentations: - [README.md](README.md) which contains everything you need to know to start working with the module. - [go-feature-flag website](https://thomaspoignant.github.io/go-feature-flag/) which is the full detail documentation of the module. @@ -27,6 +31,7 @@ We are maintaining 2 documentations: If your contribution has impact on the documentation, please check both version. ### How to run the documentation website locally + For the documentation website we are using [mkdocs](https://www.mkdocs.org/) with the "[Material for MkDocs](https://squidfunk.github.io/mkdocs-material/)" theme. To run it locally just use the docker image: ```shell @@ -35,11 +40,14 @@ docker run --rm -it -p 8000:8000 -v ${PWD}:/docs squidfunk/mkdocs-material The website will be available on http://localhost:8000/ ## Sonar + Sonarcloud is used in the project, it will comment your PR to give you feedback on your code. -# Continuous integration +### Continuous integration + We have a list of steps on each PR. The CI is running: + - Tests - Coverage - Code quality diff --git a/SECURITY.md b/SECURITY.md index 340d1aeda76..e8dbe9ef2d8 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,6 +1,7 @@ # Security Policy ## Reporting a Vulnerability + If you find a vulnerability please open an issue *(bug report)* with the flag `security` and affect the issue to `thomaspoignant`. I will look into it as soon as possible and will give you more information in the issue as soon I have somne. diff --git a/docs/data_collection/index.md b/docs/data_collection/index.md index e85680acd6d..a912c6c6eb4 100644 --- a/docs/data_collection/index.md +++ b/docs/data_collection/index.md @@ -1,4 +1,5 @@ -# Data format / Export data +# Data format / Export data + If you want to export data about how your flag are used, you can use the **`DataExporter`**. It collects all the variations events and can save these events on several locations: @@ -9,7 +10,9 @@ It collects all the variations events and can save these events on several locat - [Google Cloud Storage](google_cloud_storage.md) *- export your variation usages by calling a webhook.* 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. It represents individual flag evaluations and are considered "full fidelity" events. @@ -27,30 +30,33 @@ It represents individual flag evaluations and are considered "full fidelity" eve "default": false } ``` + ### 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
**Dafault**: 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. | -|**`default`** | (Optional) This value is set to true if feature flag evaluation failed, in which case the value returned was the default value passed to variation. | +| 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
**Dafault**: 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. | +| **`default`** | (Optional) This value is set to true if feature flag evaluation failed, in which case the value returned was 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 send them in bulk to the exporter. +To avoid spamming your location everytime you have a variation called, `go-feature-flag` is storing in memory all the events and send 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 you don't want to export, you can use `trackEvents` fields on these specific flags to disable the data export *(see [flag file format](../flag_format.md))*. ### Example + ```go linenums="1" ffclient.Config{ // ... @@ -67,51 +73,50 @@ ffclient.Config{ ### 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**.| - +| 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 are 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 linenums="1" hl_lines="6" - test-flag: - percentage: 50 - true: "B" - false: "A" - default: "Default" - trackEvents: false - ``` +``` yaml linenums="1" hl_lines="6" +test-flag: + percentage: 50 + true: "B" + false: "A" + default: "Default" + trackEvents: false +``` === "JSON" - ``` json linenums="1" hl_lines="7" - { - "test-flag": { - "percentage": 50, - "true": "B", - "false": "A", - "default": "Default", - "trackEvents": false - } - } - ``` +``` json linenums="1" hl_lines="7" +{ + "test-flag": { + "percentage": 50, + "true": "B", + "false": "A", + "default": "Default", + "trackEvents": false + } +} +``` === "TOML" - ``` toml linenums="1" hl_lines="6" - [test-flag] - percentage = 50.0 - true = "B" - false = "A" - default = "Default" - trackEvents = false - ``` - +``` toml linenums="1" hl_lines="6" +[test-flag] +percentage = 50.0 +true = "B" +false = "A" +default = "Default" +trackEvents = false +``` diff --git a/docs/data_collection/s3.md b/docs/data_collection/s3.md index 5ce189df57f..12684204509 100644 --- a/docs/data_collection/s3.md +++ b/docs/data_collection/s3.md @@ -9,10 +9,10 @@ Everytime the `FlushInterval` or `MaxEventInMemory` is reached a new file will b ![export in S3 screenshot](../assets/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 linenums="1" ffclient.Config{ // ... @@ -35,13 +35,14 @@ ffclient.Config{ ``` ## Configuration fields + | Field | Description | |---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `Bucket ` | Name of your S3 Bucket. | -| `AwsConfig ` | An instance of `aws.Config` that configure your access to AWS *(see [this documentation for more info](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html))*. | +| `Bucket` | Name of your S3 Bucket. | +| `AwsConfig` | An instance of `aws.Config` that configure your access to AWS *(see [this documentation for more info](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html))*. | | `CsvTemplate` | *(optional)* CsvTemplate is used if your output format is CSV. This field will be ignored if you are using another format 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}}\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 replacement 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 format are **`JSON`** and **`CSV`**. *(Default: `JSON`)* | -| `S3Path ` | *(optional)* The location of the directory in S3. | +| `S3Path` | *(optional)* The location of the directory in S3. | Check the [godoc for full details](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/exporter/s3exporter). diff --git a/docs/faq.md b/docs/faq.md index 65edfab5c83..9ea4ebcdc82 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -1,17 +1,17 @@ # Frequently Asked Questions -### Why using feature flags? +## Why using feature flags? This one of most common question I get. -Feature flags are a software development technique that turns certain functionality on and off during runtime, without +Feature flags are a software development technique that turns certain functionality on and off during runtime, without deploying new code. -It allows you to decouple **deploy** and **release**, giving you better control and more experimentation over the full +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? -The lifecycle of your flags is key if you don't want to have un-used things everywhere in your code. +## What is the lifecycle of a flag? +The lifecycle of your flags is key if you don't want to have un-used things everywhere in your code. 1. Start by creating the flag in your configuration file *(with 0% to avoid affecting your users)*. 2. Evaluate the flag in your code *(see [variation](users.md#variation))*. @@ -23,22 +23,22 @@ The lifecycle of your flags is key if you don't want to have un-used things ever --- -### What happen if my configuration file is not reachable/deleted? +## What happen if my configuration file is not reachable/deleted? If while you are on production 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, if the file is not reachable to module will fail to initialize except if you have set the +If you start a new instance, if the file is not reachable to module will fail to initialize except if you have set the option `StartWithRetrieverError` in the config. With this option, we will serve the SDK default value *(the 3rd param in your variation)* until the flag becomes available again. --- -### What is the best rollout strategy? +## What is the best rollout strategy? The lib gives you a lot of strategies to rollout your flags, there is no better one, it always depends on the context of your release. -- If your release is not critical and, you just want an easy cut-off strategy, you can pass your flag from 0% to 100% for +- If your release is not critical and, you just want an easy cut-off strategy, you can pass your flag from 0% to 100% for all your users - If you are scared that your infrastructure can be impacted by the new feature, a progressive rollout can help you to impact users over time and to be able to check how your system handle it. @@ -49,7 +49,7 @@ You have an endless list of rollout strategies depending on what is your feature --- -### How we ensure that users affected by the feature flags are not always the same? +## How we ensure that users affected by the feature flags are not always the same? To avoid always have the same users affected by a flag, the hash we compute that allows us to determine if the user is part of the percentage is not computed only based on the user key but a combination of the user key and the flag name. diff --git a/docs/flag_file/github.md b/docs/flag_file/github.md index 92bea9c1de6..bfeb9b6a90f 100644 --- a/docs/flag_file/github.md +++ b/docs/flag_file/github.md @@ -1,10 +1,13 @@ # 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. + +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 linenums="1" err := ffclient.Init(ffclient.Config{ PollingInterval: 3 * time.Second, @@ -20,13 +23,13 @@ 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| +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/docs/flag_file/google_cloud_storage.md b/docs/flag_file/google_cloud_storage.md index 7e739b3af19..3be6e63700a 100644 --- a/docs/flag_file/google_cloud_storage.md +++ b/docs/flag_file/google_cloud_storage.md @@ -1,6 +1,6 @@ # Google Cloud Storage -The [**Google Cloud Storage Retriever**](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/retriever/gcstorageretriever/#Retriever) +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. @@ -9,12 +9,13 @@ Storage. ```go linenums="1" err := ffclient.Init(ffclient.Config{ - PollingInterval: 3 * time.Second, - Retriever: &gcstorageretriever.Retriever{ - Options: []option.ClientOption{option.WithoutAuthentication()}, - Bucket: "2093u4pkasjc3", - Object: "flags.yaml", - } + PollingInterval: 3 * time.Second, + Retriever: &gcstorageretriever.Retriever{ + Options: []option.ClientOption{option.WithoutAuthentication() + }, + Bucket: "2093u4pkasjc3", + Object: "flags.yaml", + } }) defer ffclient.Close() ``` @@ -28,4 +29,3 @@ To configure your Google Cloud Storage file location: | **`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/docs/flag_file/http.md b/docs/flag_file/http.md index c9acef0a84a..e47bf1125a2 100644 --- a/docs/flag_file/http.md +++ b/docs/flag_file/http.md @@ -1,8 +1,10 @@ # HTTP endpoint -The [**HTTP Retriever**](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/retriever/httpretriever/#Retriever) + +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 linenums="1" err := ffclient.Init(ffclient.Config{ PollingInterval: 3 * time.Second, @@ -13,13 +15,15 @@ err := ffclient.Init(ffclient.Config{ }) defer ffclient.Close() ``` + ## Configuration fields + To configure your HTTP endpoint: -| Field | Description | -|---|---| -|**`URL`**| Location where to retrieve the file
_(ex: 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).| +| Field | Description | +|---------------|-----------------------------------------------------------------------------------------------------------------| +| __`URL`__ | Location where 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/docs/flag_format.md b/docs/flag_format.md index 214f86f381a..b80d0cc0fc0 100644 --- a/docs/flag_format.md +++ b/docs/flag_format.md @@ -1,118 +1,127 @@ # 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))*. +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))*. -The easiest way to create your configuration file is to used [**GO Feature Flag Editor** available at https://thomaspoignant.github.io/go-feature-flag-editor/](https://thomaspoignant.github.io/go-feature-flag-editor/). +The easiest way to create your configuration file is to used +[**GO Feature Flag Editor** available at https://thomaspoignant.github.io/go-feature-flag-editor/](https://thomaspoignant.github.io/go-feature-flag-editor/). 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://thomaspoignant.github.io/go-feature-flag-editor/) a simple editor to create your files. + +Creating the first version of the flag is not always pleasant, that's why we have created +[**GO Feature Flag Editor**](https://thomaspoignant.github.io/go-feature-flag-editor/) a simple editor to create your files. ## Example + A flag configuration looks like: === "YAML" - ``` yaml linenums="1" - test-flag: - percentage: 100 - rule: key eq "random-key" - true: true - false: false - default: false - disable: false - trackEvents: true - version: 1 - rollout: - experimentation: - start: 2021-03-20T00:00:00.10-05:00 - end: 2021-03-21T00:00:00.10-05:00 - - test-flag2: - rule: key eq "not-a-key" - percentage: 100 - true: true - false: false - default: false - version: 12 - ``` +``` yaml linenums="1" +test-flag: + percentage: 100 + rule: key eq "random-key" + true: true + false: false + default: false + disable: false + trackEvents: true + version: 1 + rollout: + experimentation: + start: 2021-03-20T00:00:00.10-05:00 + end: 2021-03-21T00:00:00.10-05:00 + +test-flag2: + rule: key eq "not-a-key" + percentage: 100 + true: true + false: false + default: false + version: 12 +``` === "JSON" - ``` json linenums="1" - { - "test-flag": { - "percentage": 100, - "rule": "key eq \"random-key\"", - "true": true, - "false": false, - "default": false, - "disable": false, - "trackEvents": true, - "version": 1, - "rollout": { - "experimentation": { - "start": "2021-03-20T05:00:00.100Z", - "end": "2021-03-21T05:00:00.100Z" - } - } - }, - "test-flag2": { - "rule": "key eq \"not-a-key\"", - "percentage": 100, - "true": true, - "false": false, - "default": false, - "version": 12 +``` json linenums="1" +{ + "test-flag": { + "percentage": 100, + "rule": "key eq \"random-key\"", + "true": true, + "false": false, + "default": false, + "disable": false, + "trackEvents": true, + "version": 1, + "rollout": { + "experimentation": { + "start": "2021-03-20T05:00:00.100Z", + "end": "2021-03-21T05:00:00.100Z" } } - ``` + }, + "test-flag2": { + "rule": "key eq \"not-a-key\"", + "percentage": 100, + "true": true, + "false": false, + "default": false, + "version": 12 + } +} +``` === "TOML" - ``` toml linenums="1" - [test-flag] - percentage = 100.0 - rule = "key eq \"random-key\"" - true = true - false = false - default = false - disable = false - trackEvents = true - version = 1.0 - - [test-flag.rollout] - - [test-flag.rollout.experimentation] - start = 2021-03-20T05:00:00.100Z - end = 2021-03-21T05:00:00.100Z - - [test-flag2] - rule = "key eq \"not-a-key\"" - percentage = 100.0 - true = true - false = false - default = false - version = 12.0 - ``` +``` toml linenums="1" +[test-flag] +percentage = 100.0 +rule = "key eq \"random-key\"" +true = true +false = false +default = false +disable = false +trackEvents = true +version = 1.0 + +[test-flag.rollout] + + [test-flag.rollout.experimentation] + start = 2021-03-20T05:00:00.100Z + end = 2021-03-21T05:00:00.100Z + +[test-flag2] +rule = "key eq \"not-a-key\"" +percentage = 100.0 +true = true +false = false +default = false +version = 12.0 +``` ## Format details -| Field | Description | -|:---:|---| -| **flag-key** | Name of your flag.
It must be unique.
*On the example the flag keys are **`test-flag`** and **`test-flag2`**.*| -| `true` | Value returned by the flag if apply to the user *(rule is evaluated to true)* and the user is in the active percentage.| -| `false`| Value returned by the flag if apply to the user *(rule is evaluated to true)* and the user is **not** in the active percentage.| -| `default` |Value returned by the flag if not apply to the user *(rule is evaluated to false).*| -| `percentage` |*(optional)*
Percentage of the users who should be affected by the flag.
**Default: 0**

The percentage is computed by calculating a hash of the user key *(100000 variations)*, it means that you can have 3 numbers after the comma.| -| `rule` |*(optional)*
Condition to determine on which user the flag should be applied.
Rule format is described in the [rule format section](#rule-format).
**If no rule is set, the flag applies to all users *(percentage still apply)*.**| -| `disable` |*(optional)*
True if the flag is disabled.
**Default: `false`**| -| `trackEvents` |*(optional)*
False if you don't want to export the data in your data exporter.
**Default: `true`**| -| `version` |*(optional)*
The version is the version of your flag.
This number is used to display the information in the notifiers and data collection, you have to update it your self.
**Default: 0**| -| `rollout` |*(optional)*
rollout contains a specific rollout strategy you want to use.
**See [rollout section](rollout/index.md) for more details.**| +| Field | Description | +|:-------------:|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **flag-key** | Name of your flag.
It must be unique.
*On the example the flag keys are **`test-flag`** and **`test-flag2`**.* | +| `true` | Value returned by the flag if apply to the user *(rule is evaluated to true)* and the user is in the active percentage. | +| `false` | Value returned by the flag if apply to the user *(rule is evaluated to true)* and the user is **not** in the active percentage. | +| `default` | Value returned by the flag if not apply to the user *(rule is evaluated to false).* | +| `percentage` | *(optional)*
Percentage of the users who should be affected by the flag.
**Default: 0**

The percentage is computed by calculating a hash of the user key *(100000 variations)*, it means that you can have 3 numbers after the comma. | +| `rule` | *(optional)*
Condition to determine on which user the flag should be applied.
Rule format is described in the [rule format section](#rule-format).
**If no rule is set, the flag applies to all users *(percentage still apply)*.** | +| `disable` | *(optional)*
True if the flag is disabled.
**Default: `false`** | +| `trackEvents` | *(optional)*
False if you don't want to export the data in your data exporter.
**Default: `true`** | +| `version` | *(optional)*
The version is the version of your flag.
This number is used to display the information in the notifiers and data collection, you have to update it your self.
**Default: 0** | +| `rollout` | *(optional)*
rollout contains a specific rollout strategy you want to use.
**See [rollout section](rollout/index.md) for more details.** | ## Rule format + The rule format is based on the [`nikunjy/rules`](https://github.com/nikunjy/rules) library. All the operations can be written capitalized or lowercase (ex: `eq` or `EQ` can be used). @@ -120,21 +129,20 @@ Logical Operations supported are `AND` `OR`. Compare Expression and their definitions (`a|b` means you can use either one of the two `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 | +| 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 @@ -142,11 +150,12 @@ Compare Expression and their definitions (`a|b` means you can use either one of - 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")` - ``` + *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 @@ -164,14 +173,17 @@ When an environment is set, it adds a new field in your user called **`env`** th It means that you can decide to activate a flag only for some **environment**. **Example of rules based on the environment:** + ```yaml # Flag activate only in dev rule: env == "dev" ``` + ```yaml # Flag used only in dev and staging environment rule: (env == "dev") or (env == "staging") ``` + ```yaml # Flag used on non prod environments except for the user 1234 in prod rule: (env != "prod") or (user_id == 1234) diff --git a/docs/index.md b/docs/index.md index 28edfbcf553..73c96451d97 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,7 +4,7 @@ description: go-feature-flag is a simple and complete feature flag solution, wi ---

- go-feature-flag logo + go-feature-flag logo

diff --git a/docs/notifier/custom.md b/docs/notifier/custom.md index 81d8198b571..70e26dc6bac 100644 --- a/docs/notifier/custom.md +++ b/docs/notifier/custom.md @@ -1,5 +1,7 @@ # 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. + +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. ```go linenums="1" import ( diff --git a/docs/notifier/index.md b/docs/notifier/index.md index 4259cedfa36..b4261ec557b 100644 --- a/docs/notifier/index.md +++ b/docs/notifier/index.md @@ -1,4 +1,5 @@ # Notifiers + 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. diff --git a/docs/notifier/slack.md b/docs/notifier/slack.md index 5b668ec0de5..eb4a39050e3 100644 --- a/docs/notifier/slack.md +++ b/docs/notifier/slack.md @@ -1,9 +1,14 @@ # 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. -

![slack notification example](../assets/slack_notification.png)
+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. + +
+ ![slack notification example](../assets/slack_notification.png) +
## 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. diff --git a/docs/notifier/webhook.md b/docs/notifier/webhook.md index 47cd665a5a6..cedb380741a 100644 --- a/docs/notifier/webhook.md +++ b/docs/notifier/webhook.md @@ -1,11 +1,12 @@ # Webhook Notifier + The **Webhook notifier** will perform an HTTP POST request to the specified endpoint everytime that 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. +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 linenums="1" +```go linenums="1" ffclient.Config{ // ... Notifiers: []notifier.Notifier{ @@ -22,13 +23,15 @@ ffclient.Config{ ``` ## 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 add 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.**| + +| 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 add 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.** | ## Format + If you have configured a webhook, a `POST` request will be sent to the `EndpointURL` with a body in this format: ```json linenums="1" @@ -99,7 +102,9 @@ If you have configured a webhook, a `POST` request will be sent to the `Endpoint ``` ## 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. + +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. !!! Danger 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 have a man in the middle attack. diff --git a/docs/rollout/progressive.md b/docs/rollout/progressive.md index dbd836b67d2..68366ea6b47 100644 --- a/docs/rollout/progressive.md +++ b/docs/rollout/progressive.md @@ -2,78 +2,79 @@ 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. +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" - ``` yaml linenums="1" hl_lines="5-12" - progressive-flag: - true: "B" - false: "A" - default: "Default" - rollout: - progressive: - percentage: - initial: 0 - end: 100 - releaseRamp: - start: 2021-03-20T00:00:00.10-05:00 - end: 2021-03-21T00:00:00.10-05:00 - ``` +``` yaml linenums="1" hl_lines="5-12" +progressive-flag: + true: "B" + false: "A" + default: "Default" + rollout: + progressive: + percentage: + initial: 0 + end: 100 + releaseRamp: + start: 2021-03-20T00:00:00.10-05:00 + end: 2021-03-21T00:00:00.10-05:00 +``` === "JSON" - ``` json linenums="1" hl_lines="6-17" - { - "progressive-flag": { - "true": "B", - "false": "A", - "default": "Default", - "rollout": { - "progressive": { - "percentage": { - "initial": 0, - "end": 100 - }, - "releaseRamp": { - "start": "2021-03-20T05:00:00.100Z", - "end": "2021-03-21T05:00:00.100Z" - } - } +``` json linenums="1" hl_lines="6-17" +{ + "progressive-flag": { + "true": "B", + "false": "A", + "default": "Default", + "rollout": { + "progressive": { + "percentage": { + "initial": 0, + "end": 100 + }, + "releaseRamp": { + "start": "2021-03-20T05:00:00.100Z", + "end": "2021-03-21T05:00:00.100Z" } } } - ``` + } +} +``` === "TOML" - ``` toml linenums="1" hl_lines="6-16" - [progressive-flag] - true = "B" - false = "A" - default = "Default" - - [progressive-flag.rollout] - - [progressive-flag.rollout.progressive] - - [progressive-flag.rollout.progressive.percentage] - initial = 0.0 - end = 100.0 - - [progressive-flag.rollout.progressive.releaseRamp] - start = 2021-03-20T05:00:00.100Z - end = 2021-03-21T05:00:00.100Z - ``` +``` toml linenums="1" hl_lines="6-16" +[progressive-flag] +true = "B" +false = "A" +default = "Default" + + [progressive-flag.rollout] + + [progressive-flag.rollout.progressive] + + [progressive-flag.rollout.progressive.percentage] + initial = 0.0 + end = 100.0 + + [progressive-flag.rollout.progressive.releaseRamp] + start = 2021-03-20T05:00:00.100Z + end = 2021-03-21T05:00:00.100Z +``` ## 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 of 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 at which level it ends (`end`).
**Default: `initial` = `0` and `end` = `100`**| +| 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 of 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 at which level it ends (`end`).
**Default: `initial` = `0` and `end` = `100`** | diff --git a/docs/rollout/scheduled.md b/docs/rollout/scheduled.md index 4f20933bcab..98a854cb8c2 100644 --- a/docs/rollout/scheduled.md +++ b/docs/rollout/scheduled.md @@ -6,71 +6,73 @@ While this sounds deceptively straightforward, it unlocks the potential for user 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" - ```yaml linenums="1" hl_lines="6-13" - scheduled-flag: - true: "B" - false: "A" - default: "Default" - rollout: - scheduled: - steps: - - date: 2020-04-10T00:00:00.10+02:00 - rule: beta eq "true" - percentage: 100 - - - date: 2022-05-12T15:36:00.10+02:00 - rule: beta eq "false" - ``` +```yaml linenums="1" hl_lines="6-13" +scheduled-flag: + true: "B" + false: "A" + default: "Default" + rollout: + scheduled: + steps: + - date: 2020-04-10T00:00:00.10+02:00 + rule: beta eq "true" + percentage: 100 + + - date: 2022-05-12T15:36:00.10+02:00 + rule: beta eq "false" +``` + === "JSON" - ```json linenums="1" hl_lines="6-19" - { - "scheduled-flag": { - "true": "B", - "false": "A", - "default": "Default", - "rollout": { - "scheduled": { - "steps": [ - { - "date": "2020-04-09T22:00:00.100Z", - "rule": "beta eq \"true\"", - "percentage": 100 - }, - { - "date": "2022-05-12T13:36:00.100Z", - "rule": "beta eq \"false\"" - } - ] +```json linenums="1" hl_lines="6-19" +{ + "scheduled-flag": { + "true": "B", + "false": "A", + "default": "Default", + "rollout": { + "scheduled": { + "steps": [ + { + "date": "2020-04-09T22:00:00.100Z", + "rule": "beta eq \"true\"", + "percentage": 100 + }, + { + "date": "2022-05-12T13:36:00.100Z", + "rule": "beta eq \"false\"" } - } + ] } } - ``` + } +} +``` === "TOML" - ```toml linenums="1" hl_lines="6-17" - [scheduled-flag] - true = "B" - false = "A" - default = "Default" - - [scheduled-flag.rollout] - - [scheduled-flag.rollout.scheduled] - - [[scheduled-flag.rollout.scheduled.steps]] - date = 2020-04-09T22:00:00.100Z - rule = "beta eq \"true\"" - percentage = 100.0 - - [[scheduled-flag.rollout.scheduled.steps]] - date = 2022-05-12T13:36:00.100Z - rule = "beta eq \"false\"" - ``` +```toml linenums="1" hl_lines="6-17" +[scheduled-flag] +true = "B" +false = "A" +default = "Default" + + [scheduled-flag.rollout] + + [scheduled-flag.rollout.scheduled] + + [[scheduled-flag.rollout.scheduled.steps]] + date = 2020-04-09T22:00:00.100Z + rule = "beta eq \"true\"" + percentage = 100.0 + + [[scheduled-flag.rollout.scheduled.steps]] + date = 2022-05-12T13:36:00.100Z + rule = "beta eq \"false\"" +``` ## Configuration fields @@ -78,6 +80,6 @@ For example, you may want to turn a feature ON for internal testing tomorrow and 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. | +| 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. | From 8c11563fdf9c9d345daef8399c29d613458d067d Mon Sep 17 00:00:00 2001 From: Thomas Poignant Date: Wed, 20 Jul 2022 15:25:54 +0200 Subject: [PATCH 3/4] Fix
Signed-off-by: Thomas Poignant --- README.md | 34 ++++++++++---------- docs/configuration.md | 20 ++++++------ docs/data_collection/file.md | 8 ++--- docs/data_collection/google_cloud_storage.md | 16 ++++----- docs/data_collection/index.md | 6 ++-- docs/data_collection/log.md | 2 +- docs/data_collection/s3.md | 4 +-- docs/data_collection/webhook.md | 4 +-- docs/flag_file/github.md | 6 ++-- docs/flag_file/google_cloud_storage.md | 2 +- docs/flag_file/s3.md | 2 +- docs/flag_format.md | 14 ++++---- docs/notifier/webhook.md | 4 +-- docs/rollout/progressive.md | 2 +- docs/rollout/scheduled.md | 2 +- 15 files changed, 63 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index 44d058676e7..090eb0a9f62 100644 --- a/README.md +++ b/README.md @@ -125,16 +125,16 @@ ffclient.Init(ffclient.Config{ | Field | Description | |---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `Retriever` | The configuration retriever you want to use to get your flag file.
*See [Store your flag file](https://thomaspoignant.github.io/go-feature-flag/latest/flag_file/) for the configuration details*. | -| `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: `""` | -| `DataExporter` | *(optional)*
DataExporter defines how to export data on how your flags are used.
*see [export data section](https://thomaspoignant.github.io/go-feature-flag/latest/data_collection/) 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 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](https://thomaspoignant.github.io/go-feature-flag/latest/notifier/) for more details*. | -| `PollingInterval` | *(optional)* Duration to wait before refreshing the flags.
The minimum polling interval is 1 second.
Default: 60 * time.Second | -| `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 notification will be send neither.
Default: false | +| `Retriever` | The configuration retriever you want to use to get your flag file.
*See [Store your flag file](https://thomaspoignant.github.io/go-feature-flag/latest/flag_file/) for the configuration details*. | +| `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: `""` | +| `DataExporter` | *(optional)*
DataExporter defines how to export data on how your flags are used.
*see [export data section](https://thomaspoignant.github.io/go-feature-flag/latest/data_collection/) 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 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](https://thomaspoignant.github.io/go-feature-flag/latest/notifier/) for more details*. | +| `PollingInterval` | *(optional)* Duration to wait before refreshing the flags.
The minimum polling interval is 1 second.
Default: 60 * time.Second | +| `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 notification will be send neither.
Default: 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. @@ -263,16 +263,16 @@ version = 12.0 | Field | Description | |:-------------:|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **flag-key** | Name of your flag.
It must be unique.
*On the example the flag keys are **`test-flag`** and **`test-flag2`**.* | +| **flag-key** | Name of your flag.
It must be unique.
*On the example the flag keys are **`test-flag`** and **`test-flag2`**.* | | `true` | Value returned by the flag if the rule is evaluated to true and the user is in the active percentage. | | `false` | Value returned by the flag if the rule is evaluated to true and the user is **not** in the active percentage. | | `default` | Value returned by the flag if the rule is evaluated to false. | -| `percentage` | *(optional)*
Percentage of users who should be affected by the flag.
**Default: 0**

The percentage is computed by calculating a hash of the user key *(100000 variations)*, it means that you can have 3 numbers after the comma. | -| `rule` | *(optional)*
Condition to determine on which user the flag should be applied.
Rule format is described in the rule format section.
**If no rule is set, the flag applies to all users *(percentage still apply)*.** | -| `disable` | *(optional)*
True if the flag is disabled.
**Default: `false`** | -| `trackEvents` | *(optional)*
False if you don't want to export the data in your data exporter.
**Default: `true`** | -| `version` | *(optional)*
The version is the version of your flag.
This number is used to display the information in the notifiers and data collection, you have to update it your self.
**Default: 0** | -| `rollout` | *(optional)*
rollout contains a specific rollout strategy you want to use.
**See [rollout section](https://thomaspoignant.github.io/go-feature-flag/latest/rollout/) for more details.** | +| `percentage` | *(optional)*
Percentage of users who should be affected by the flag.
**Default: 0**

The percentage is computed by calculating a hash of the user key *(100000 variations)*, it means that you can have 3 numbers after the comma. | +| `rule` | *(optional)*
Condition to determine on which user the flag should be applied.
Rule format is described in the rule format section.
**If no rule is set, the flag applies to all users *(percentage still apply)*.** | +| `disable` | *(optional)*
True if the flag is disabled.
**Default: `false`** | +| `trackEvents` | *(optional)*
False if you don't want to export the data in your data exporter.
**Default: `true`** | +| `version` | *(optional)*
The version is the version of your flag.
This number is used to display the information in the notifiers and data collection, you have to update it your self.
**Default: 0** | +| `rollout` | *(optional)*
rollout contains a specific rollout strategy you want to use.
**See [rollout section](https://thomaspoignant.github.io/go-feature-flag/latest/rollout/) for more details.** | ## Rule format The rule format is based on the [`nikunjy/rules`](https://github.com/nikunjy/rules) library. diff --git a/docs/configuration.md b/docs/configuration.md index dc383ed5841..02bd4755143 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -8,16 +8,16 @@ During the initialization you must give a [`ffclient.Config{}`](https://pkg.go.d | Field | Description | |---|---| -|`Retriever` | The configuration retriever you want to use to get your flag file
*See [Store your flag file](flag_file/index.md) for the configuration details*.| -|`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](../flag_format/#environments) to understand how to use this parameter.*| -|`DataExporter` | *(optional)*
DataExporter defines how to export data on how your flags are used.
*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 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| -|`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 notification will be send neither.
Default: false| +|`Retriever` | The configuration retriever you want to use to get your flag file
*See [Store your flag file](flag_file/index.md) for the configuration details*.| +|`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](../flag_format/#environments) to understand how to use this parameter.*| +|`DataExporter` | *(optional)*
DataExporter defines how to export data on how your flags are used.
*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 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| +|`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 notification will be send neither.
Default: false| ## Example ```go linenums="1" diff --git a/docs/data_collection/file.md b/docs/data_collection/file.md index 8f7271a8eb7..86625081fc0 100644 --- a/docs/data_collection/file.md +++ b/docs/data_collection/file.md @@ -25,9 +25,9 @@ ffclient.Config{ | Field | Description | |---|---| -|`OutputDir` | OutputDir is the location of the directory where 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`**.
**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 replacement 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 another format 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}}\n` | +|`OutputDir` | OutputDir is the location of the directory where 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`**.
**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 replacement 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 another format 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}}\n` | Check the [godoc for full details](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/exporter/fileexporter). diff --git a/docs/data_collection/google_cloud_storage.md b/docs/data_collection/google_cloud_storage.md index 084ea3b9e93..7d660affbf6 100644 --- a/docs/data_collection/google_cloud_storage.md +++ b/docs/data_collection/google_cloud_storage.md @@ -28,13 +28,13 @@ ffclient.Config{ ``` ## 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 another format 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}}\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 replacement 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 format are **`JSON`** and **`CSV`**. *(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. | +| 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 another format 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}}\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 replacement 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 format are **`JSON`** and **`CSV`**. *(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. | Check the [godoc for full details](https://pkg.go.dev/github.com/thomaspoignant/go-feature-flag/exporter/gcstorageexporter). diff --git a/docs/data_collection/index.md b/docs/data_collection/index.md index a912c6c6eb4..f32558ff121 100644 --- a/docs/data_collection/index.md +++ b/docs/data_collection/index.md @@ -40,7 +40,7 @@ It represents individual flag evaluations and are considered "full fidelity" eve | **`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
**Dafault**: if the flag was evaluated to Default
**SdkDefault**: if something wrong happened and the SDK default value was used. | +| **`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
**Dafault**: 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. | | **`default`** | (Optional) This value is set to true if feature flag evaluation failed, in which case the value returned was the default value passed to variation. | @@ -76,8 +76,8 @@ ffclient.Config{ | 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**. | +| `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 diff --git a/docs/data_collection/log.md b/docs/data_collection/log.md index ca95045689d..30c0205c9b4 100644 --- a/docs/data_collection/log.md +++ b/docs/data_collection/log.md @@ -21,6 +21,6 @@ ffclient.Config{ ## 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 represent the date with the **RFC 3339** Format.

**Default: `[{{ .FormattedDate}}] user="{{ .UserKey}}", flag="{{ .Key}}", value="{{ .Value}}"`** | +| `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 represent 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/docs/data_collection/s3.md b/docs/data_collection/s3.md index 12684204509..f74ba5bb34d 100644 --- a/docs/data_collection/s3.md +++ b/docs/data_collection/s3.md @@ -40,8 +40,8 @@ ffclient.Config{ |---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `Bucket` | Name of your S3 Bucket. | | `AwsConfig` | An instance of `aws.Config` that configure your access to AWS *(see [this documentation for more info](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html))*. | -| `CsvTemplate` | *(optional)* CsvTemplate is used if your output format is CSV. This field will be ignored if you are using another format 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}}\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 replacement 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 another format 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}}\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 replacement 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 format are **`JSON`** and **`CSV`**. *(Default: `JSON`)* | | `S3Path` | *(optional)* The location of the directory in S3. | diff --git a/docs/data_collection/webhook.md b/docs/data_collection/webhook.md index dc87bdbeabd..9f769ac65d7 100644 --- a/docs/data_collection/webhook.md +++ b/docs/data_collection/webhook.md @@ -27,8 +27,8 @@ ffclient.Config{ | 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. | +|`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. | ## Webhook format diff --git a/docs/flag_file/github.md b/docs/flag_file/github.md index bfeb9b6a90f..8ef6d3a1d8a 100644 --- a/docs/flag_file/github.md +++ b/docs/flag_file/github.md @@ -30,6 +30,6 @@ To configure the access to your GitHub file: |----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **`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 | +| **`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/docs/flag_file/google_cloud_storage.md b/docs/flag_file/google_cloud_storage.md index 3be6e63700a..e92f2c9c4c1 100644 --- a/docs/flag_file/google_cloud_storage.md +++ b/docs/flag_file/google_cloud_storage.md @@ -28,4 +28,4 @@ To configure your Google Cloud Storage file location: |--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **`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). | +| **`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/docs/flag_file/s3.md b/docs/flag_file/s3.md index a8c108b2efb..f8551cd073d 100644 --- a/docs/flag_file/s3.md +++ b/docs/flag_file/s3.md @@ -23,4 +23,4 @@ To configure your S3 file location: |---|---| |**`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)*.| +|**`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/docs/flag_format.md b/docs/flag_format.md index b80d0cc0fc0..e9c6bdb4232 100644 --- a/docs/flag_format.md +++ b/docs/flag_format.md @@ -109,16 +109,16 @@ version = 12.0 | Field | Description | |:-------------:|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **flag-key** | Name of your flag.
It must be unique.
*On the example the flag keys are **`test-flag`** and **`test-flag2`**.* | +| **flag-key** | Name of your flag.
It must be unique.
*On the example the flag keys are **`test-flag`** and **`test-flag2`**.* | | `true` | Value returned by the flag if apply to the user *(rule is evaluated to true)* and the user is in the active percentage. | | `false` | Value returned by the flag if apply to the user *(rule is evaluated to true)* and the user is **not** in the active percentage. | | `default` | Value returned by the flag if not apply to the user *(rule is evaluated to false).* | -| `percentage` | *(optional)*
Percentage of the users who should be affected by the flag.
**Default: 0**

The percentage is computed by calculating a hash of the user key *(100000 variations)*, it means that you can have 3 numbers after the comma. | -| `rule` | *(optional)*
Condition to determine on which user the flag should be applied.
Rule format is described in the [rule format section](#rule-format).
**If no rule is set, the flag applies to all users *(percentage still apply)*.** | -| `disable` | *(optional)*
True if the flag is disabled.
**Default: `false`** | -| `trackEvents` | *(optional)*
False if you don't want to export the data in your data exporter.
**Default: `true`** | -| `version` | *(optional)*
The version is the version of your flag.
This number is used to display the information in the notifiers and data collection, you have to update it your self.
**Default: 0** | -| `rollout` | *(optional)*
rollout contains a specific rollout strategy you want to use.
**See [rollout section](rollout/index.md) for more details.** | +| `percentage` | *(optional)*
Percentage of the users who should be affected by the flag.
**Default: 0**

The percentage is computed by calculating a hash of the user key *(100000 variations)*, it means that you can have 3 numbers after the comma. | +| `rule` | *(optional)*
Condition to determine on which user the flag should be applied.
Rule format is described in the [rule format section](#rule-format).
**If no rule is set, the flag applies to all users *(percentage still apply)*.** | +| `disable` | *(optional)*
True if the flag is disabled.
**Default: `false`** | +| `trackEvents` | *(optional)*
False if you don't want to export the data in your data exporter.
**Default: `true`** | +| `version` | *(optional)*
The version is the version of your flag.
This number is used to display the information in the notifiers and data collection, you have to update it your self.
**Default: 0** | +| `rollout` | *(optional)*
rollout contains a specific rollout strategy you want to use.
**See [rollout section](rollout/index.md) for more details.** | ## Rule format diff --git a/docs/notifier/webhook.md b/docs/notifier/webhook.md index cedb380741a..b679af08173 100644 --- a/docs/notifier/webhook.md +++ b/docs/notifier/webhook.md @@ -27,8 +27,8 @@ ffclient.Config{ | 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 add 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.** | +| `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 add 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.** | ## Format diff --git a/docs/rollout/progressive.md b/docs/rollout/progressive.md index 68366ea6b47..e45b10ff8eb 100644 --- a/docs/rollout/progressive.md +++ b/docs/rollout/progressive.md @@ -77,4 +77,4 @@ default = "Default" | 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 of 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 at which level it ends (`end`).
**Default: `initial` = `0` and `end` = `100`** | +| **`percentage`** | *(optional)*
It represents the ramp of progress, at which level the flag starts (`initial`) and at which level it ends (`end`).
**Default: `initial` = `0` and `end` = `100`** | diff --git a/docs/rollout/scheduled.md b/docs/rollout/scheduled.md index 98a854cb8c2..70d68e100f4 100644 --- a/docs/rollout/scheduled.md +++ b/docs/rollout/scheduled.md @@ -82,4 +82,4 @@ default = "Default" | 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. | +| **`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. | From a4a295d080d4b88a80f0d392fccd49041bf4a88a Mon Sep 17 00:00:00 2001 From: Thomas Poignant Date: Wed, 20 Jul 2022 15:46:10 +0200 Subject: [PATCH 4/4] Edit readme Signed-off-by: Thomas Poignant --- README.md | 45 +++++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 090eb0a9f62..86901573fd0 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ No server is needed, just add a file to your central system and all your service **go-feature-flags supports:** -- Storing your configuration flags file on various locations (`HTTP`, `S3`, `GitHub`, `file`, `Google Cloud Storage` ...). +- Storing your configuration flags file on various locations (`HTTP`, `S3`, `GitHub`, `file`, `Google Cloud Storage`, `Kubernetes` ...). - Configuring your flags in various format (`JSON`, `TOML` and `YAML`). - Adding complex rules to target your users. - Use complex rollout strategy for your flags : @@ -58,6 +58,15 @@ https://user-images.githubusercontent.com/17908063/168597893-e957e648-b795-4b5f- _The code of this demo is available in [`thomaspoignant/go-feature-flag-demo`](https://github.com/thomaspoignant/go-feature-flag-demo) repository_. +## Can I use GO Feature Flag with another language? + +Originally GO Feature Flag was build to be a GOlang only libraries, but it limits too much the echo system. +To be compatible with more language we have implemented the [GO Feature Flag Relay Proxy](https://github.com/thomaspoignant/go-feature-flag-relay-proxy). +It is a service you can host that provides an API to evaluate your flags, you can call it using HTTP to get your variation. + +Since we believe in standardization we are also implementing [Open-feature](https://github.com/open-feature) providers to interact with this API in the language of your choice. +__(Open-feature is still at an early stage, so not all language are supported and expect some changes in the future)__ + ## Getting started First, you need to initialize the `ffclient` with the location of your backend file. ```go @@ -123,20 +132,10 @@ ffclient.Init(ffclient.Config{ ``` ### Configuration fields -| Field | Description | -|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `Retriever` | The configuration retriever you want to use to get your flag file.
*See [Store your flag file](https://thomaspoignant.github.io/go-feature-flag/latest/flag_file/) for the configuration details*. | -| `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: `""` | -| `DataExporter` | *(optional)*
DataExporter defines how to export data on how your flags are used.
*see [export data section](https://thomaspoignant.github.io/go-feature-flag/latest/data_collection/) 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 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](https://thomaspoignant.github.io/go-feature-flag/latest/notifier/) for more details*. | -| `PollingInterval` | *(optional)* Duration to wait before refreshing the flags.
The minimum polling interval is 1 second.
Default: 60 * time.Second | -| `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 notification will be send neither.
Default: false | +All the configuration fields are described in the [configuration documentation page](https://docs.gofeatureflag.org/configuration/). ### 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. @@ -159,7 +158,7 @@ Available retriever are: You can also [create your own retriever](https://thomaspoignant.github.io/go-feature-flag/latest/flag_file/custom/). ## Flags file format -`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. +`go-feature-flag` core feature is to centralize all your feature flags in a single file, and to avoid hosting and maintaining a backend server to manage them. Your file should be a `YAML`, `JSON` or `TOML` file with a list of flags *(examples: [`YAML`](testdata/flag-config.yaml), [`JSON`](testdata/flag-config.json), [`TOML`](testdata/flag-config.toml))*. @@ -260,21 +259,10 @@ version = 12.0 - -| Field | Description | -|:-------------:|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **flag-key** | Name of your flag.
It must be unique.
*On the example the flag keys are **`test-flag`** and **`test-flag2`**.* | -| `true` | Value returned by the flag if the rule is evaluated to true and the user is in the active percentage. | -| `false` | Value returned by the flag if the rule is evaluated to true and the user is **not** in the active percentage. | -| `default` | Value returned by the flag if the rule is evaluated to false. | -| `percentage` | *(optional)*
Percentage of users who should be affected by the flag.
**Default: 0**

The percentage is computed by calculating a hash of the user key *(100000 variations)*, it means that you can have 3 numbers after the comma. | -| `rule` | *(optional)*
Condition to determine on which user the flag should be applied.
Rule format is described in the rule format section.
**If no rule is set, the flag applies to all users *(percentage still apply)*.** | -| `disable` | *(optional)*
True if the flag is disabled.
**Default: `false`** | -| `trackEvents` | *(optional)*
False if you don't want to export the data in your data exporter.
**Default: `true`** | -| `version` | *(optional)*
The version is the version of your flag.
This number is used to display the information in the notifiers and data collection, you have to update it your self.
**Default: 0** | -| `rollout` | *(optional)*
rollout contains a specific rollout strategy you want to use.
**See [rollout section](https://thomaspoignant.github.io/go-feature-flag/latest/rollout/) for more details.** | +All the fields to create a flag are described in the [documentation](https://docs.gofeatureflag.org/v0.27.1/flag_format/). ## Rule format + The rule format is based on the [`nikunjy/rules`](https://github.com/nikunjy/rules) library. All the operations can be written capitalized or lowercase (ex: `eq` or `EQ` can be used). @@ -332,7 +320,8 @@ You can also distinguish logged-in users from anonymous users in the SDK ([check ## 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) +[`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)