Пример #1
0
    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);
        }
Пример #4
0
        /// <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);
 }
Пример #9
0
        /// <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);
        }
Пример #10
0
 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();
 }
Пример #11
0
 /// <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);
 }
Пример #12
0
        /// <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);
        }
Пример #14
0
        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);
        }
Пример #17
0
        /// <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));
        }
Пример #18
0
        /// <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));
        }
Пример #19
0
        /// <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);
        }
Пример #20
0
 internal RuleBuilder Rollout(Rollout rollout)
 {
     _rollout = rollout;
     return(this);
 }