예제 #1
0
        public ValidatorResult IsValid(string trafficType, string method)
        {
            if (trafficType == null)
            {
                _log.Error($"{method}: you passed a null traffic_type, traffic_type must be a non-empty string");
                return(new ValidatorResult {
                    Success = false
                });
            }

            if (trafficType == string.Empty)
            {
                _log.Error($"{method}: you passed an empty traffic_type, traffic_type must be a non-empty string");
                return(new ValidatorResult {
                    Success = false
                });
            }

            if (trafficType.Any(ch => char.IsUpper(ch)))
            {
                _log.Warn($"{method}: {trafficType} should be all lowercase - converting string to lowercase");

                trafficType = trafficType.ToLower();
            }

            if (!_splitCache.TrafficTypeExists(trafficType))
            {
                _log.Warn($"Track: Traffic Type {trafficType} does not have any corresponding Splits in this environment, make sure you’re tracking your events to a valid traffic type defined in the Split console.");
            }

            return(new ValidatorResult {
                Success = true, Value = trafficType
            });
        }
예제 #2
0
        public void Increase(string apiKey)
        {
            lock (_lock)
            {
                var exists = _factoryInstantiations.TryGetValue(apiKey, out int quantity);

                if (exists)
                {
                    if (quantity >= 1)
                    {
                        _log.Warn($"factory instantiation: You already have {quantity} factories with this API Key. We recommend keeping only one instance of the factory at all times(Singleton pattern) and reusing it throughout your application.");
                    }

                    var newQuantity = quantity + 1;

                    _factoryInstantiations.TryUpdate(apiKey, newQuantity, quantity);

                    return;
                }

                if (_factoryInstantiations.Count > 0)
                {
                    _log.Warn("factory instantiation: You already have an instance of the Split factory. Make sure you definitely want this additional instance. We recommend keeping only one instance of the factory at all times(Singleton pattern) and reusing it throughout your application.");
                }

                _factoryInstantiations.TryAdd(apiKey, 1);
            }
        }
예제 #3
0
        public List <string> SplitNamesAreValid(List <string> splitNames, string method)
        {
            if (splitNames == null)
            {
                _log.Error($"{method}: split_names must be a non-empty array");
                return(splitNames);
            }

            if (!splitNames.Any())
            {
                _log.Error($"{method}: split_names must be a non-empty array");
                return(splitNames);
            }

            var dicSplits = new Dictionary <string, string>();

            foreach (var name in splitNames)
            {
                var splitNameResult = SplitNameIsValid(name, method);

                if (splitNameResult.Success)
                {
                    try
                    {
                        dicSplits.Add(splitNameResult.Value, splitNameResult.Value);
                    }
                    catch
                    {
                        _log.Warn($"{method}: error adding splitName into list.");
                    }
                }
            }

            return(dicSplits.Keys.ToList());
        }
예제 #4
0
        public EventValidatorResult IsValid(Dictionary <string, object> properties)
        {
            if (properties == null)
            {
                return new EventValidatorResult {
                           Success = true
                }
            }
            ;

            var propertiesResult = new Dictionary <string, object>();
            var size             = 1024L;

            if (properties.Count > 300)
            {
                _log.Warn("Event has more than 300 properties. Some of them will be trimmed when processed");
            }

            foreach (var entry in properties)
            {
                size += entry.Key.Length;
                var value = entry.Value;

                if (!(value is null) && !IsNumeric(value) && !(value is bool) && !(value is string))
                {
                    _log.Warn($"Property {value.GetType()} is of invalid type. Setting value to null");
                    value = null;
                }

                if (value is string)
                {
                    size += ((string)value).Length;
                }

                if (size > MAX_PROPERTIES_LENGTH_BYTES)
                {
                    _log.Error($"The maximum size allowed for the properties is 32768 bytes. Current one is {size} bytes. Event not queued");
                    return(new EventValidatorResult {
                        Success = false
                    });
                }

                propertiesResult.Add(entry.Key, value);
            }

            return(new EventValidatorResult
            {
                Success = true,
                Value = propertiesResult,
                EventSize = size
            });
        }
