Giter Club home page Giter Club logo

flagsmith-dotnet-client's Introduction

Flagsmith .NET SDK

The SDK for .NET Core, .NET Framework, Mono, Xamarin and Universal Windows Platform applications for https://www.flagsmith.com/.

Flagsmith .NET Engine

This Project powers the core Flagsmith API flag evaluations engine.

Flagsmith .NET Engine-Test

This Project contains all the Test Cases to evaluate the Engine functionality.

Adding to your project

For full documentation visit https://docs.flagsmith.com/clients/server-side.

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests

Getting Help

If you encounter a bug or feature request we would like to hear about it. Before you submit an issue please search existing issues in order to prevent duplicates.

Get in touch

If you have any questions about our projects you can email [email protected].

Useful links

Website

flagsmith-dotnet-client's People

Contributors

asadabbasfolio3 avatar benrometsch avatar dabeeeenster avatar dependabot[bot] avatar gagantrivedi avatar jfcote avatar khvn26 avatar kpdowns avatar luk355 avatar lukefanning avatar matthewelwell avatar menur avatar novakzaballa avatar tberger avatar vpetrusevici avatar xenm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flagsmith-dotnet-client's Issues

Identity overrides in local evaluation mode

  1. Extend the Environment model with the identity_overrides: List[IdentityModel] field.
  2. On environment update in local evaluation mode, store overrides so they're efficiently accessed by identifier.
  3. For GetIdentityFlagsFromDocument interface, use the storage above to retrieve the identity overrides. Fall back to a new IdentityModel instance if not found. If found, update traits with user-provided traits.

Refer to the following existing implementations:

Flagsmith/flagsmith-python-client#72
Flagsmith/flagsmith-java-client#142
Flagsmith/flagsmith-nodejs-client#143

HttpClient is intended to be instantiated once and re-used throughout the life of an application

https://github.com/SolidStateGroup/bullet-train-dotnet-client/blob/12413ec6b940479feec5df1180377aa226003d04/BulletTrainClient.cs#L158

HttpClient is intended to be instantiated once and re-used throughout the life of an application. Instantiating an HttpClient class for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors. See
https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netframework-4.7.2

Be aware of the DNS issue described here
http://byterot.blogspot.com/2016/07/singleton-httpclient-dns.html

FlagsmithClient's interface was completely changed

Hi,

We were using Flagsmith 3.1.0 nuget package and thought to upgrade and it seems that all the interface has changed...
Was the 3.1.0 a beta release? What are the plans with the future releases? Are there any breaking changes expected there?
We see that there is no SetTraits method in the new interface. So how do we add users and traits dynamically in the new version?

Thanks,
Sveta

Don't log errors using Console.WriteLine

Example:

Console.WriteLine("\nJSON Exception Caught!");

There is no guarantee that the process has a console, and if it doesn't then an attempt to write to the non-existent console can bring down the entire application. Ideally you'd want to use a proper logging framework, but since the usage here is relatively limited you could implement a simple check before writing to the console: if (Console.WindowHeight > 0) { Console.WriteLine("Error"); }

When identity is specified a redundant slash character is added in the end

Hi,

I've noticed that if I use identity, then a user is added with incorrect id, such as user_id/. It's because of AppendPath in the class UrlExtension.
There are two consequences from this:

  1. the user has additional slash which wasn't specified in the client application
  2. BulletTrain Web doesn't correctly show user with additional slash.

At the same time this is not crucial issue. It is still possible to use Web and Api with this identity.

Regards,

Can't install SDK on new projects

I was trying to install the SDK version 4.0.0. on a project that throws the error.

Severity	Code	Description	Project	File	Line	Suppression State
Error	NU1101	Unable to find package Flagsmith.Engine. No packages exist with this id in source(s): Microsoft Visual Studio Offline Packages, nuget.org	Todo	D:\projects\xamarin-forms-samples\Todo\Todo\Todo\Todo.csproj	1	

Later, I created a new xamarin project(to check if it works on .Net 6) it still showed the same error while installing the nuget package

small question why doesn't /flags API return tags?

Caching does not implement a max size

Currently the caching implementation does not implement a max size. We should add a configurable limit to the size of the cache to ensure that there are no memory concerns when using the cache implementation in the client.

Exception: System.ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported

Hi,
We were getting this error in production environment on one of our pods:

Screenshot 2024-01-24 at 14 26 26

It started yesterday evening, and restarting of the pod stopped it. We followed your example how to register service, also didn't have any related changes recently. Stack pointing to this one:

