//----------------------------------------------------------------------------- // // Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). // You may not use this file except in compliance with the License. // A copy of the License is located at // // http://aws.amazon.com/apache2.0 // // or in the "license" file accompanying this file. This file is distributed // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either // express or implied. See the License for the specific language governing // permissions and limitations under the License. // //----------------------------------------------------------------------------- using Amazon.Runtime.Internal.Util; using Amazon.XRay.Recorder.Core; using Amazon.XRay.Recorder.Core.Internal.Utils; using Amazon.XRay.Recorder.Core.Sampling.Local; using System; namespace Amazon.XRay.Recorder.Core.Sampling { /// /// Making sampling decisions based on sampling rules defined /// by X-Ray control plane APIs.It will fall back to if /// sampling rules are not available. /// public class DefaultSamplingStrategy : ISamplingStrategy { private static readonly Logger _logger = Logger.GetLogger(typeof(DefaultSamplingStrategy)); private ISamplingStrategy _localFallbackRules; private RuleCache _ruleCache; private RulePoller _rulePoller; private TargetPoller _targetPoller; private IConnector _connector; private bool _isPollerStarted = false; private readonly Object _lock = new Object(); /// /// Instance of . /// public DaemonConfig DaemonCfg { get; private set; } /// /// Instance of . /// public XRayConfig XRayConfig = null; /// /// Instance of . /// public DefaultSamplingStrategy() { _localFallbackRules = new LocalizedSamplingStrategy(); InititalizeStrategy(); } /// /// Instance of . /// /// Path to local sampling maifest file. public DefaultSamplingStrategy(string samplingRuleManifest) { _localFallbackRules = new LocalizedSamplingStrategy(samplingRuleManifest); InititalizeStrategy(); } private void InititalizeStrategy() { _ruleCache = new RuleCache(); _rulePoller = new RulePoller(_ruleCache); _targetPoller = new TargetPoller(_ruleCache, _rulePoller); } /// /// Start rule poller and target poller. /// private void Start() { lock (_lock) { if (!_isPollerStarted) { _connector = new ServiceConnector(DaemonCfg, XRayConfig); _rulePoller.Poll(_connector); _targetPoller.Poll(_connector); _isPollerStarted = true; } } } /// /// Return the matched sampling rule name if the sampler finds one /// and decide to sample. If no sampling rule matched, it falls back /// to "ShouldTrace" implementation. /// All optional arguments are extracted from incoming requests by /// X-Ray middleware to perform path based sampling. /// /// Instance of . /// Instance of . public SamplingResponse ShouldTrace(SamplingInput input) { if (!_isPollerStarted && !AWSXRayRecorder.Instance.IsTracingDisabled()) // Start pollers lazily and only if tracing is not disabled. { 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 DefaultSamplingStrategy.ProcessMatchedRule(sampleRule, time); } else { _logger.InfoFormat("No effective centralized sampling rule match. Fallback to local rules."); return _localFallbackRules.ShouldTrace(input); } } private static SamplingResponse ProcessMatchedRule(SamplingRule sampleRule, TimeStamp time) { bool shouldSample = true; Reservior reservior = sampleRule.Reservior; sampleRule.IncrementRequestCount(); // increment request counter for matched rule ReserviorDecision reserviorDecision = reservior.BorrowOrTake(time, sampleRule.CanBorrow); // check if we can borrow or take from reservior if (reserviorDecision == ReserviorDecision.Borrow) { sampleRule.IncrementBorrowCount(); } else if (reserviorDecision == ReserviorDecision.Take) { sampleRule.IncrementSampledCount(); } else if (ThreadSafeRandom.NextDouble() <= sampleRule.GetRate()) // compute based on fixed rate { sampleRule.IncrementSampledCount(); } else { shouldSample = false; } SamplingResponse sampleResult; if (shouldSample) { sampleResult = new SamplingResponse(sampleRule.RuleName, SampleDecision.Sampled); } else { sampleResult = new SamplingResponse(SampleDecision.NotSampled); } return sampleResult; } /// /// Configures X-Ray client with given instance. /// /// An instance of . public void LoadDaemonConfig(DaemonConfig daemonConfig) { DaemonCfg = daemonConfig; } } }