예제 #5
0
        private TreatmentResult EvaluateTreatment(Key key, ParsedSplit parsedSplit, string featureName, Stopwatch clock = null, Dictionary <string, object> attributes = null)
        {
            try
            {
                if (clock == null)
                {
                    clock = new Stopwatch();
                    clock.Start();
                }

                if (parsedSplit == null)
                {
                    _log.Warn($"GetTreatment: you passed {featureName} that does not exist in this environment, please double check what Splits exist in the web console.");

                    return(new TreatmentResult(Labels.SplitNotFound, Control, elapsedMilliseconds: clock.ElapsedMilliseconds));
                }

                var treatmentResult = GetTreatmentResult(key, parsedSplit, attributes);

                if (parsedSplit.configurations != null && parsedSplit.configurations.ContainsKey(treatmentResult.Treatment))
                {
                    treatmentResult.Config = parsedSplit.configurations[treatmentResult.Treatment];
                }

                treatmentResult.ElapsedMilliseconds = clock.ElapsedMilliseconds;

                return(treatmentResult);
            }
            catch (Exception e)
            {
                _log.Error($"Exception caught getting treatment for feature: {featureName}", e);

                return(new TreatmentResult(Labels.Exception, Control, elapsedMilliseconds: clock.ElapsedMilliseconds));
            }
        }
예제 #6
0
        private string GetSdkMachineIP(ConfigurationOptions config, bool ipAddressesEnabled, ISplitLogger log)
        {
            if (ipAddressesEnabled)
            {
                try
                {
#if NETSTANDARD
                    var hostAddressesTask = Dns.GetHostAddressesAsync(Environment.MachineName);
                    hostAddressesTask.Wait();
                    return(config.SdkMachineIP ?? hostAddressesTask.Result.Where(x => x.AddressFamily == AddressFamily.InterNetwork && x.IsIPv6LinkLocal == false).Last().ToString());
#else
                    return(config.SdkMachineIP ?? Dns.GetHostAddresses(Environment.MachineName).Where(x => x.AddressFamily == AddressFamily.InterNetwork && x.IsIPv6LinkLocal == false).Last().ToString());
#endif
                }
                catch (Exception e)
                {
                    log.Warn("Exception retrieving machine IP.", e);
                    return(Constants.Gral.Unknown);
                }
            }
            else if (config.CacheAdapterConfig?.Type == AdapterType.Redis)
            {
                return(Constants.Gral.NA);
            }

            return(string.Empty);
        }
예제 #7
0
        private void SendBulkEvents()
        {
            if (_wrappedEventsCache.HasReachedMaxSize())
            {
                Logger.Warn("Split SDK events queue is full. Events may have been dropped. Consider increasing capacity.");
            }

            var wrappedEvents = _wrappedEventsCache.FetchAllAndClear();

            if (wrappedEvents.Count > 0)
            {
                try
                {
                    var events = wrappedEvents
                                 .Select(x => x.Event)
                                 .ToList();

                    _apiClient.SendBulkEvents(events);

                    _acumulateSize = 0;
                }
                catch (Exception e)
                {
                    Logger.Error("Exception caught updating events.", e);
                }
            }
        }
예제 #8
0
        private int GetMinimunAllowed(int value, int minAllowed, string configName)
        {
            if (value < minAllowed)
            {
                _log.Warn($"{configName} minimum allowed value: {minAllowed}");

                return(minAllowed);
            }

            return(value);
        }
예제 #9
0
        private string CheckWhiteSpaces(string splitName, string method)
        {
            if (splitName.StartsWith(WHITESPACE) || splitName.EndsWith(WHITESPACE))
            {
                _log.Warn($"{method}: split name {splitName} has extra whitespace, trimming");

                splitName = splitName.TrimStart();
                splitName = splitName.TrimEnd();
            }

            return(splitName);
        }