public async Task TrackFeature(string featureName)
    {
      int num;
      this.AnalyticsData[featureName] = this.AnalyticsData.TryGetValue(featureName, out num) ? num + 1 : 1;
      if ((DateTime.Now - this._LastFlushed).Seconds <= this._FlushIntervalSeconds)
        return;
      await this.Flush();
    } 

Do you have any idea why this happened, could it be related to lack of thread safety?

We are using version 5.0.1

When called consecutively, HasFeatureFlag method gets an error on the second run

I've been trying 2.0.0 BulletTrain Client SDK on a .NetCore 3.1 WebApi project and on a Console application. For Api calls, my initial plan was to run an on-prem version on Docker. But also I tried "https://app.bullet-train.io/" with a free account.

  • Console Application works properly. But WebApi project fails when a second call is made to the BulletTrain Api.

  • So here's my sample code for Console App,

            BulletTrainConfiguration configuration = new BulletTrainConfiguration()
            {
                ApiUrl = "http://localhost:8000/api/v1/",
                EnvironmentKey = "my-local-env-key"
            };

            BulletTrainClient bulletClient = new BulletTrainClient(configuration);
            bool featureEnabled = await bulletClient.HasFeatureFlag("is_it_weekend");
                if (featureEnabled) {
                    // Run the code to execute enabled feature
                    Console.WriteLine("Hello World!");
                } else {
                    // Run the code if feature switched off
                    Console.WriteLine("GoodBye World!");
                }
  • Here is the sample code from the WebApi project, they're almost identical (I used BulletTrain docs for implementation)
            BulletTrainConfiguration configuration = new BulletTrainConfiguration()
            {
                ApiUrl = "http://localhost:8000/api/v1/",
                EnvironmentKey = "my-local-env-key"
            };

            BulletTrainClient bulletClient = new BulletTrainClient(configuration);
            bool featureEnabled = await bulletClient.HasFeatureFlag("is_it_weekend");
            if (featureEnabled) {
                // Run the code to execute enabled feature
                return Ok(myWeekendItem);
            } else {
                // Run the code if feature switched off
                return NotFound();
            }
  • When I run it for the first time, it works properly. Without even changing anything, when I run on the web api the second time, it throws the below exception:

Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware: Error: An unhandled exception has occurred while executing the request.

System.NullReferenceException: Object reference not set to an instance of an object.
at BulletTrain.BulletTrainClient.GetFeatureFlags(String identity)
at BulletTrain.BulletTrainClient.HasFeatureFlag(String featureId, String identity)
at Glossary.Controllers.GlossaryController.Get(String term) in /Users/sevikarakose/Projects/Glossary/Controllers/GlossaryController.cs:line 52
at lambda_method(Closure , Object )
at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult()
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Fix package validation errors

The following errors are seen when validating a locally built package:

{
  "Packages": {
    "/Users/kgustyr/dev/flagsmith/flagsmith-dotnet-client/Flagsmith.FlagsmithClient/bin/Release/Flagsmith.5.3.0.nupkg": {
      "Errors": [
        {
          "ErrorCode": 101,
          "Message": "XML documentation not found",
          "HelpText": "lib/netstandard2.0/Flagsmith.Engine.dll"
        },
        {
          "ErrorCode": 101,
          "Message": "XML documentation not found",
          "HelpText": "lib/netstandard2.0/Flagsmith.FlagsmithClient.dll"
        },
        {
          "ErrorCode": 111,
          "Message": "Symbol file not found",
          "FileName": "lib/netstandard2.0/Flagsmith.FlagsmithClient.dll"
        },
        {
          "ErrorCode": 111,
          "Message": "Symbol file not found",
          "FileName": "lib/netstandard2.0/Flagsmith.Engine.dll"
        },
        {
          "ErrorCode": 74,
          "Message": "Repository commit is not set"
        },
        {
          "ErrorCode": 72,
          "Message": "Repository type is not set"
        },
        {
          "ErrorCode": 61,
          "Message": "Readme is not set"
        },
        {
          "ErrorCode": 12,
          "Message": "\u003Cauthors\u003E element is not set explicitly (same as \u003Cid\u003E)"
        }
      ]
    }
  }
}

These need to be resolved and removed from the --excluded-rule-ids validator argument in the release workflow.

Question: DI registration example

Hi guys!
I see in the example you register Flagsmith client as singleton, but in fact this is a typed httpclient.
Is it better to use this approach mb?

services.Configure<FlagsmithConfiguration>(builder.Configuration.GetSection(nameof(FlagsmithConfiguration)));
services.AddHttpClient<IFlagsmithClient, FlagsmithClient>(nameof(FlagsmithClient));

