diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 0e5b256d..65f558e7 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.3.1" + ".": "2.0.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eae4599..452a2e03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,59 @@ # Changelog +## [2.0.0](https://github.com/open-feature/dotnet-sdk/compare/v1.3.1...v2.0.0) (2024-01-19) + + +### โš  BREAKING CHANGES + +* Add support for provider shutdown and status. ([#158](https://github.com/open-feature/dotnet-sdk/issues/158)) + +### ๐Ÿ› Bug Fixes + +* Fix ArgumentOutOfRangeException for empty hooks ([#187](https://github.com/open-feature/dotnet-sdk/issues/187)) ([950775b](https://github.com/open-feature/dotnet-sdk/commit/950775b65093e22ce209c947bf9da71b17ad7387)) +* More robust shutdown/cleanup/reset ([#188](https://github.com/open-feature/dotnet-sdk/issues/188)) ([a790f78](https://github.com/open-feature/dotnet-sdk/commit/a790f78c32b8500ce27d04d906c98d1de2afd2b4)) +* Remove upper-bound version constraint from SCI ([#171](https://github.com/open-feature/dotnet-sdk/issues/171)) ([8f8b661](https://github.com/open-feature/dotnet-sdk/commit/8f8b661f1cac6a4f1c51eb513999372d30a4f726)) + + +### โœจ New Features + +* Add dx to catch ConfigureAwait(false) ([#152](https://github.com/open-feature/dotnet-sdk/issues/152)) ([9c42d4a](https://github.com/open-feature/dotnet-sdk/commit/9c42d4afa9139094e0316bbe1306ae4856b7d013)) +* add support for eventing ([#166](https://github.com/open-feature/dotnet-sdk/issues/166)) ([f5fc1dd](https://github.com/open-feature/dotnet-sdk/commit/f5fc1ddadc11f712ae0893cde815e7a1c6fe2c1b)) +* Add support for provider shutdown and status. ([#158](https://github.com/open-feature/dotnet-sdk/issues/158)) ([24c3441](https://github.com/open-feature/dotnet-sdk/commit/24c344163423973b54a06b73648ba45b944589ee)) + + +### ๐Ÿงน Chore + +* Add GitHub Actions logger for CI ([#174](https://github.com/open-feature/dotnet-sdk/issues/174)) ([c1a189a](https://github.com/open-feature/dotnet-sdk/commit/c1a189a5cff7106d37f0a45dd5824f18e7ec0cd6)) +* add placeholder eventing and shutdown sections ([#156](https://github.com/open-feature/dotnet-sdk/issues/156)) ([5dfea29](https://github.com/open-feature/dotnet-sdk/commit/5dfea29bb3d01f6c8640de321c4fde52f283a1c0)) +* Add support for GitHub Packages ([#173](https://github.com/open-feature/dotnet-sdk/issues/173)) ([26cd5cd](https://github.com/open-feature/dotnet-sdk/commit/26cd5cdd613577c53ae79b889d1cf2d89262236f)) +* Adding sealed keyword to classes ([#191](https://github.com/open-feature/dotnet-sdk/issues/191)) ([1a14f6c](https://github.com/open-feature/dotnet-sdk/commit/1a14f6cd6c8988756a2cf2da1137a739e8d960f8)) +* **deps:** update actions/checkout action to v4 ([#144](https://github.com/open-feature/dotnet-sdk/issues/144)) ([90d9d02](https://github.com/open-feature/dotnet-sdk/commit/90d9d021b227fba626bb99454cb7c0f7fef2d8d8)) +* **deps:** update actions/setup-dotnet action to v4 ([#162](https://github.com/open-feature/dotnet-sdk/issues/162)) ([0b0bb10](https://github.com/open-feature/dotnet-sdk/commit/0b0bb10419f836d9cc276fe8ac3c71c9214420ef)) +* **deps:** update dependency dotnet-sdk to v7.0.404 ([#148](https://github.com/open-feature/dotnet-sdk/issues/148)) ([e8ca1da](https://github.com/open-feature/dotnet-sdk/commit/e8ca1da9ed63df9685ec49a9569e0ec99ba0b3b9)) +* **deps:** update github/codeql-action action to v3 ([#163](https://github.com/open-feature/dotnet-sdk/issues/163)) ([c85e93e](https://github.com/open-feature/dotnet-sdk/commit/c85e93e9c9a97083660f9062c38dcbf6d64a3ad6)) +* fix alt text for NuGet on the readme ([2cbdba8](https://github.com/open-feature/dotnet-sdk/commit/2cbdba80d836f8b7850e8dc5f1f1790ef2ed1aca)) +* Fix FieldCanBeMadeReadOnly ([#183](https://github.com/open-feature/dotnet-sdk/issues/183)) ([18a092a](https://github.com/open-feature/dotnet-sdk/commit/18a092afcab1b06c25f3b825a6130d22226790fc)) +* Fix props to support more than one project ([#177](https://github.com/open-feature/dotnet-sdk/issues/177)) ([f47cf07](https://github.com/open-feature/dotnet-sdk/commit/f47cf07420cdcb6bc74b0455898b7b17a144daf3)) +* minor formatting cleanup ([#168](https://github.com/open-feature/dotnet-sdk/issues/168)) ([d0c25af](https://github.com/open-feature/dotnet-sdk/commit/d0c25af7df5176d10088c148eac35b0034536e04)) +* Reduce dependency on MEL -> MELA ([#176](https://github.com/open-feature/dotnet-sdk/issues/176)) ([a6062fe](https://github.com/open-feature/dotnet-sdk/commit/a6062fe2b9f0d83490c7ce900e837863521f5f55)) +* remove duplicate eventing section in readme ([1efe09d](https://github.com/open-feature/dotnet-sdk/commit/1efe09da3948d5dfd7fd9f1c7a040fc5c2cbe833)) +* remove test sleeps, fix flaky test ([#194](https://github.com/open-feature/dotnet-sdk/issues/194)) ([f2b9b03](https://github.com/open-feature/dotnet-sdk/commit/f2b9b03eda5f6d6b4a738f761702cd9d9a105e76)) +* update spec release link ([a2f70eb](https://github.com/open-feature/dotnet-sdk/commit/a2f70ebd68357156f9045fc6e94845a53ffd204a)) +* updated readme for inclusion in the docs ([6516866](https://github.com/open-feature/dotnet-sdk/commit/6516866ec7601a7adaa4dc6b517c9287dec54fca)) + + +### ๐Ÿ“š Documentation + +* Add README.md to the nuget package ([#164](https://github.com/open-feature/dotnet-sdk/issues/164)) ([b6b0ee2](https://github.com/open-feature/dotnet-sdk/commit/b6b0ee2b61a9b0b973b913b53887badfa0c5a3de)) +* fixed the contrib url on the readme ([9d8939e](https://github.com/open-feature/dotnet-sdk/commit/9d8939ef57a3be4ee220bd21f36b166887b2c30b)) +* remove duplicate a tag from readme ([2687cf0](https://github.com/open-feature/dotnet-sdk/commit/2687cf0663e20aa2dd113569cbf177833639cbbd)) +* update README.md ([#155](https://github.com/open-feature/dotnet-sdk/issues/155)) ([b62e21f](https://github.com/open-feature/dotnet-sdk/commit/b62e21f76964e7f6f7456f720814de0997232d71)) + + +### ๐Ÿ”„ Refactoring + +* Add TFMs for net{6,7,8}.0 ([#172](https://github.com/open-feature/dotnet-sdk/issues/172)) ([cf2baa8](https://github.com/open-feature/dotnet-sdk/commit/cf2baa8a6b4328f1aa346bbea91160aa2e5f3a8d)) + ## [1.3.1](https://github.com/open-feature/dotnet-sdk/compare/v1.3.0...v1.3.1) (2023-09-19) diff --git a/README.md b/README.md index 33cf5c5d..90c34e5c 100644 --- a/README.md +++ b/README.md @@ -1,342 +1,342 @@ - - -

