public void TestFixedTargetAndRateBehaveCorrectly()
        {
            var strategy = new LocalizedSamplingStrategy();

            strategy.Rules.Add(new Core.Sampling.Local.SamplingRule("name", "test", "get", 10, 0.05));
            int count = 0;

            // fill the fixed target rate
            Action action = () =>
            {
                var input = new SamplingInput("name", "test", "get", "", "");
                if (strategy.ShouldTrace(input).SampleDecision == SampleDecision.Sampled)
                {
                    Interlocked.Increment(ref count);
                }
            };
            var actions = Enumerable.Repeat(action, 10).ToArray();

            Parallel.Invoke(actions);
            Assert.AreEqual(10, count);

            count = 0;
            var samplingInput = new SamplingInput("name", "test", "get", "", "");

            for (int i = 0; i < 200; i++)
            {
                count += strategy.ShouldTrace(samplingInput).SampleDecision == SampleDecision.Sampled ? 1 : 0;
            }

            // Default sample rate is 5%. The chance that count == 0 after 200 tries is 0.003%.
            Assert.IsTrue(count > 0);
            Assert.IsTrue(count < 50);
        }
Exemple #2
0
        public static void ContinueFrom(this AWSXRayRecorder recorder, string serviceName, Message message)
        {
            var traceHeader = message?.GetTraceHeader() ?? new TraceHeader
            {
                RootTraceId = TraceId.NewId(),
                ParentId    = null,
                Sampled     = SampleDecision.Unknown
            };

            string ruleName = null;

            if (traceHeader.Sampled == SampleDecision.Unknown || traceHeader.Sampled == SampleDecision.Requested)
            {
                var samplingInput  = new SamplingInput(serviceName);
                var sampleResponse = recorder.SamplingStrategy.ShouldTrace(samplingInput);
                traceHeader.Sampled = sampleResponse.SampleDecision;
                ruleName            = sampleResponse.RuleName;
            }

            var samplingResponse = new SamplingResponse(ruleName, traceHeader.Sampled);

            recorder
            .BeginSegment
            (
                serviceName,
                traceHeader.RootTraceId,
                traceHeader.ParentId,
                samplingResponse
            );
        }
        public void TestLocalFallbackRules() // If rules are not loaded by default sampler, use local rules
        {
            var strategy = new DefaultSamplingStrategy($"JSONs{Path.DirectorySeparatorChar}SamplingRules1.json");

            var input            = new SamplingInput("name", "test", "get", "", "");
            var samplingResponse = strategy.ShouldTrace(input);

            Assert.AreEqual(SampleDecision.Sampled, samplingResponse.SampleDecision);
            Assert.IsTrue(string.IsNullOrEmpty(samplingResponse.RuleName));
        }
        public void TestGetMatchedRuleForExpiredCache1() // Cache not loaded, hould return null
        {
            RuleCache     ruleCache     = new RuleCache();
            SamplingInput samplingInput = new SamplingInput("elasticbeanstalk", "/api/1", "GET", "dynamo", "*");
            TimeStamp     current       = TimeStamp.CurrentTime();

            var actualRule = ruleCache.GetMatchedRule(samplingInput, current); // cache is expired since never loaded

            Assert.IsNull(actualRule);
        }
