public static void Veuilayout() { if (mInstance == null) { mInstance = (VeuiEditor)EditorWindow.GetWindow(typeof(VeuiEditor)); mInstance.titleContent.text = "Visual UI Layout"; mInstance.minSize = new Vector2(700, 500); mInstance.maxSize = new Vector2(5200, 5000); mInstance.Show(); Rect tmpwr = new Rect(zpx, zpy, 500, 350); aroll = new Rollout(tmpwr); //aroll.gid = "mainroll"; //aroll.gid=regmap(tmpwr, aroll); gdata = new guidata(); gdata.ctrlist = new Dictionary <string, Ctrbox>(); pctr.Add(aroll); ash = new Scalehandle(tmpwr); apan = new VUEPanel(tmpwr); } foreach (var ctr in map) { Debug.Log(ctr); } //VeuiEditor.showpth(); }
public void GetServiceRollout() { moq::Mock <ServiceManager.ServiceManagerClient> mockGrpcClient = new moq::Mock <ServiceManager.ServiceManagerClient>(moq::MockBehavior.Strict); mockGrpcClient.Setup(x => x.CreateOperationsClient()).Returns(new moq::Mock <lro::Operations.OperationsClient>().Object); GetServiceRolloutRequest request = new GetServiceRolloutRequest { ServiceName = "service_named5df05d5", RolloutId = "rollout_id174e7821", }; Rollout expectedResponse = new Rollout { RolloutId = "rollout_id174e7821", CreateTime = new wkt::Timestamp(), CreatedBy = "created_by206bd4da", Status = Rollout.Types.RolloutStatus.Cancelled, TrafficPercentStrategy = new Rollout.Types.TrafficPercentStrategy(), ServiceName = "service_named5df05d5", DeleteServiceStrategy = new Rollout.Types.DeleteServiceStrategy(), }; mockGrpcClient.Setup(x => x.GetServiceRollout(request, moq::It.IsAny <grpccore::CallOptions>())).Returns(expectedResponse); ServiceManagerClient client = new ServiceManagerClientImpl(mockGrpcClient.Object, null); Rollout response = client.GetServiceRollout(request.ServiceName, request.RolloutId); xunit::Assert.Same(expectedResponse, response); mockGrpcClient.VerifyAll(); }
private static void AssertVariationIndexFromRollout( int expectedVariation, Rollout rollout, User user, string flagKey, string salt ) { var flag1 = new FeatureFlagBuilder(flagKey) .On(true) .GeneratedVariations(3) .FallthroughRollout(rollout) .Salt(salt) .Build(); var result1 = BasicEvaluator.Evaluate(flag1, user, EventFactory.Default); Assert.Equal(EvaluationReason.FallthroughReason, result1.Result.Reason); Assert.Equal(expectedVariation, result1.Result.VariationIndex); // Make sure we consistently apply the rollout regardless of whether it's in a rule or a fallthrough var flag2 = new FeatureFlagBuilder(flagKey) .On(true) .GeneratedVariations(3) .Rules(new RuleBuilder().Id("id") .Rollout(rollout) .Clauses(new ClauseBuilder().Attribute(UserAttribute.Key).Op(Operator.In).Values(LdValue.Of(user.Key)).Build()) .Build()) .Salt(salt) .Build(); var result2 = BasicEvaluator.Evaluate(flag2, user, EventFactory.Default); Assert.Equal(EvaluationReason.RuleMatchReason(0, "id"), result2.Result.Reason); Assert.Equal(expectedVariation, result2.Result.VariationIndex); }
/// <summary>Snippet for CreateServiceRollout</summary> /// <remarks> /// This snippet has been automatically generated for illustrative purposes only. /// It may require modifications to work in your environment. /// </remarks> public void CreateServiceRollout() { // Create client ServiceManagerClient serviceManagerClient = ServiceManagerClient.Create(); // Initialize request argument(s) string serviceName = ""; Rollout rollout = new Rollout(); // Make the request Operation <Rollout, OperationMetadata> response = serviceManagerClient.CreateServiceRollout(serviceName, rollout); // Poll until the returned long-running operation is complete Operation <Rollout, OperationMetadata> completedResponse = response.PollUntilCompleted(); // Retrieve the operation result Rollout result = completedResponse.Result; // Or get the name of the operation string operationName = response.Name; // This name can be stored, then the long-running operation retrieved later by name Operation <Rollout, OperationMetadata> retrievedResponse = serviceManagerClient.PollOnceCreateServiceRollout(operationName); // Check if the retrieved long-running operation has completed if (retrievedResponse.IsCompleted) { // If it has completed, then access the result Rollout retrievedResult = retrievedResponse.Result; } }
private FeatureFlag BuildFlag() { var clause = new ClauseBuilder().Attribute("name").Op("in").Values(new JValue("x")).Negate(true).Build(); var wv = new WeightedVariation(0, 50); var rollout = new Rollout(new List <WeightedVariation> { wv }, "key"); var rule = new RuleBuilder().Id("ruleid").Variation(0).Rollout(rollout).Clauses(clause) .TrackEvents(true).Build(); var target = new Target(new List <string> { "userkey" }, 0); return(new FeatureFlagBuilder("flagkey") .DebugEventsUntilDate(100000) .Deleted(true) .Fallthrough(new VariationOrRollout(0, rollout)) .OffVariation(0) .On(true) .Prerequisites(new Prerequisite("prereq", 1)) .Rules(rule) .Salt("NaCl") .Targets(target) .TrackEvents(true) .TrackEventsFallthrough(true) .Variations(new JValue("value")) .Version(100) .Build()); }
public async stt::Task GetServiceRolloutAsync() { moq::Mock <ServiceManager.ServiceManagerClient> mockGrpcClient = new moq::Mock <ServiceManager.ServiceManagerClient>(moq::MockBehavior.Strict); mockGrpcClient.Setup(x => x.CreateOperationsClient()).Returns(new moq::Mock <lro::Operations.OperationsClient>().Object); GetServiceRolloutRequest request = new GetServiceRolloutRequest { ServiceName = "service_named5df05d5", RolloutId = "rollout_id174e7821", }; Rollout expectedResponse = new Rollout { RolloutId = "rollout_id174e7821", CreateTime = new wkt::Timestamp(), CreatedBy = "created_by206bd4da", Status = Rollout.Types.RolloutStatus.Cancelled, TrafficPercentStrategy = new Rollout.Types.TrafficPercentStrategy(), ServiceName = "service_named5df05d5", DeleteServiceStrategy = new Rollout.Types.DeleteServiceStrategy(), }; mockGrpcClient.Setup(x => x.GetServiceRolloutAsync(request, moq::It.IsAny <grpccore::CallOptions>())).Returns(new grpccore::AsyncUnaryCall <Rollout>(stt::Task.FromResult(expectedResponse), null, null, null, null)); ServiceManagerClient client = new ServiceManagerClientImpl(mockGrpcClient.Object, null); Rollout responseCallSettings = await client.GetServiceRolloutAsync(request.ServiceName, request.RolloutId, gaxgrpc::CallSettings.FromCancellationToken(st::CancellationToken.None)); xunit::Assert.Same(expectedResponse, responseCallSettings); Rollout responseCancellationToken = await client.GetServiceRolloutAsync(request.ServiceName, request.RolloutId, st::CancellationToken.None); xunit::Assert.Same(expectedResponse, responseCancellationToken); mockGrpcClient.VerifyAll(); }
/// <summary>Snippet for CreateServiceRolloutAsync</summary> /// <remarks> /// This snippet has been automatically generated for illustrative purposes only. /// It may require modifications to work in your environment. /// </remarks> public async Task CreateServiceRolloutRequestObjectAsync() { // Create client ServiceManagerClient serviceManagerClient = await ServiceManagerClient.CreateAsync(); // Initialize request argument(s) CreateServiceRolloutRequest request = new CreateServiceRolloutRequest { ServiceName = "", Rollout = new Rollout(), }; // Make the request Operation <Rollout, OperationMetadata> response = await serviceManagerClient.CreateServiceRolloutAsync(request); // Poll until the returned long-running operation is complete Operation <Rollout, OperationMetadata> completedResponse = await response.PollUntilCompletedAsync(); // Retrieve the operation result Rollout result = completedResponse.Result; // Or get the name of the operation string operationName = response.Name; // This name can be stored, then the long-running operation retrieved later by name Operation <Rollout, OperationMetadata> retrievedResponse = await serviceManagerClient.PollOnceCreateServiceRolloutAsync(operationName); // Check if the retrieved long-running operation has completed if (retrievedResponse.IsCompleted) { // If it has completed, then access the result Rollout retrievedResult = retrievedResponse.Result; } }
/// <summary>Snippet for GetServiceRollout</summary> /// <remarks> /// This snippet has been automatically generated for illustrative purposes only. /// It may require modifications to work in your environment. /// </remarks> public void GetServiceRollout() { // Create client ServiceManagerClient serviceManagerClient = ServiceManagerClient.Create(); // Initialize request argument(s) string serviceName = ""; string rolloutId = ""; // Make the request Rollout response = serviceManagerClient.GetServiceRollout(serviceName, rolloutId); }
/// <summary>Snippet for GetServiceRolloutAsync</summary> /// <remarks> /// This snippet has been automatically generated for illustrative purposes only. /// It may require modifications to work in your environment. /// </remarks> public async Task GetServiceRolloutAsync() { // Create client ServiceManagerClient serviceManagerClient = await ServiceManagerClient.CreateAsync(); // Initialize request argument(s) string serviceName = ""; string rolloutId = ""; // Make the request Rollout response = await serviceManagerClient.GetServiceRolloutAsync(serviceName, rolloutId); }
public PSRollout(string resourceGroupName, Rollout rollout) : base(rollout) { this.ResourceGroupName = resourceGroupName; this.BuildVersion = rollout.BuildVersion; this.ArtifactSourceId = rollout.ArtifactSourceId; this.TargetServiceTopologyId = rollout.TargetServiceTopologyId; this.Identity = rollout.Identity != null ? new PSIdentity(rollout.Identity) : null; this.OperationInfo = rollout.OperationInfo != null ? new PSRolloutOperationInfo(rollout.OperationInfo) : null; this.Status = rollout.Status; this.TotalRetryAttempts = rollout.TotalRetryAttempts; this.Services = rollout.Services?.Select(s => new PSService(s)).ToList(); }
/// <summary>Snippet for GetServiceRollout</summary> /// <remarks> /// This snippet has been automatically generated for illustrative purposes only. /// It may require modifications to work in your environment. /// </remarks> public void GetServiceRolloutRequestObject() { // Create client ServiceManagerClient serviceManagerClient = ServiceManagerClient.Create(); // Initialize request argument(s) GetServiceRolloutRequest request = new GetServiceRolloutRequest { ServiceName = "", RolloutId = "", }; // Make the request Rollout response = serviceManagerClient.GetServiceRollout(request); }
/// <summary>Snippet for GetServiceRolloutAsync</summary> /// <remarks> /// This snippet has been automatically generated for illustrative purposes only. /// It may require modifications to work in your environment. /// </remarks> public async Task GetServiceRolloutRequestObjectAsync() { // Create client ServiceManagerClient serviceManagerClient = await ServiceManagerClient.CreateAsync(); // Initialize request argument(s) GetServiceRolloutRequest request = new GetServiceRolloutRequest { ServiceName = "", RolloutId = "", }; // Make the request Rollout response = await serviceManagerClient.GetServiceRolloutAsync(request); }
public void LastBucketIsUsedIfBucketValueEqualsTotalWeight() { var user = User.WithKey("userkey"); const string flagKey = "flagkey"; const string salt = "salt"; // We'll construct a list of variations that stops right at the target bucket value int bucketValue = (int)(Bucketing.BucketUser(null, user, flagKey, UserAttribute.Key, salt) * 100000); var variations = new List <WeightedVariation>() { new WeightedVariation(0, bucketValue, true) }; var rollout = new Rollout(RolloutKind.Rollout, null, variations, null); AssertVariationIndexFromRollout(0, rollout, user, flagKey, salt); }
private static void AssertVariationIndexAndExperimentStateForRollout( int expectedVariation, bool expectedInExperiment, Rollout rollout, User user, string flagKey, string salt ) { var flag = new FeatureFlagBuilder(flagKey) .On(true) .GeneratedVariations(3) .FallthroughRollout(rollout) .Salt(salt) .Build(); var result = BasicEvaluator.Evaluate(flag, user, EventFactory.Default); Assert.Equal(expectedVariation, result.Result.VariationIndex); Assert.Equal(EvaluationReasonKind.Fallthrough, result.Result.Reason.Kind); Assert.Equal(expectedInExperiment, result.Result.Reason.InExperiment); }
private FeatureFlag BuildFlag() { var clause = new Clause("name", "in", new List <JValue> { new JValue("x") }, true); var wv = new WeightedVariation(0, 50); var rollout = new Rollout(new List <WeightedVariation> { wv }, "key"); var rule = new Rule("ruleid", 0, rollout, new List <Clause> { clause }); var target = new Target(new List <string> { "userkey" }, 0); return(new FeatureFlagBuilder("flagkey") .DebugEventsUntilDate(100000) .Deleted(true) .Fallthrough(new VariationOrRollout(0, rollout)) .OffVariation(0) .On(true) .Prerequisites(new List <Prerequisite> { new Prerequisite("prereq", 1) }) .Rules(new List <Rule> { rule }) .Salt("NaCl") .Targets(new List <Target> { target }) .TrackEvents(true) .Variations(new List <JToken> { new JValue("value") }) .Version(100) .Build()); }
public void VariationIndexForBucket() { var user = User.WithKey("userkey"); const string flagKey = "flagkey"; const string salt = "salt"; // First verify that with our test inputs, the bucket value will be greater than zero and less than 100000, // so we can construct a rollout whose second bucket just barely contains that value var bucketValue = (int)(Bucketing.BucketUser(null, user, flagKey, UserAttribute.Key, salt) * 100000); Assert.InRange(bucketValue, 1, 99999); const int badVariationA = 0, matchedVariation = 1, badVariationB = 2; var variations = new List <WeightedVariation>() { new WeightedVariation(badVariationA, bucketValue, true), // end of bucket range is not inclusive, so it will *not* match the target value new WeightedVariation(matchedVariation, 1, true), // size of this bucket is 1, so it only matches that specific value new WeightedVariation(badVariationB, 100000 - (bucketValue + 1), true) }; var rollout = new Rollout(RolloutKind.Rollout, null, variations, null); AssertVariationIndexFromRollout(matchedVariation, rollout, user, flagKey, salt); }
/// <summary> /// Try to bucket the user into a rollout rule. /// Evaluate the user for rules in priority order by seeing if the user satisfies the audience. /// Fall back onto the everyone else rule if the user is ever excluded from a rule due to traffic allocation. /// </summary> /// <param name = "featureFlag" >The feature flag the user wants to access.</param> /// <param name = "userId" >User Identifier</param> /// <param name = "filteredAttributes" >The user's attributes. This should be filtered to just attributes in the Datafile.</param> /// <param name = "reasons" >Decision log messages.</param> /// <returns>null if the user is not bucketed into the rollout or if the feature flag was not attached to a rollout. /// otherwise the FeatureDecision entity</returns> public virtual Result <FeatureDecision> GetVariationForFeatureRollout(FeatureFlag featureFlag, OptimizelyUserContext user, ProjectConfig config) { var reasons = new DecisionReasons(); if (featureFlag == null) { Logger.Log(LogLevel.ERROR, "Invalid feature flag provided."); return(Result <FeatureDecision> .NullResult(reasons)); } if (string.IsNullOrEmpty(featureFlag.RolloutId)) { Logger.Log(LogLevel.INFO, reasons.AddInfo($"The feature flag \"{featureFlag.Key}\" is not used in a rollout.")); return(Result <FeatureDecision> .NullResult(reasons)); } Rollout rollout = config.GetRolloutFromId(featureFlag.RolloutId); if (string.IsNullOrEmpty(rollout.Id)) { Logger.Log(LogLevel.ERROR, reasons.AddInfo($"The rollout with id \"{featureFlag.RolloutId}\" is not found in the datafile for feature flag \"{featureFlag.Key}\"")); return(Result <FeatureDecision> .NullResult(reasons)); } if (rollout.Experiments == null || rollout.Experiments.Count == 0) { return(Result <FeatureDecision> .NullResult(reasons)); } var rolloutRulesLength = rollout.Experiments.Count; var rolloutRules = rollout.Experiments; var userId = user.GetUserId(); var attributes = user.GetAttributes(); var index = 0; while (index < rolloutRulesLength) { // To skip rules var skipToEveryoneElse = false; //Check forced decision first var rule = rolloutRules[index]; var decisionContext = new OptimizelyDecisionContext(featureFlag.Key, rule.Key); var forcedDecisionResponse = ValidatedForcedDecision(decisionContext, config, user); reasons += forcedDecisionResponse.DecisionReasons; if (forcedDecisionResponse.ResultObject != null) { return(Result <FeatureDecision> .NewResult(new FeatureDecision(rule, forcedDecisionResponse.ResultObject, null), reasons)); } // Regular decision // Get Bucketing ID from user attributes. var bucketingIdResult = GetBucketingId(userId, attributes); reasons += bucketingIdResult.DecisionReasons; var everyoneElse = index == rolloutRulesLength - 1; var loggingKey = everyoneElse ? "Everyone Else" : string.Format("{0}", index + 1); // Evaluate if user meets the audience condition of this rollout rule var doesUserMeetAudienceConditionsResult = ExperimentUtils.DoesUserMeetAudienceConditions(config, rule, attributes, LOGGING_KEY_TYPE_RULE, rule.Key, Logger); reasons += doesUserMeetAudienceConditionsResult.DecisionReasons; if (doesUserMeetAudienceConditionsResult.ResultObject) { Logger.Log(LogLevel.INFO, reasons.AddInfo($"User \"{userId}\" meets condition for targeting rule \"{loggingKey}\".")); var bucketedVariation = Bucketer.Bucket(config, rule, bucketingIdResult.ResultObject, userId); reasons += bucketedVariation?.DecisionReasons; if (bucketedVariation?.ResultObject?.Key != null) { Logger.Log(LogLevel.INFO, reasons.AddInfo($"User \"{userId}\" is in the traffic group of targeting rule \"{loggingKey}\".")); return(Result <FeatureDecision> .NewResult(new FeatureDecision(rule, bucketedVariation.ResultObject, FeatureDecision.DECISION_SOURCE_ROLLOUT), reasons)); } else if (!everyoneElse) { //skip this logging for everyoneElse rule since this has a message not for everyoneElse Logger.Log(LogLevel.INFO, reasons.AddInfo($"User \"{userId}\" is not in the traffic group for targeting rule \"{loggingKey}\". Checking EveryoneElse rule now.")); skipToEveryoneElse = true; } } else { Logger.Log(LogLevel.DEBUG, reasons.AddInfo($"User \"{userId}\" does not meet the conditions for targeting rule \"{loggingKey}\".")); } // the last rule is special for "Everyone Else" index = skipToEveryoneElse ? (rolloutRulesLength - 1) : (index + 1); } return(Result <FeatureDecision> .NullResult(reasons)); }
/// <summary> /// Try to bucket the user into a rollout rule. /// Evaluate the user for rules in priority order by seeing if the user satisfies the audience. /// Fall back onto the everyone else rule if the user is ever excluded from a rule due to traffic allocation. /// </summary> /// <param name = "featureFlag" >The feature flag the user wants to access.</param> /// <param name = "userId" >User Identifier</param> /// <param name = "filteredAttributes" >The user's attributes. This should be filtered to just attributes in the Datafile.</param> /// <param name = "reasons" >Decision log messages.</param> /// <returns>null if the user is not bucketed into the rollout or if the feature flag was not attached to a rollout. /// otherwise the FeatureDecision entity</returns> public virtual Result <FeatureDecision> GetVariationForFeatureRollout(FeatureFlag featureFlag, string userId, UserAttributes filteredAttributes, ProjectConfig config) { var reasons = new DecisionReasons(); if (featureFlag == null) { Logger.Log(LogLevel.ERROR, "Invalid feature flag provided."); return(Result <FeatureDecision> .NullResult(reasons)); } if (string.IsNullOrEmpty(featureFlag.RolloutId)) { Logger.Log(LogLevel.INFO, reasons.AddInfo($"The feature flag \"{featureFlag.Key}\" is not used in a rollout.")); return(Result <FeatureDecision> .NullResult(reasons)); } Rollout rollout = config.GetRolloutFromId(featureFlag.RolloutId); if (string.IsNullOrEmpty(rollout.Id)) { Logger.Log(LogLevel.ERROR, reasons.AddInfo($"The rollout with id \"{featureFlag.RolloutId}\" is not found in the datafile for feature flag \"{featureFlag.Key}\"")); return(Result <FeatureDecision> .NullResult(reasons)); } if (rollout.Experiments == null || rollout.Experiments.Count == 0) { return(Result <FeatureDecision> .NullResult(reasons)); } Result <Variation> variationResult = null; var rolloutRulesLength = rollout.Experiments.Count; // Get Bucketing ID from user attributes. var bucketingIdResult = GetBucketingId(userId, filteredAttributes); reasons += bucketingIdResult.DecisionReasons; // For all rules before the everyone else rule for (int i = 0; i < rolloutRulesLength - 1; i++) { string loggingKey = (i + 1).ToString(); var rolloutRule = rollout.Experiments[i]; var userMeetConditionsResult = ExperimentUtils.DoesUserMeetAudienceConditions(config, rolloutRule, filteredAttributes, LOGGING_KEY_TYPE_RULE, loggingKey, Logger); reasons += userMeetConditionsResult.DecisionReasons; if (userMeetConditionsResult.ResultObject) { variationResult = Bucketer.Bucket(config, rolloutRule, bucketingIdResult.ResultObject, userId); reasons += variationResult?.DecisionReasons; if (string.IsNullOrEmpty(variationResult.ResultObject?.Id)) { break; } return(Result <FeatureDecision> .NewResult(new FeatureDecision(rolloutRule, variationResult.ResultObject, FeatureDecision.DECISION_SOURCE_ROLLOUT), reasons)); } else { Logger.Log(LogLevel.DEBUG, $"User \"{userId}\" does not meet the conditions for targeting rule \"{loggingKey}\"."); } } // Get the last rule which is everyone else rule. var everyoneElseRolloutRule = rollout.Experiments[rolloutRulesLength - 1]; var userMeetConditionsResultEveryoneElse = ExperimentUtils.DoesUserMeetAudienceConditions(config, everyoneElseRolloutRule, filteredAttributes, LOGGING_KEY_TYPE_RULE, "Everyone Else", Logger); reasons += userMeetConditionsResultEveryoneElse.DecisionReasons; if (userMeetConditionsResultEveryoneElse.ResultObject) { variationResult = Bucketer.Bucket(config, everyoneElseRolloutRule, bucketingIdResult.ResultObject, userId); reasons += variationResult?.DecisionReasons; if (!string.IsNullOrEmpty(variationResult?.ResultObject?.Id)) { Logger.Log(LogLevel.DEBUG, $"User \"{userId}\" meets conditions for targeting rule \"Everyone Else\"."); return(Result <FeatureDecision> .NewResult(new FeatureDecision(everyoneElseRolloutRule, variationResult.ResultObject, FeatureDecision.DECISION_SOURCE_ROLLOUT), reasons)); } } else { var audience = config.GetAudience(everyoneElseRolloutRule.AudienceIds[0]); Logger.Log(LogLevel.DEBUG, $"User \"{userId}\" does not meet the conditions to be in rollout rule for audience \"{audience.Name}\"."); } return(Result <FeatureDecision> .NewResult(null, reasons)); }
/// <summary> /// Try to bucket the user into a rollout rule. /// Evaluate the user for rules in priority order by seeing if the user satisfies the audience. /// Fall back onto the everyone else rule if the user is ever excluded from a rule due to traffic allocation. /// </summary> /// <param name = "featureFlag" >The feature flag the user wants to access.</param> /// <param name = "userId" >User Identifier</param> /// <param name = "filteredAttributes" >The user's attributes. This should be filtered to just attributes in the Datafile.</param> /// <returns>null if the user is not bucketed into the rollout or if the feature flag was not attached to a rollout. /// otherwise the FeatureDecision entity</returns> public virtual FeatureDecision GetVariationForFeatureRollout(FeatureFlag featureFlag, string userId, UserAttributes filteredAttributes, ProjectConfig config) { if (featureFlag == null) { Logger.Log(LogLevel.ERROR, "Invalid feature flag provided."); return(null); } if (string.IsNullOrEmpty(featureFlag.RolloutId)) { Logger.Log(LogLevel.INFO, $"The feature flag \"{featureFlag.Key}\" is not used in a rollout."); return(null); } Rollout rollout = config.GetRolloutFromId(featureFlag.RolloutId); if (string.IsNullOrEmpty(rollout.Id)) { Logger.Log(LogLevel.ERROR, $"The rollout with id \"{featureFlag.RolloutId}\" is not found in the datafile for feature flag \"{featureFlag.Key}\""); return(null); } if (rollout.Experiments == null || rollout.Experiments.Count == 0) { return(null); } Variation variation = null; var rolloutRulesLength = rollout.Experiments.Count; // Get Bucketing ID from user attributes. string bucketingId = GetBucketingId(userId, filteredAttributes); // For all rules before the everyone else rule for (int i = 0; i < rolloutRulesLength - 1; i++) { var rolloutRule = rollout.Experiments[i]; if (ExperimentUtils.IsUserInExperiment(config, rolloutRule, filteredAttributes, Logger)) { variation = Bucketer.Bucket(config, rolloutRule, bucketingId, userId); if (variation == null || string.IsNullOrEmpty(variation.Id)) { break; } return(new FeatureDecision(rolloutRule, variation, FeatureDecision.DECISION_SOURCE_ROLLOUT)); } else { var audience = config.GetAudience(rolloutRule.AudienceIds[0]); Logger.Log(LogLevel.DEBUG, $"User \"{userId}\" does not meet the conditions to be in rollout rule for audience \"{audience.Name}\"."); } } // Get the last rule which is everyone else rule. var everyoneElseRolloutRule = rollout.Experiments[rolloutRulesLength - 1]; if (ExperimentUtils.IsUserInExperiment(config, everyoneElseRolloutRule, filteredAttributes, Logger)) { variation = Bucketer.Bucket(config, everyoneElseRolloutRule, bucketingId, userId); if (variation != null && !string.IsNullOrEmpty(variation.Id)) { return(new FeatureDecision(everyoneElseRolloutRule, variation, FeatureDecision.DECISION_SOURCE_ROLLOUT)); } } else { var audience = config.GetAudience(everyoneElseRolloutRule.AudienceIds[0]); Logger.Log(LogLevel.DEBUG, $"User \"{userId}\" does not meet the conditions to be in rollout rule for audience \"{audience.Name}\"."); } return(null); }
internal RuleBuilder Rollout(Rollout rollout) { _rollout = rollout; return(this); }