예제 #10
0
        public void BlockUntilReady(int blockMilisecondsUntilReady)
        {
            if (!IsSdkReady())
            {
                if (blockMilisecondsUntilReady <= 0)
                {
                    _log.Warn("The blockMilisecondsUntilReady param has to be higher than 0.");
                }

                if (!_gates.IsSDKReady(blockMilisecondsUntilReady))
                {
                    throw new TimeoutException(string.Format($"SDK was not ready in {blockMilisecondsUntilReady} miliseconds"));
                }
            }
        }
예제 #11
0
        public void BlockUntilReady(int blockMilisecondsUntilReady)
        {
            if (!IsSdkReady())
            {
                if (blockMilisecondsUntilReady <= 0)
                {
                    _log.Warn("The blockMilisecondsUntilReady param has to be higher than 0.");
                }

                if (!_statusManager.WaitUntilReady(blockMilisecondsUntilReady))
                {
                    _telemetryInitProducer.RecordBURTimeout();
                    throw new TimeoutException(string.Format($"SDK was not ready in {blockMilisecondsUntilReady} miliseconds"));
                }
            }
        }
예제 #12
0
 public void AddTag(string tag)
 {
     try
     {
         if (_tags.Count < 10)
         {
             _tags.TryAdd(tag, tag);
         }
     }
     catch (Exception ex)
     {
         _log.Warn("Exception caught executing AddTag", ex);
     }
 }
예제 #13
0
        public SplitView Split(string featureName)
        {
            if (!IsSdkReady(nameof(Split)) || _splitCache == null)
            {
                return(null);
            }

            var result = _splitNameValidator.SplitNameIsValid(featureName, nameof(Split));

            if (!result.Success)
            {
                return(null);
            }

            featureName = result.Value;

            var split = _splitCache.GetSplit(featureName);

            if (split == null)
            {
                _log.Warn($"split: you passed {featureName} that does not exist in this environment, please double check what Splits exist in the web console.");

                return(null);
            }

            var condition = split.conditions.Where(x => x.conditionType == ConditionType.ROLLOUT).FirstOrDefault() ?? split.conditions.FirstOrDefault();

            var treatments = condition != null?condition.partitions.Select(y => y.treatment).ToList() : new List <string>();

            var lightSplit = new SplitView()
            {
                name         = split.name,
                killed       = split.killed,
                changeNumber = split.changeNumber,
                treatments   = treatments,
                trafficType  = split.trafficTypeName,
                configs      = split.configurations
            };

            return(lightSplit);
        }
예제 #14
0
        private void SendBulkImpressions()
        {
            if (_impressionsCache.HasReachedMaxSize())
            {
                Logger.Warn("Split SDK impressions queue is full. Impressions may have been dropped. Consider increasing capacity.");
            }

            var impressions = _impressionsCache.FetchAllAndClear();

            if (impressions.Count > 0)
            {
                try
                {
                    _apiClient.SendBulkImpressions(impressions);
                }
                catch (Exception e)
                {
                    Logger.Error("Exception caught updating impressions.", e);
                }
            }
        }
예제 #15
0
        private string GetSdkMachineName(ConfigurationOptions config, bool ipAddressesEnabled, ISplitLogger log)
        {
            if (ipAddressesEnabled)
            {
                try
                {
                    return(config.SdkMachineName ?? Environment.MachineName);
                }
                catch (Exception e)
                {
                    log.Warn("Exception retrieving machine name.", e);
                    return(Constants.Gral.Unknown);
                }
            }
            else if (config.CacheAdapterConfig?.Type == AdapterType.Redis)
            {
                return(Constants.Gral.NA);
            }

            return(string.Empty);
        }
예제 #16
0
        public bool RegisterSegment(string segmentName)
        {
            if (string.IsNullOrEmpty(segmentName) || AreSplitsReady(0))
            {
                return(false);
            }

            try
            {
                segmentsAreReady.Add(segmentName, new CountdownEvent(1));
                if (Log.IsDebugEnabled)
                {
                    Log.Debug("Registered segment: " + segmentName);
                }
            }
            catch (ArgumentException e)
            {
                Log.Warn("Already registered segment: " + segmentName, e);
            }

            return(true);
        }