Exemple #5
0
        private static SamplingResponse MakeSamplingDecision(HttpRequest request, TraceHeader traceHeader, string name)
        {
            string           host           = request.Headers.Get("Host");
            string           url            = request.Url.AbsolutePath;
            string           method         = request.HttpMethod;
            SamplingInput    samplingInput  = new SamplingInput(host, url, method, name, _recorder.Origin);
            SamplingResponse sampleResponse = _recorder.SamplingStrategy.ShouldTrace(samplingInput);

            traceHeader.Sampled = sampleResponse.SampleDecision;
            return(sampleResponse);
        }
        public void TestGetMatchedRule3() // sampling input ServiceName and ServiceType is null - it should be ignored for rule matching
        {
            RuleCache           ruleCache     = new RuleCache();
            List <SamplingRule> newRules      = new List <SamplingRule>();
            SamplingInput       samplingInput = new SamplingInput("elasticbeanstalk", "/api/1", "GET", "", "");
            SamplingRule        expectedRule  = GetSamplingRule("a", 1, 0.5, 10, samplingInput.Host, "test", samplingInput.Method, samplingInput.Url, serviceType: "XYZ");

            newRules.Add(expectedRule);
            ruleCache.LoadRules(newRules);
            TimeStamp current = TimeStamp.CurrentTime();

            ruleCache.LastUpdated = current;

            var actualRule = ruleCache.GetMatchedRule(samplingInput, current);

            Assert.IsTrue(actualRule.Equals(expectedRule));
        }
        public void TestGetMatchedRule4() // sampling input has only ServiceName - the rule should be matched
        {
            RuleCache           ruleCache     = new RuleCache();
            List <SamplingRule> newRules      = new List <SamplingRule>();
            SamplingInput       samplingInput = new SamplingInput("elasticbeanstalk");
            SamplingRule        expectedRule  = GetSamplingRule("a", 1, 0.5, 10, serviceName: samplingInput.ServiceName);

            newRules.Add(expectedRule);
            ruleCache.LoadRules(newRules);
            TimeStamp current = TimeStamp.CurrentTime();

            ruleCache.LastUpdated = current;

            var actualRule = ruleCache.GetMatchedRule(samplingInput, current);

            Assert.IsTrue(actualRule.Equals(expectedRule));
        }
        public void TestGetMatchedRuleNotMatching() // Rule not matched
        {
            RuleCache           ruleCache     = new RuleCache();
            List <SamplingRule> newRules      = new List <SamplingRule>();
            SamplingInput       samplingInput = new SamplingInput("elasticbeanstalk", "/api/1", "GET", "dynamo", "*");
            SamplingRule        rule          = GetSamplingRule("a", 1, 0.5, 10, "j", samplingInput.ServiceName, samplingInput.Method, samplingInput.Url);

            newRules.Add(rule);
            ruleCache.LoadRules(newRules);
            TimeStamp current = TimeStamp.CurrentTime();

            ruleCache.LastUpdated = current;

            var actualRule = ruleCache.GetMatchedRule(samplingInput, current);

            Assert.IsNull(actualRule);
        }
        public void TestGetMatchedRuleNotMatching2() // SamplingInput with only ServiceName - Rule not matched
        {
            RuleCache           ruleCache     = new RuleCache();
            List <SamplingRule> newRules      = new List <SamplingRule>();
            SamplingInput       samplingInput = new SamplingInput("elasticbeanstalk");
            SamplingRule        rule          = GetSamplingRule("a", 1, 0.5, 10, serviceName: "XYZ");

            newRules.Add(rule);
            ruleCache.LoadRules(newRules);
            TimeStamp current = TimeStamp.CurrentTime();

            ruleCache.LastUpdated = current;

            var actualRule = ruleCache.GetMatchedRule(samplingInput, current);

            Assert.IsNull(actualRule);
        }
        public void TestGetMatchedRule2() // ServiceType is different
        {
            RuleCache           ruleCache     = new RuleCache();
            List <SamplingRule> newRules      = new List <SamplingRule>();
            SamplingInput       samplingInput = new SamplingInput("elasticbeanstalk", "/api/1", "GET", "dynamo", "AWS::ECS::Container");
            SamplingRule        expectedRule  = GetSamplingRule("a", 1, 0.5, 10, samplingInput.Host, samplingInput.ServiceName, samplingInput.Method, samplingInput.Url, serviceType: "XYZ");

            newRules.Add(expectedRule);
            ruleCache.LoadRules(newRules);
            TimeStamp current = TimeStamp.CurrentTime();

            ruleCache.LastUpdated = current;

            var actualRule = ruleCache.GetMatchedRule(samplingInput, current);

            Assert.IsNull(actualRule);
        }
        public void TestGetMatchedRuleForExpiredCache2() // Expired cache should not match rule.
        {
            RuleCache           ruleCache     = new RuleCache();
            List <SamplingRule> newRules      = new List <SamplingRule>();
            SamplingInput       samplingInput = new SamplingInput("elasticbeanstalk", "/api/1", "GET", "dynamo", "*");
            SamplingRule        expectedRule  = GetSamplingRule("a", 1, 0.5, 10, samplingInput.Host, samplingInput.ServiceName, samplingInput.Method, samplingInput.Url);

            newRules.Add(expectedRule);
            ruleCache.LoadRules(newRules);
            TimeStamp current = TimeStamp.CurrentTime();

            ruleCache.LastUpdated.Time = current.Time;
            current.Time += RuleCache.TTL + 1;

            var actualRule = ruleCache.GetMatchedRule(samplingInput, current); // cache is expired, though matching rule is present

            Assert.IsNull(actualRule);
        }
        public void TestDefaultRuleWithRequest()
        {
            var request = new HttpRequestMessage
            {
                RequestUri = new Uri(@"http://www.amazon.com/api/product"),
                Method     = HttpMethod.Post
            };

            request.Headers.Add("Host", "www.amazon.com");
            var              strategy         = new LocalizedSamplingStrategy();
            string           host             = request.Headers.Host;
            string           url              = request.RequestUri.AbsolutePath;
            string           method           = request.Method.Method;
            SamplingInput    samplingInput    = new SamplingInput(host, url, method, "", "");
            SamplingResponse samplingResponse = strategy.ShouldTrace(samplingInput);

            Assert.AreEqual(SampleDecision.Sampled, samplingResponse.SampleDecision);
            Assert.IsTrue(string.IsNullOrEmpty(samplingResponse.RuleName));
        }
        public void TestGetMatchedRuleWithDefaultRule2() // SamplingInput with only ServiceName - Matching with default Rule;
        {
            RuleCache           ruleCache     = new RuleCache();
            List <SamplingRule> newRules      = new List <SamplingRule>();
            SamplingInput       samplingInput = new SamplingInput("elasticbeanstalk");
            SamplingRule        rule          = GetSamplingRule("a", 1, 0.5, 10, serviceName: "XYZ");

            newRules.Add(rule);
            SamplingRule expectedRule = GetSamplingRule(SamplingRule.Default, 10000, 0.5, 1, "j", "*", "*", "*"); // should match to default rule

            newRules.Add(expectedRule);
            ruleCache.LoadRules(newRules);
            TimeStamp current = TimeStamp.CurrentTime();

            ruleCache.LastUpdated = current;

            var actualRule = ruleCache.GetMatchedRule(samplingInput, current);

            Assert.IsTrue(actualRule.Equals(expectedRule));
        }
        public void TestGetMatchedRuleWithDefaultRule() // Matching with default Rule;
        {
            RuleCache           ruleCache     = new RuleCache();
            List <SamplingRule> newRules      = new List <SamplingRule>();
            SamplingInput       samplingInput = new SamplingInput("elasticbeanstalk", "/api/1", "GET", "dynamo", "*");
            SamplingRule        rule          = GetSamplingRule("a", 1, 0.5, 10, "j", "test", samplingInput.Method, samplingInput.Url);

            newRules.Add(rule);
            SamplingRule expectedRule = GetSamplingRule(SamplingRule.Default, 10000, 0.5, 1, "j", "*", "*", "*"); // should match to default rule

            newRules.Add(expectedRule);
            ruleCache.LoadRules(newRules);
            TimeStamp current = TimeStamp.CurrentTime();

            ruleCache.LastUpdated = current;

            var actualRule = ruleCache.GetMatchedRule(samplingInput, current);

            Assert.IsTrue(actualRule.Equals(expectedRule));
        }
