open-feature / dotnet-sdk Goto Github PK
View Code? Open in Web Editor NEW.NET implementation of the OpenFeature SDK
Home Page: https://openfeature.dev
License: Apache License 2.0
.NET implementation of the OpenFeature SDK
Home Page: https://openfeature.dev
License: Apache License 2.0
This has been discussed under open-feature/ofep#29
Allow the users to define the default logger on the client
Make sure we use the latest xUnit version since we should not have any limitations concerning versions during the unit tests.
Originally posted by @austindrenski in #178 (comment)
Looking at the EvaluationContext I see that you can use any object
as a value in the context. I am not clear how a provider could make use of non-trivial types, or be able to easily serialize the overall context without some level of interface requirement. (Unless they provided provider specific types, or specified specific types, but that doesn't seem very interoperable.)
In the basic use case, where there are top level basic types (string, number, boolean), I can see how a provider could request something as a type based on the meta-data that they likely have.
In the case of a structure
use case I am not sure how that could be accomplished. I do see how it could be accomplished if the types were effectively restricted to each of the base types, as well as ImmutableList
and ImmutableDictionary
of those those types and more ImmutableLists
and ImmutableDictionary
.
Or is there going to be a builder which can mange those constraints?
Imagining a context of this general shape:
{
"name": "example",
"complex": {
"field1": "value"
}
}
How could a provider access the value of field1? Aside from using reflection, or using some pre-specified type?
Edit:
The node implementation contains this type, which I think expresses how this data can be made navigable and understood.
export type JSONValue = null | string | number | boolean | Date | { [x: string]: JSONValue } | Array<JSONValue>;
Thank you,
Ryan
Add the hook behaviour described in the specification https://github.com/open-feature/spec/blob/main/specification/hooks.md
Update the SDK to be compliant with the v0.5.0 spec.
reason
must be a string in the flag resolution details
and evaluation details
.error message
to flag resolution details
. #72Full Changelog: open-feature/spec@v0.4.0...v0.5.0
Update the SDK to be compliant with the v0.4.0 spec.
Full Changelog: open-feature/spec@v0.3.1...v0.4.0
See changes since last release.
Please note there's no need to complete all these tasks in a single PR (in fact, that's not recommended).
v0.7.0
: Implement a comprehensive unit test suite that covers all of the specifications
https://github.com/open-feature/spec/blob/main/specification.json
Hello. I been working on a custom feature flag solution for our company. It is custom tailed to fit our use cases and needs. I came across OpenFeature a few months back and found it well thought-out, so we adopted it as a standard. Kudos on doing this work.
We have implemented a custom provider that uses our internal feature flag solution. We have many software projects that need to evaluate feature flags and some of them do not support async/await. When I try and call GetBooleanDetails
on IFeatureClient
I call GetAwaiter().GetResult()
at the end to force the code to support synchronous evaluation. This causes a deadlock. I have ensured that our custom provide calls ConfigureAwait(false)
on all async calls. Looking at the source code, it appears FeatureClient.GetBooleanDetails awaits Tasks from inner methods, but ConfigureAwait(false)
is not called.
My assumption is that because none of the awaited calls with FeatureClient
have ConfigureAwait(false)
, it's causing the deadlock because the calling code tries to resume execution on the same thread (which fails in an MVC application).
Calling .GetAwaiter().GetResult()
or .Result
should not cause a deadlock, but force the code to execute synchronously.
client.GetBooleanDetails(flagKey, false, customContext).Result;
within an ASP.Net MVC (4.8 framework) action that does not support async/await or return a Task<>
As brought up here, there's some potential issues with thread safety in the SDK, particularly around state maintained in the API singleton and clients. Let's use this issue to investigate and discuss some of these.
cc @kinyoklion
I think we can default this to empty in the FlagEvaluationOptions constructor.
Stumbled onto this while investigating failing unit tests add as part of #181 that fail when run in concert, but pass when run independently.
Working theory is that we're not restarting the consumer thread. Patch forthcoming.
See: #181
No response
No response
Due to the controversies around the Moq
library (see https://github.com/moq/moq/issues/1372), we may want to consider switching to another mocking library, like e.g. NSubstitute to avoid any privacy issues.
[1] Contains an example of how this was done by another previous Moq
user.
Note: Currently we are using v4.18 of Moq, and the controversial change has been introduced with v4.20 and above, so currently this repo is not directly affected by the change. However, we should not merge any renovate PRs bumping the Moq dependency
References:
[1] Afterlife-Guide/AppSettings.Merge#6
Based on the defined schemas in schemas repository, FeatureProvider should implement ResolveAll method to retrieve all feature flags.
This method would be extremely useful to us to be able to migrate over to OpenFeature.
We already have error codes defined, but it would be nice to define error classes to make things a bit more ergonomic for contributors. Basically something like is already implemented in this contrib ; simple classes wrapping these error types that can easily be thrown.
Create a cert, store it in secure place that the OpenFeature team has access to.
https://docs.microsoft.com/en-us/nuget/create-packages/sign-a-package
Create a CI/CD pipeline for the repo
We currently don't have a readme being published.
We can do follow these steps to do that: https://devblogs.microsoft.com/nuget/add-a-readme-to-your-nuget-package/#add-a-readme-to-your-package
The requirement IDs used in the specification changed when we added support for client-side feature flags. The .NET SDK uses those IDs in some tests. These should be reviewed to make sure they match the spec.
Requirements that are out of date:
dotnet-sdk/test/OpenFeature.Tests/OpenFeatureClientTests.cs
dotnet-sdk/test/OpenFeature.Tests/OpenFeatureHookTests.cs
Here's the diff between spec v0.5.2 and v0.8.0.
Is there a reason why the PackageReference to System.Collection.Immutable doesn't allow version 7. Version 7 has been out for 8 months now and this restriction is preventing us from being able to use this library.
Implement the most basic version of the specification to allow for retrieving flags in the defined forms (string, number, boolean, and structure)
Use https://github.com/xoofx/dotnet-releaser to manage to release dotnet-sdk
This tool will do the following
Things that will need to be considered
Update readme to be consistent with the template here: open-feature/.github#36
DoD:
TODOs
in templateSee similar Java PR: open-feature/java-sdk#382
Still trying to figure out all the triggering bits, but tldr; in a mixed-target solution (e.g. net48
, net8.0
, and netstandard2.0
), OpenFeature
is breaking source generators when loading the solution in IDEs (e.g. both Rider and Visual Studio), as well as when building directly from MSBuild.exe
when certain MSBuild targets are used (seems to relate to the VS install and which task DLLs are loaded).
CSC : error CS8784:
Generator 'SomeGenerator' failed to initialize. It will not contribute to the output and compilation errors may occur
as a result. Exception was of type 'FileNotFoundException' with message 'Could not load file or assembly 'System.
Collections.Immutable, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies.
The system cannot find the file specified.'.
[C:\a\dotnet\SomeSolution\src\SomeProject\SomeProject.csproj::TargetFramework=netstandard2.0]
where SomeProject.csproj
:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../SomeProject.Generators/SomeProject.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>
</Project>
and SomeProject.Generators.csproj
:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" PrivateAssets="all" />
</ItemGroup>
</Project>
and then SomeProject.csproj
is eventually being used by SomeLegacyWebProject.csproj
:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>library</OutputType>
<TargetFramework>net48</TargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- N.B. in reality this is a transitive reference coming from deep within the project graph -->
<PackageReference Include="System.Collections.Immutable" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../SomeProject/SomeProject.csproj" />
</ItemGroup>
<Import Condition="Exists('$(VSToolsPath)/WebApplications/Microsoft.WebApplication.targets')" Project="$(VSToolsPath)/WebApplications/Microsoft.WebApplication.targets" />
</Project>
Now one look at SomeLegacyWebProject.csproj
and the immediate reaction of any reasonable engineer is to blame the legacy of it all, but this project plays nice with all of the other modern components that we continue to shoehorn into it, including a whole slew of OpenTelemetry
and OpenTelemetry.*
packages, but just not with OpenFeature
.
I hate opening issues without a minimal repro, so will keep trying to put one together and ping back here if/when I can, but hoping the nuances of reproducing my actual use case won't stymie making progress on resolving this, since I think it's fairly clear cut.
The primary issue is that OpenFeature
flows this constraint onto consumers:
Line 27 in d0c25af
I would like to see the upper-bound of this constraint removed as was originally proposed in #136 since we're back here 6 months later as predicted by @toddbaert in #136 (comment).
I can reference OpenFeature
from projects consuming (transitively or otherwise) version 8.0.0
or later of System.Collections.Immutable
without breaking source generators.
No response
Leverage the test-harness and evaluation.feature gherkin suite to create a set of integration tests for .NET. See equivalent examples in Java and JS. Though we should call these "end-to-end" not integration tests, since that's what they are.
The suite should start the test harness container and run it in CI (again, see references in Java and JS).
Add support for evaluation context described in the specification https://github.com/open-feature/spec/blob/main/specification/evaluation-context.md
Update the SDK to be compliant with the v0.2.0 spec.
Full Changelog: open-feature/spec@v0.1.0...v0.2.0
Investigate applying for myget opensource account this will be used to publish development builds
We need a targeting key
in the evaluation context. It should be added to the builder, and should be immutable (like all the props in the current implementation).
The evaluation context also lacks the required 'targeting key` field
Originally posted by @roelofb in #204 (comment)
Add InMemoryProvider
to SDK. See spec.
Tasks:
InMemoryProvider
.see Java equivalent.
Parent issue: #126
Update the readme to follow the new template. Once this is ready, the documentation can be configured to pull from the repo automatically.
Examples from other repos:
I think it is probably intended to link to a github search of some kind.
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
xunit
, xunit.runner.visualstudio
)These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.
System.Collections.Immutable
, System.Threading.Channels
).github/workflows/ci.yml
actions/checkout v4
actions/setup-dotnet v4
actions/checkout v4
actions/setup-dotnet v4
actions/upload-artifact v4.3.3
.github/workflows/code-coverage.yml
actions/checkout v4
actions/setup-dotnet v4
codecov/codecov-action v4.3.1
.github/workflows/codeql-analysis.yml
actions/checkout v4
github/codeql-action v3
github/codeql-action v3
github/codeql-action v3
.github/workflows/dotnet-format.yml
actions/checkout v4
actions/setup-dotnet v4
.github/workflows/e2e.yml
actions/checkout v4
actions/setup-dotnet v4
.github/workflows/lint-pr.yml
amannn/action-semantic-pull-request v5
.github/workflows/release.yml
google-github-actions/release-please-action v3
actions/checkout v4
actions/setup-dotnet v4
actions/checkout v4
.config/dotnet-tools.json
dotnet-format 5.1.250801
Directory.Packages.props
Microsoft.NETFramework.ReferenceAssemblies 1.0.3
xunit.runner.visualstudio 2.5.8
xunit 2.7.1
SpecFlow.xUnit 3.9.74
SpecFlow.Tools.MsBuild.Generation 3.9.74
SpecFlow 3.9.74
NSubstitute 5.1.0
Microsoft.NET.Test.Sdk 17.10.0
GitHubActionsTestLogger 2.3.3
FluentAssertions 6.12.0
coverlet.msbuild 6.0.2
coverlet.collector 6.0.2
BenchmarkDotNet 0.13.1
AutoFixture 4.18.1
System.ValueTuple 4.5.0
System.Threading.Channels 6.0.0
System.Collections.Immutable 1.7.1
Microsoft.Extensions.Logging.Abstractions 8.0.1
Microsoft.Bcl.AsyncInterfaces 8.0.0
global.json
dotnet-sdk 8.0.301
I think it's possible to define virtual methods on interfaces. Since the Hook abstract class has no state, I think there's no reason not to simply use IHook
everywhere for more flexibility (multiple inheritance, etc)
I'm wondering if we could get a consensus on using release please.
Basically, it's an github action that runs after commits/merges to main. It checks for semantic commits, and if it detects a feat/fix/breaking
change, it creates a running PR (see example in Java SDK here). The action automatically and intelligently increments the versions numbers in this PR with new commits to main by searching for annotations in XML/JSON/etc.
When these PRs are merged, the existing release process runs. Currently, we use this in the Java SDK, Go SDK, Node SDK, and all the contrib repos. To ease things for deveopers, we use github's "sqush and merge" setting to use the PR title as the commit message. We also have a github action that lints the commit message. This means that the only thing that needs to follow semantic commits is the PR title.
Benefits:
cc @benjiro
As part of C# 8.0, we have access to a Nullable Reference Types (NRT) feature. This allows the have a more explicit flow of nulls in the codebase.
The NRT feature holds you to a higher standard on how you deal with nulls, and as such it issues new warnings on existing code. So that those warnings (however useful) don’t break you, the feature must be explicitly enabled in your code before it starts complaining. Once you do that on existing code, you have work to do to make that code null-safe and satisfy the compiler that you did.
Check: https://devblogs.microsoft.com/dotnet/embracing-nullable-reference-types/
This might bring some potential breaking changes for the providers and customers that consume our library. I think this should be released with a breaking change alert.
To ease the migration, the new code created can use a preprocessor directive. See https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives#nullable-context
We have SBOMs currently for Java and Go. We could use them here as well. I recommend this utility: https://github.com/marketplace/actions/cyclonedx-net-generate-sbom (we're using the clyclonedx format elsewhere and it's popular).
Definition of done:
See convo here: #38 (comment)
Use https://benchmarkdotnet.org/ to make a suite of performance benchmarks to ensure OpenFeature.SDK has little overhead as possible.
Alpha Checklist:
Update the SDK to be compliant with the v0.3.0 spec.
Full Changelog: open-feature/spec@v0.2.0...v0.3.0
Update the SDK to be compliant with the v0.5.1 spec.
Update the badge on the readme to
Full Changelog: open-feature/spec@v0.5.0...v0.5.1
We want to be able to publish development builds to nuget so they are able to be distributed and tested by provider implementers before the major release.
Following open-feature/dotnet-sdk-contrib#132, the OpenFeature.Contrib.Hooks.Otel
package now only depends on OpenFeature
and OpenTelemetry.Api
, the latter of which in turn has just a single dependency on System.Diagnostics.DiagnosticSource
.
I'm proposing that we obsolete the OpenFeature.Contrib.Hooks.Otel
package and incorporate its contained code into the main OpenFeature
project to provide first-class telemetry support in line with other popular projects in the .NET ecosystem.
From open-telemetry/opentelemetry-dotnet
(emphasis added):
The inspiration of the OpenTelemetry project is to make every library observable out of the box by having them call OpenTelemetry API directly. However, many libraries will not have such integration, and as such there is a need for a separate library which would inject such calls, using mechanisms such as wrapping interfaces, subscribing to library-specific callbacks, or translating existing telemetry into OpenTelemetry model.
From open-telemetry/opentelemetry-dotnet
(emphasis added):
Application developers and library authors use OpenTelemetry API to instrument their application/library. The API only surfaces necessary abstractions to instrument an application/library. It does not address concerns like how telemetry is exported to a specific telemetry backend, how to sample the telemetry, etc. The API consists of Tracing API, Logging API, Metrics API, Context and Propagation API, and a set of semantic conventions.
OpenTelemetry.Api
is just too scary?I personally have a lot of faith in the open-telemetry/opentelemetry-dotnet
team, and thus place a lot of trust in their promise to maintain OpenTelemetry.Api
as a lightweight abstractions package, but for good measure, I do want to call out that we could accomplish this proposed in-the-box'ing without taking a dependency on OpenTelemetry.Api
.
To do this we would instead take a direct dependency on System.Diagnostics.DiagnosticSource
, and then reimplement-the-wheel for ActivityExtensions.RecordException(...)
, ActivityExtensions.SetStatus(...)
, etc.
Again, I'm not endorsing this, but it's an option (e.g. among many other reasons, it would be exceptionally peevish if our impl drifts from the upstream impl and exceptions recorded by another library have different formats in Datadog/Dynatrace/etc).
I'm eventually planning to offer this upstream as part of a new
OpenFeature.Extensions.Hosting
package à laOpenTelemetry.Extensions.Hosting
, but still working through the realistic use cases and general ergonomics, but just mentioning that so this doesn't seem entirely irrelevant to the project at hand.This has been suggested before, and I think it's a good idea. I would welcome such a PR, or at least an issue proposing it.
I'll open a new issue to track this, and will see about getting a draft PR put together over the next couple of weeks.
Originally posted by @austindrenski in open-feature/dotnet-sdk-contrib#125 (comment)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.