Because static/singleton HttpClient doesn't respect DNS changes and is considered bad practice. See details here

using .NET client SDK always return "Value cannot be null. Parameter name: value" error

When we use .NET client SDK always return "Value cannot be null. Parameter name: value" error.

When we call .net code like below

        BulletTrainConfiguration configuration = new BulletTrainConfiguration()
        {
            ApiUrl = "https://features.xyz.ca/api/v1/",
            EnvironmentKey = EnvironmentKey
        };

        BulletTrainClient bulletClient = new BulletTrainClient(configuration);
        bool featureEnabled = await BulletTrainClient.instance.HasFeatureFlag("configuration_resource");
        string result = "";
        if (featureEnabled)
        {
            result = " run the code to execute enabled feature";
        }
        else
        {
            result = "run the code if feature switched off";
        } 
        return "value - " + result;

Generate Exception

<Message>An error has occurred.</Message>
<ExceptionMessage>Value cannot be null. Parameter name: value</ExceptionMessage>
<ExceptionType>System.ArgumentNullException</ExceptionType>

After some investigation about the inner HTTP call to the API, we found that the root cause is that :

GET https://features.xyz.ca/api/v1/flags/ HTTP/1.1
X-Environment-Key: xyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxy
Host: features.xyz.ca
Connection: Keep-Alive

This returns :

 HTTP/1.1 403 Forbidden
 Server: awselb/2.0
Date: Thu, 17 Sep 2020 14:26:42 GMT
Content-Type: text/html
Content-Length: 134
Connection: keep-alive

<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
</body>
</html>

After some investigation and compare between .NET SDK and Direct API Access by curl , we found that the direct call to curl is working with same parameters

curl https://features.xyz.ca/api/v1/flags/ -H "X-Environment-Key: xyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxy"

This return all features in JSON.

So, why .NET SDK not working, any Idea?

Not getting flags after hitting request second time from method GetIdentityFlags

I have incorporated SDK 5.1.0 and implemented the below code in ASP.NET MVC application (not core) which is running on .NET 4.7.2.

using Flagsmith;
using System;
using System.Configuration;
using System.Threading.Tasks;

namespace FeatureFlagHelper
{
    public class FlagsmithClientHelper
    {
        private readonly IFlagsmithClient _flagsmithClient;

        public FlagsmithClientHelper()
        {
            FlagsmithConfiguration configuration = new FlagsmithConfiguration()
            {
                EnvironmentKey = ConfigurationManager.AppSettings["FlagsmithEnvironmentKey"],
                EnableClientSideEvaluation = Convert.ToBoolean(ConfigurationManager.AppSettings["EnableClientSideEvaluation"]),
                EnvironmentRefreshIntervalSeconds = Convert.ToInt32(ConfigurationManager.AppSettings["EnvironmentRefreshIntervalSeconds"]),
                EnableAnalytics = Convert.ToBoolean(ConfigurationManager.AppSettings["EnableAnalytics"]),
                RequestTimeout = Convert.ToDouble(ConfigurationManager.AppSettings["RequestTimeout"]),
                Retries = Convert.ToInt32(ConfigurationManager.AppSettings["Retries"])

            };

            _flagsmithClient = new FlagsmithClient(configuration);
        }

        public async Task<bool> IsFlagEnabled(string flagName, string identity)
        {
            var flags = await this._flagsmithClient.GetIdentityFlags(identity, null);
            var flagStatus = await flags.IsFeatureEnabled(flagName.ToLower());

            return flagStatus;
        }
    }
}

I am calling this class post initializing and am trying to get the flagStatus whether it is turned on or off. Like this

 public static bool IsSomeFlagEnabled(string email)
        {
            var flagsmithClientHelper = new FlagsmithClientHelper();
            return flagsmithClientHelper.IsFlagEnabled("issomeflagenabled", "[email protected]").Result;
        } 

Now this code works perfectly fine when it fetches the flag status the very first time but once the second calls comes to get the flag status this piece of code goes in wait and the debugger never returns to the next statement:

var flags = await this._flagsmithClient.GetIdentityFlags(identity, null);

After above code the debugger doesn't return to the code. it's like the thread has gone in infinite wait.
I have to reset IIS and start the application again to get rid of this infinite wait issue.
Please help me with the fix.

image

Implement SDK-side Caching

Hi There,

It looks like the .Net client does a request to the endpoint every single time, any plans to cache the flags on the backend, say for 30 seconds?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.