- - - OpenFeature Logo - -

- -

OpenFeature .NET SDK

- - - -

- - Specification - - - - - Release - - -
- - Slack - - - Codecov - - - NuGet - - - CII Best Practices - - -

- - -[OpenFeature](https://openfeature.dev) is an open specification that provides a vendor-agnostic, community-driven API for feature flagging that works with your favorite feature flag management tool. - - - -## ๐Ÿš€ Quick start - -### Requirements - -- .NET 6+ -- .NET Core 6+ -- .NET Framework 4.6.2+ - -Note that the packages will aim to support all current .NET versions. Refer to the currently supported versions [.NET](https://dotnet.microsoft.com/download/dotnet) and [.NET Framework](https://dotnet.microsoft.com/download/dotnet-framework) excluding .NET Framework 3.5 - -### Install - -Use the following to initialize your project: - -```sh -dotnet new console -``` - -and install OpenFeature: - -```sh -dotnet add package OpenFeature -``` - -### Usage - -```csharp -public async Task Example() -{ - // Register your feature flag provider - await Api.Instance.SetProvider(new InMemoryProvider()); - - // Create a new client - FeatureClient client = Api.Instance.GetClient(); - - // Evaluate your feature flag - bool v2Enabled = await client.GetBooleanValue("v2_enabled", false); - - if ( v2Enabled ) - { - //Do some work - } -} -``` - -## ๐ŸŒŸ Features - -| Status | Features | Description | -| ------ | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -| โœ… | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. | -| โœ… | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). | -| โœ… | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. | -| โœ… | [Logging](#logging) | Integrate with popular logging packages. | -| โœ… | [Named clients](#named-clients) | Utilize multiple providers in a single application. | -| โœ… | [Eventing](#eventing) | React to state changes in the provider or flag management system. | -| โœ… | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | -| โœ… | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | - -Implemented: โœ… | In-progress: โš ๏ธ | Not implemented yet: โŒ - -### Providers - -[Providers](https://openfeature.dev/docs/reference/concepts/provider) are an abstraction between a flag management system and the OpenFeature SDK. -Here is [a complete list of available providers](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Provider&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=.NET). - -If the provider you're looking for hasn't been created yet, see the [develop a provider](#develop-a-provider) section to learn how to build it yourself. - -Once you've added a provider as a dependency, it can be registered with OpenFeature like this: - -```csharp -await Api.Instance.SetProvider(new MyProvider()); -``` - -In some situations, it may be beneficial to register multiple providers in the same application. -This is possible using [named clients](#named-clients), which is covered in more detail below. - -### Targeting - -Sometimes, the value of a flag must consider some dynamic criteria about the application or user such as the user's location, IP, email address, or the server's location. -In OpenFeature, we refer to this as [targeting](https://openfeature.dev/specification/glossary#targeting). -If the flag management system you're using supports targeting, you can provide the input data using the [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). - -```csharp -// set a value to the global context -EvaluationContextBuilder builder = EvaluationContext.Builder(); -builder.Set("region", "us-east-1"); -EvaluationContext apiCtx = builder.Build(); -Api.Instance.SetContext(apiCtx); - -// set a value to the client context -builder = EvaluationContext.Builder(); -builder.Set("region", "us-east-1"); -EvaluationContext clientCtx = builder.Build(); -var client = Api.Instance.GetClient(); -client.SetContext(clientCtx); - -// set a value to the invocation context -builder = EvaluationContext.Builder(); -builder.Set("region", "us-east-1"); -EvaluationContext reqCtx = builder.Build(); - -bool flagValue = await client.GetBooleanValue("some-flag", false, reqCtx); - -``` - -### Hooks - -[Hooks](https://openfeature.dev/docs/reference/concepts/hooks) allow for custom logic to be added at well-defined points of the flag evaluation life-cycle. -Here is [a complete list of available hooks](https://openfeature.dev/docs/reference/technologies/server/dotnet/). -If the hook you're looking for hasn't been created yet, see the [develop a hook](#develop-a-hook) section to learn how to build it yourself. - -Once you've added a hook as a dependency, it can be registered at the global, client, or flag invocation level. - -```csharp -// add a hook globally, to run on all evaluations -Api.Instance.AddHooks(new ExampleGlobalHook()); - -// add a hook on this client, to run on all evaluations made by this client -var client = Api.Instance.GetClient(); -client.AddHooks(new ExampleClientHook()); - -// add a hook for this evaluation only -var value = await client.GetBooleanValue("boolFlag", false, context, new FlagEvaluationOptions(new ExampleInvocationHook())); -``` - -### Logging - -The .NET SDK uses Microsoft.Extensions.Logging. See the [manual](https://learn.microsoft.com/en-us/dotnet/core/extensions/logging?tabs=command-line) for complete documentation. - -### Named clients - -Clients can be given a name. -A name is a logical identifier that can be used to associate clients with a particular provider. -If a name has no associated provider, the global provider is used. - -```csharp -// registering the default provider -await Api.Instance.SetProvider(new LocalProvider()); - -// registering a named provider -await Api.Instance.SetProvider("clientForCache", new CachedProvider()); - -// a client backed by default provider -FeatureClient clientDefault = Api.Instance.GetClient(); - -// a client backed by CachedProvider -FeatureClient clientNamed = Api.Instance.GetClient("clientForCache"); - -``` - -### Eventing - -Events allow you to react to state changes in the provider or underlying flag management system, such as flag definition changes, -provider readiness, or error conditions. -Initialization events (`PROVIDER_READY` on success, `PROVIDER_ERROR` on failure) are dispatched for every provider. -Some providers support additional events, such as `PROVIDER_CONFIGURATION_CHANGED`. - -Please refer to the documentation of the provider you're using to see what events are supported. - -Example usage of an Event handler: - -```csharp -public static void EventHandler(ProviderEventPayload eventDetails) -{ - Console.WriteLine(eventDetails.Type); -} -``` - -```csharp -EventHandlerDelegate callback = EventHandler; -// add an implementation of the EventHandlerDelegate for the PROVIDER_READY event -Api.Instance.AddHandler(ProviderEventTypes.ProviderReady, callback); -``` - -It is also possible to register an event handler for a specific client, as in the following example: - -```csharp -EventHandlerDelegate callback = EventHandler; - -var myClient = Api.Instance.GetClient("my-client"); - -var provider = new ExampleProvider(); -await Api.Instance.SetProvider(myClient.GetMetadata().Name, provider); - -myClient.AddHandler(ProviderEventTypes.ProviderReady, callback); -``` - -### Shutdown - -The OpenFeature API provides a close function to perform a cleanup of all registered providers. This should only be called when your application is in the process of shutting down. - -```csharp -// Shut down all providers -await Api.Instance.Shutdown(); -``` - -## Extending - -### Develop a provider - -To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency. -This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/dotnet-sdk-contrib) available under the OpenFeature organization. -Youโ€™ll then need to write the provider by implementing the `FeatureProvider` interface exported by the OpenFeature SDK. - -```csharp -public class MyProvider : FeatureProvider -{ - public override Metadata GetMetadata() - { - return new Metadata("My Provider"); - } - - public override Task> ResolveBooleanValue(string flagKey, bool defaultValue, EvaluationContext context = null) - { - // resolve a boolean flag value - } - - public override Task> ResolveDoubleValue(string flagKey, double defaultValue, EvaluationContext context = null) - { - // resolve a double flag value - } - - public override Task> ResolveIntegerValue(string flagKey, int defaultValue, EvaluationContext context = null) - { - // resolve an int flag value - } - - public override Task> ResolveStringValue(string flagKey, string defaultValue, EvaluationContext context = null) - { - // resolve a string flag value - } - - public override Task> ResolveStructureValue(string flagKey, Value defaultValue, EvaluationContext context = null) - { - // resolve an object flag value - } -} -``` - -### Develop a hook - -To develop a hook, you need to create a new project and include the OpenFeature SDK as a dependency. -This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/dotnet-sdk-contrib) available under the OpenFeature organization. -Implement your own hook by conforming to the `Hook interface`. -To satisfy the interface, all methods (`Before`/`After`/`Finally`/`Error`) need to be defined. - -```csharp -public class MyHook : Hook -{ - public Task Before(HookContext context, - IReadOnlyDictionary hints = null) - { - // code to run before flag evaluation - } - - public virtual Task After(HookContext context, FlagEvaluationDetails details, - IReadOnlyDictionary hints = null) - { - // code to run after successful flag evaluation - } - - public virtual Task Error(HookContext context, Exception error, - IReadOnlyDictionary hints = null) - { - // code to run if there's an error during before hooks or during flag evaluation - } - - public virtual Task Finally(HookContext context, IReadOnlyDictionary hints = null) - { - // code to run after all other stages, regardless of success/failure - } -} -``` - -Built a new hook? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=&labels=hook&projects=&template=document-hook.yaml&title=%5BHook%5D%3A+) so we can add it to the docs! - - -## โญ๏ธ Support the project - -- Give this repo a โญ๏ธ! -- Follow us on social media: - - Twitter: [@openfeature](https://twitter.com/openfeature) - - LinkedIn: [OpenFeature](https://www.linkedin.com/company/openfeature/) -- Join us on [Slack](https://cloud-native.slack.com/archives/C0344AANLA1) -- For more information, check out our [community page](https://openfeature.dev/community/) - -## ๐Ÿค Contributing - -Interested in contributing? Great, we'd love your help! To get started, take a look at the [CONTRIBUTING](CONTRIBUTING.md) guide. - -### Thanks to everyone who has already contributed - - - - - -Made with [contrib.rocks](https://contrib.rocks). - + + +

+ + + OpenFeature Logo + +

+ +

OpenFeature .NET SDK

+ + + +

+ + Specification + + + + + Release + + +
+ + Slack + + + Codecov + + + NuGet + + + CII Best Practices + + +

+ + +[OpenFeature](https://openfeature.dev) is an open specification that provides a vendor-agnostic, community-driven API for feature flagging that works with your favorite feature flag management tool. + + + +## ๐Ÿš€ Quick start + +### Requirements + +- .NET 6+ +- .NET Core 6+ +- .NET Framework 4.6.2+ + +Note that the packages will aim to support all current .NET versions. Refer to the currently supported versions [.NET](https://dotnet.microsoft.com/download/dotnet) and [.NET Framework](https://dotnet.microsoft.com/download/dotnet-framework) excluding .NET Framework 3.5 + +### Install + +Use the following to initialize your project: + +```sh +dotnet new console +``` + +and install OpenFeature: + +```sh +dotnet add package OpenFeature +``` + +### Usage + +```csharp +public async Task Example() +{ + // Register your feature flag provider + await Api.Instance.SetProvider(new InMemoryProvider()); + + // Create a new client + FeatureClient client = Api.Instance.GetClient(); + + // Evaluate your feature flag + bool v2Enabled = await client.GetBooleanValue("v2_enabled", false); + + if ( v2Enabled ) + { + //Do some work + } +} +``` + +## ๐ŸŒŸ Features + +| Status | Features | Description | +| ------ | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| โœ… | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. | +| โœ… | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). | +| โœ… | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. | +| โœ… | [Logging](#logging) | Integrate with popular logging packages. | +| โœ… | [Named clients](#named-clients) | Utilize multiple providers in a single application. | +| โœ… | [Eventing](#eventing) | React to state changes in the provider or flag management system. | +| โœ… | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | +| โœ… | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | + +Implemented: โœ… | In-progress: โš ๏ธ | Not implemented yet: โŒ + +### Providers + +[Providers](https://openfeature.dev/docs/reference/concepts/provider) are an abstraction between a flag management system and the OpenFeature SDK. +Here is [a complete list of available providers](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Provider&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=.NET). + +If the provider you're looking for hasn't been created yet, see the [develop a provider](#develop-a-provider) section to learn how to build it yourself. + +Once you've added a provider as a dependency, it can be registered with OpenFeature like this: + +```csharp +await Api.Instance.SetProvider(new MyProvider()); +``` + +In some situations, it may be beneficial to register multiple providers in the same application. +This is possible using [named clients](#named-clients), which is covered in more detail below. + +### Targeting + +Sometimes, the value of a flag must consider some dynamic criteria about the application or user such as the user's location, IP, email address, or the server's location. +In OpenFeature, we refer to this as [targeting](https://openfeature.dev/specification/glossary#targeting). +If the flag management system you're using supports targeting, you can provide the input data using the [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). + +```csharp +// set a value to the global context +EvaluationContextBuilder builder = EvaluationContext.Builder(); +builder.Set("region", "us-east-1"); +EvaluationContext apiCtx = builder.Build(); +Api.Instance.SetContext(apiCtx); + +// set a value to the client context +builder = EvaluationContext.Builder(); +builder.Set("region", "us-east-1"); +EvaluationContext clientCtx = builder.Build(); +var client = Api.Instance.GetClient(); +client.SetContext(clientCtx); + +// set a value to the invocation context +builder = EvaluationContext.Builder(); +builder.Set("region", "us-east-1"); +EvaluationContext reqCtx = builder.Build(); + +bool flagValue = await client.GetBooleanValue("some-flag", false, reqCtx); + +``` + +### Hooks + +[Hooks](https://openfeature.dev/docs/reference/concepts/hooks) allow for custom logic to be added at well-defined points of the flag evaluation life-cycle. +Here is [a complete list of available hooks](https://openfeature.dev/docs/reference/technologies/server/dotnet/). +If the hook you're looking for hasn't been created yet, see the [develop a hook](#develop-a-hook) section to learn how to build it yourself. + +Once you've added a hook as a dependency, it can be registered at the global, client, or flag invocation level. + +```csharp +// add a hook globally, to run on all evaluations +Api.Instance.AddHooks(new ExampleGlobalHook()); + +// add a hook on this client, to run on all evaluations made by this client +var client = Api.Instance.GetClient(); +client.AddHooks(new ExampleClientHook()); + +// add a hook for this evaluation only +var value = await client.GetBooleanValue("boolFlag", false, context, new FlagEvaluationOptions(new ExampleInvocationHook())); +``` + +### Logging + +The .NET SDK uses Microsoft.Extensions.Logging. See the [manual](https://learn.microsoft.com/en-us/dotnet/core/extensions/logging?tabs=command-line) for complete documentation. + +### Named clients + +Clients can be given a name. +A name is a logical identifier that can be used to associate clients with a particular provider. +If a name has no associated provider, the global provider is used. + +```csharp +// registering the default provider +await Api.Instance.SetProvider(new LocalProvider()); + +// registering a named provider +await Api.Instance.SetProvider("clientForCache", new CachedProvider()); + +// a client backed by default provider +FeatureClient clientDefault = Api.Instance.GetClient(); + +// a client backed by CachedProvider +FeatureClient clientNamed = Api.Instance.GetClient("clientForCache"); + +``` + +### Eventing + +Events allow you to react to state changes in the provider or underlying flag management system, such as flag definition changes, +provider readiness, or error conditions. +Initialization events (`PROVIDER_READY` on success, `PROVIDER_ERROR` on failure) are dispatched for every provider. +Some providers support additional events, such as `PROVIDER_CONFIGURATION_CHANGED`. + +Please refer to the documentation of the provider you're using to see what events are supported. + +Example usage of an Event handler: + +```csharp +public static void EventHandler(ProviderEventPayload eventDetails) +{ + Console.WriteLine(eventDetails.Type); +} +``` + +```csharp +EventHandlerDelegate callback = EventHandler; +// add an implementation of the EventHandlerDelegate for the PROVIDER_READY event +Api.Instance.AddHandler(ProviderEventTypes.ProviderReady, callback); +``` + +It is also possible to register an event handler for a specific client, as in the following example: + +```csharp +EventHandlerDelegate callback = EventHandler; + +var myClient = Api.Instance.GetClient("my-client"); + +var provider = new ExampleProvider(); +await Api.Instance.SetProvider(myClient.GetMetadata().Name, provider); + +myClient.AddHandler(ProviderEventTypes.ProviderReady, callback); +``` + +### Shutdown + +The OpenFeature API provides a close function to perform a cleanup of all registered providers. This should only be called when your application is in the process of shutting down. + +```csharp +// Shut down all providers +await Api.Instance.Shutdown(); +``` + +## Extending + +### Develop a provider + +To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency. +This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/dotnet-sdk-contrib) available under the OpenFeature organization. +Youโ€™ll then need to write the provider by implementing the `FeatureProvider` interface exported by the OpenFeature SDK. + +```csharp +public class MyProvider : FeatureProvider +{ + public override Metadata GetMetadata() + { + return new Metadata("My Provider"); + } + + public override Task> ResolveBooleanValue(string flagKey, bool defaultValue, EvaluationContext context = null) + { + // resolve a boolean flag value + } + + public override Task> ResolveDoubleValue(string flagKey, double defaultValue, EvaluationContext context = null) + { + // resolve a double flag value + } + + public override Task> ResolveIntegerValue(string flagKey, int defaultValue, EvaluationContext context = null) + { + // resolve an int flag value + } + + public override Task> ResolveStringValue(string flagKey, string defaultValue, EvaluationContext context = null) + { + // resolve a string flag value + } + + public override Task> ResolveStructureValue(string flagKey, Value defaultValue, EvaluationContext context = null) + { + // resolve an object flag value + } +} +``` + +### Develop a hook + +To develop a hook, you need to create a new project and include the OpenFeature SDK as a dependency. +This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/dotnet-sdk-contrib) available under the OpenFeature organization. +Implement your own hook by conforming to the `Hook interface`. +To satisfy the interface, all methods (`Before`/`After`/`Finally`/`Error`) need to be defined. + +```csharp +public class MyHook : Hook +{ + public Task Before(HookContext context, + IReadOnlyDictionary hints = null) + { + // code to run before flag evaluation + } + + public virtual Task After(HookContext context, FlagEvaluationDetails details, + IReadOnlyDictionary hints = null) + { + // code to run after successful flag evaluation + } + + public virtual Task Error(HookContext context, Exception error, + IReadOnlyDictionary hints = null) + { + // code to run if there's an error during before hooks or during flag evaluation + } + + public virtual Task Finally(HookContext context, IReadOnlyDictionary hints = null) + { + // code to run after all other stages, regardless of success/failure + } +} +``` + +Built a new hook? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=&labels=hook&projects=&template=document-hook.yaml&title=%5BHook%5D%3A+) so we can add it to the docs! + + +## โญ๏ธ Support the project + +- Give this repo a โญ๏ธ! +- Follow us on social media: + - Twitter: [@openfeature](https://twitter.com/openfeature) + - LinkedIn: [OpenFeature](https://www.linkedin.com/company/openfeature/) +- Join us on [Slack](https://cloud-native.slack.com/archives/C0344AANLA1) +- For more information, check out our [community page](https://openfeature.dev/community/) + +## ๐Ÿค Contributing + +Interested in contributing? Great, we'd love your help! To get started, take a look at the [CONTRIBUTING](CONTRIBUTING.md) guide. + +### Thanks to everyone who has already contributed + + + + + +Made with [contrib.rocks](https://contrib.rocks). + diff --git a/build/Common.prod.props b/build/Common.prod.props index 4d073ecf..39bba09f 100644 --- a/build/Common.prod.props +++ b/build/Common.prod.props @@ -9,7 +9,7 @@ - 1.3.1 + 2.0.0 git https://github.com/open-feature/dotnet-sdk OpenFeature is an open standard for feature flag management, created to support a robust feature flag ecosystem using cloud native technologies. OpenFeature will provide a unified API and SDK, and a developer-first, cloud-native implementation, with extensibility for open source and commercial offerings. diff --git a/version.txt b/version.txt index 3a3cd8cc..227cea21 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.3.1 +2.0.0