Exemple #15
0
        public void TestNotInitializeSamplingStrategy()
        {
            SamplingInput input = new SamplingInput("randomName", "testPath", "get", "test", "*");

            _recorder.SamplingStrategy.ShouldTrace(input);
        }
Exemple #16
0
 public SamplingResponse ShouldTrace(SamplingInput input)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        /// Perform sampling decison based on <see cref="SamplingInput"/>.
        /// </summary>
        /// <param name="input"> Instance of <see cref="SamplingInput"/>.</param>
        /// <returns>Instance of <see cref="SamplingResponse"/>.</returns>
        public SamplingResponse ShouldTrace(SamplingInput input)
        {
            SampleDecision sampleDecision = Sample(input.Host, input.Url, input.Method);

            return(new SamplingResponse(sampleDecision));
        }
Exemple #18
0
        /// <summary>
        /// Processes HTTP request.
        /// </summary>
        private void ProcessHTTPRequest(HttpContext context)
        {
            HttpRequest request      = context.Request;
            string      headerString = null;

            if (request.Headers.TryGetValue(TraceHeader.HeaderKey, out StringValues headerValue))
            {
                if (headerValue.ToArray().Length >= 1)
                {
                    headerString = headerValue.ToArray()[0];
                }
            }

            // Trace header doesn't exist, which means this is the root node. Create a new traceId and inject the trace header.
            if (!TraceHeader.TryParse(headerString, out TraceHeader traceHeader))
            {
                _logger.DebugFormat("Trace header doesn't exist or not valid : ({0}). Injecting a new one.", headerString);
                traceHeader = new TraceHeader
                {
                    RootTraceId = TraceId.NewId(),
                    ParentId    = null,
                    Sampled     = SampleDecision.Unknown
                };
            }

            var  segmentName = SegmentNamingStrategy.GetSegmentName(request);
            bool isSampleDecisionRequested = traceHeader.Sampled == SampleDecision.Requested;

            string ruleName = null;

            // Make sample decision
            if (traceHeader.Sampled == SampleDecision.Unknown || traceHeader.Sampled == SampleDecision.Requested)
            {
                string           host           = request.Host.Host;
                string           url            = request.Path;
                string           method         = request.Method;
                SamplingInput    samplingInput  = new SamplingInput(host, url, method, segmentName, _recorder.Origin);
                SamplingResponse sampleResponse = _recorder.SamplingStrategy.ShouldTrace(samplingInput);
                traceHeader.Sampled = sampleResponse.SampleDecision;
                ruleName            = sampleResponse.RuleName;
            }

            if (AWSXRayRecorder.IsLambda())
            {
                _recorder.BeginSubsegment(segmentName);
            }
            else
            {
                SamplingResponse samplingResponse = new SamplingResponse(ruleName, traceHeader.Sampled); // get final ruleName and SampleDecision
                _recorder.BeginSegment(SegmentNamingStrategy.GetSegmentName(request), traceHeader.RootTraceId, traceHeader.ParentId, samplingResponse);
            }

            if (!AWSXRayRecorder.Instance.IsTracingDisabled())
            {
                var requestAttributes = new Dictionary <string, object>();
                PopulateRequestAttributes(request, requestAttributes);
                _recorder.AddHttpInformation("request", requestAttributes);
            }

            if (isSampleDecisionRequested)
            {
                context.Response.Headers.Add(TraceHeader.HeaderKey, traceHeader.ToString()); // Its recommended not to modify response header after _next.Invoke() call
            }
        }
        /// <summary>
        /// Sends an HTTP request to the inner handler to send to the server as an asynchronous
        /// operation.
        /// </summary>
        /// <param name="request">The HTTP request message to send to the server.</param>
        /// <param name="cancellationToken">A cancellation token to cancel operation.</param>
        /// <returns>Returns System.Threading.Tasks.Task. The task object representing the asynchronous operation.</returns>
        protected async override Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            string headerSring = null;
            string ruleName    = null;

            if (request.Headers.TryGetValues(TraceHeader.HeaderKey, out IEnumerable <string> headerValue))
            {
                headerSring = headerValue.First();
            }

            // If Trace header doesn't exist, which means this is the root node. Create a new traceId and inject the trace header.
            if (!TraceHeader.TryParse(headerSring, out TraceHeader traceHeader))
            {
                _logger.DebugFormat("Trace header doesn't exist or not valid. Injecting a new one. existing header = {0}", headerSring);
                traceHeader = new TraceHeader
                {
                    RootTraceId = TraceId.NewId(),
                    ParentId    = null,
                    Sampled     = SampleDecision.Unknown
                };
            }

            bool isSampleDecisionRequested = traceHeader.Sampled == SampleDecision.Requested;

            string segmentName = SegmentNamingStrategy.GetSegmentName(request);

            // Make sample decision
            if (traceHeader.Sampled == SampleDecision.Unknown || traceHeader.Sampled == SampleDecision.Requested)
            {
                string           host          = request.Headers.Host;
                string           url           = request.RequestUri.AbsolutePath;
                string           method        = request.Method.Method;
                SamplingInput    samplingInput = new SamplingInput(host, url, method, segmentName, _recorder.Origin);
                SamplingResponse s             = _recorder.SamplingStrategy.ShouldTrace(samplingInput);
                traceHeader.Sampled = s.SampleDecision;
                ruleName            = s.RuleName;
            }

            SamplingResponse samplingResponse = new SamplingResponse(ruleName, traceHeader.Sampled); // get final ruleName and SampleDecision

            _recorder.BeginSegment(segmentName, traceHeader.RootTraceId, traceHeader.ParentId, samplingResponse);

            if (!AppSettings.IsXRayTracingDisabled)
            {
                var requestAttributes = new Dictionary <string, object>();
                requestAttributes["url"]    = request.RequestUri.AbsoluteUri;
                requestAttributes["method"] = request.Method.Method;
                string xForwardedFor = GetXForwardedFor(request);
                if (xForwardedFor == null)
                {
                    requestAttributes["client_ip"] = GetClientIpAddress(request);
                }
                else
                {
                    requestAttributes["client_ip"]       = xForwardedFor;
                    requestAttributes["x_forwarded_for"] = true;
                }

                requestAttributes["user_agent"] = request.Headers.UserAgent.ToString();
                _recorder.AddHttpInformation("request", requestAttributes);
            }

            var response = await base.SendAsync(request, cancellationToken);

            if (!AppSettings.IsXRayTracingDisabled)
            {
                var responseAttributes = new Dictionary <string, object>();
                int statusCode         = (int)response.StatusCode;
                if (statusCode >= 400 && statusCode <= 499)
                {
                    _recorder.MarkError();
                    if (statusCode == 429)
                    {
                        _recorder.MarkThrottle();
                    }
                }
                else if (statusCode >= 500 && statusCode <= 599)
                {
                    _recorder.MarkFault();
                }

                responseAttributes["status"] = statusCode;

                if (response.Content != null && response.Content.Headers.ContentLength != null)
                {
                    responseAttributes["content_length"] = response.Content.Headers.ContentLength;
                }

                _recorder.AddHttpInformation("response", responseAttributes);
            }

            _recorder.EndSegment();

            // If the sample decision is requested, added the trace header to response
            if (isSampleDecisionRequested)
            {
                response.Headers.Add(TraceHeader.HeaderKey, traceHeader.ToString());
            }

            return(response);
        }