/// <summary>
        /// Return the matched sampling rule name if the sampler finds one
        /// and decide to sample. If no sampling rule matched, it falls back
        /// to <see cref="LocalizedSamplingStrategy"/> "ShouldTrace" implementation.
        /// All optional arguments are extracted from incoming requests by
        /// X-Ray middleware to perform path based sampling.
        /// </summary>
        /// <param name="input">Instance of <see cref="SamplingInput"/>.</param>
        /// <returns>Instance of <see cref="SamplingResponse"/>.</returns>
        public SamplingResponse ShouldTrace(SamplingInput input)
        {
            if (!_isPollerStarted) // Start pollers lazily
            {
                Start();
            }

            if (string.IsNullOrEmpty(input.ServiceType))
            {
                input.ServiceType = AWSXRayRecorder.Instance.Origin;
            }

            TimeStamp    time       = TimeStamp.CurrentTime();
            SamplingRule sampleRule = _ruleCache.GetMatchedRule(input, time);

            if (sampleRule != null)
            {
                _logger.DebugFormat("Rule {0} is selected to make a sampling decision.", sampleRule.RuleName);
                return(ProcessMatchedRule(sampleRule, time));
            }
            else
            {
                _logger.InfoFormat("No effective centralized sampling rule match. Fallback to local rules.");
                return(_localFallbackRules.ShouldTrace(input));
            }
        }
 internal Reservoir()
 {
     Quota        = null;
     TTL          = null;
     Interval     = _defaultInterval;
     _refreshedAt = TimeStamp.CurrentTime();
 }
        /// <summary>
        /// Gets sampling rules from the X-Ray service ans populates <see cref="RuleCache"/>.
        /// </summary>
        /// <returns>Task instance.</returns>
        private async Task RefreshCache()
        {
            TimeStamp time = TimeStamp.CurrentTime();
            GetSamplingRulesResponse response = await _connector.GetSamplingRules();

            if (response.IsRulePresent())
            {
                _ruleCache.LoadRules(response.Rules);
                _ruleCache.LastUpdated = time;
                _logger.InfoFormat("Successfully refreshed sampling rule cache.");
            }
        }
        /// <summary>
        /// Don't report a rule statistics if any of the conditions is met:
        /// 1. The report time hasn't come (some rules might have larger report intervals).
        /// 2. The rule is never matched.
        /// </summary>
        /// <returns>List of <see cref="SamplingRule"/>.</returns>
        private List <SamplingRule> GetCandidates()
        {
            List <SamplingRule>  candidates = new List <SamplingRule>();
            IList <SamplingRule> rules      = _ruleCache.GetRules();
            TimeStamp            now        = TimeStamp.CurrentTime();

            foreach (var rule in rules)
            {
                if (rule.ShouldReport(now))
                {
                    candidates.Add(rule);
                }
            }

            return(candidates);
        }
 /// <summary>
 /// Updates Targets in the cache
 /// </summary>
 /// <param name="targets"> Targets returned by GetSamplingTargets.</param>
 public void LoadTargets(IList <Target> targets)
 {
     _cacheLock.EnterReadLock();
     try
     {
         TimeStamp now = TimeStamp.CurrentTime();
         foreach (var t in targets)
         {
             if (_cache.TryGetValue(t.RuleName, out SamplingRule rule))
             {
                 rule.Reservior.LoadQuota(t, now);
                 rule.SetRate(t.FixedRate);
             }
         }
     }
     finally
     {
         _cacheLock.ExitReadLock();
     }
 }