示例#1
0
        public override RuleResult Run(IEnumerable <ServiceCallItem> items, ServiceCallStats stats)
        {
            bool richpresenceFound   = false;
            var  richPresenceJsonObj = new { activity = new Object() };

            foreach (var call in items)
            {
                var richPresenceResult = JsonConvert.DeserializeAnonymousType(call.m_reqBody, richPresenceJsonObj);
                if (richPresenceResult != null && richPresenceResult.activity != null)
                {
                    richpresenceFound = true;
                    break;
                }
            }

            RuleResult result = InitializeResult(DisplayName, "");

            if (!richpresenceFound)
            {
                result.Violations.Add(new Violation());
            }
            return(result);
        }
示例#2
0
        public override RuleResult Run(IEnumerable <ServiceCallItem> items, ServiceCallStats stats)
        {
            RuleResult result = InitializeResult(DisplayName, Description);

            //check invalid log versions
            if (items.Count(item => item.m_logVersion == Constants.Version1509) > 0)
            {
                result.AddViolation(ViolationLevel.Warning, "Data version does not support this rule. You need an updated Xbox Live SDK to support this rule");
                return(result);
            }

            StringBuilder description = new StringBuilder();

            // Traverse through each pattern set found in rule parameter
            foreach (var pattern in m_MatchPatterns)
            {
                Dictionary <ServiceCallItem, int> matchesFoundDict = new Dictionary <ServiceCallItem, int>();

                int patternInstancesFound = 0;
                int lowXUIDInstancesFound = 0;

                // This first section reports on violations which are from batch calls made with not enough XUIDs in the request body
                foreach (ServiceCallItem thisItem in items)
                {
                    Match match = Regex.Match(thisItem.m_uri, pattern.Key);
                    if (match.Success)
                    {
                        if (!thisItem.m_reqHeader.Contains("SocialManager"))
                        {
                            patternInstancesFound++;
                            try
                            {
                                JObject requestBodyJSON = JObject.Parse(thisItem.m_reqBody);
                                var     values          = requestBodyJSON.SelectToken(pattern.Value) as JArray;
                                if (values != null)
                                {
                                    matchesFoundDict.Add(thisItem, values.Count);
                                    if (values.Count < m_minBatchXUIDsPerBatchCall)
                                    {
                                        lowXUIDInstancesFound++;
                                        description.Clear();
                                        description.AppendFormat("Batch call detected for endpoint for a small sized set of {0} XUIDs.", values.Count);
                                        result.AddViolation(ViolationLevel.Warning, description.ToString(), thisItem);
                                    }
                                }
                            }
                            catch (Exception)
                            {
                                // ignored
                            }
                        }
                    }
                }  // finished traversing calls made to endpoint

                m_patternInstancesFound.Add(new Tuple <int, int>(patternInstancesFound, lowXUIDInstancesFound));
            } // end of foreach pattern in patterns

            var finalStats = PatternsFoundSumAsTuple();


            result.Results.Add("Total Batch Calls", finalStats.Item1);
            result.Results.Add("Min. Users Allowed", m_minBatchXUIDsPerBatchCall);
            result.Results.Add("Calls Below Count", finalStats.Item2);
            result.Results.Add("% Below Count", (double)(finalStats.Item2) / finalStats.Item1);

            return(result);
        }
示例#3
0
        override public RuleResult Run(IEnumerable <ServiceCallItem> items, ServiceCallStats stats)
        {
            RuleResult result = InitializeResult(DisplayName, Description);

            m_stats = stats;
            m_endpointSustainedViolations = 0;
            m_endpointBurstViolations     = 0;

            // For set of limits, look through items to determine where excess calls occurred
            foreach (var limits in m_rateLimits)
            {
                // Filter the full list of service calls to those which apply to this set of limits
                List <ServiceCallItem> applicableCalls = items.Where(serviceCall =>
                {
                    foreach (var subpath in limits.m_applicableSubpaths)
                    {
                        var subpathRegex = new Regex("^" + Regex.Escape(subpath).Replace("\\?", ".").Replace("\\*", ".*") + "$");
                        if (subpathRegex.IsMatch(new Uri(serviceCall.m_uri).AbsolutePath))
                        {
                            return(true);
                        }
                    }
                    return(false);
                }).ToList();

                var sustainedExcessCallsPerWindow = Utils.GetExcessCallsForTimeWindow(applicableCalls, limits.m_sustainedTimePeriodSeconds * 1000, limits.m_sustainedCallLimit);
                var burstExcessCallsPerWindow     = Utils.GetExcessCallsForTimeWindow(applicableCalls, limits.m_burstTimePeriodSeconds * 1000, limits.m_burstCallLimit);

                foreach (var excessCalls in sustainedExcessCallsPerWindow)
                {
                    if (excessCalls.Count >= limits.m_sustainedCallLimit * 10)
                    {
                        var desc = $"Exceeding rate limits for '{limits.m_description}' required for title certification( limit of {limits.m_sustainedCallLimit * 10} calls with {excessCalls.Count} calls in {limits.m_sustainedTimePeriodSeconds} seconds).  Failure to adhere to the specified limits may block a title from release, and in-production issues with released titles may result in service suspension up to and including title removal.";
                        result.AddViolation(ViolationLevel.Error, desc, excessCalls);
                    }
                    else
                    {
                        var desc = $"Call frequency above the sustained call limit for '{limits.m_description}' (limit of {limits.m_sustainedCallLimit} exceeded with {excessCalls.Count} calls in {limits.m_sustainedTimePeriodSeconds} seconds).";
                        result.AddViolation(ViolationLevel.Warning, desc, excessCalls);
                    }
                    m_endpointSustainedViolations++;
                }

                foreach (var excessCalls in burstExcessCallsPerWindow)
                {
                    var desc = $"Call frequency above the burst call limit for '{limits.m_description}' (limit of {limits.m_burstCallLimit} exceeded with {excessCalls.Count} calls in {limits.m_burstTimePeriodSeconds} seconds).";
                    result.AddViolation(ViolationLevel.Warning, desc, excessCalls);
                    m_endpointBurstViolations++;
                }

                // The following is information that would only be useful for internal purposes.
                if (RulesEngine.m_isInternal)
                {
                    UInt64 avgTimeBetweenReqsMs = stats.m_avgTimeBetweenReqsMs;
                    UInt64 avgElapsedCallTimeMs = stats.m_avgElapsedCallTimeMs;
                    UInt64 maxElapsedCallTimeMs = stats.m_maxElapsedCallTimeMs;


                    if (avgTimeBetweenReqsMs > 0 && avgTimeBetweenReqsMs < limits.m_avgTimeBetweenReqsMs)
                    {
                        result.AddViolation(ViolationLevel.Warning, "Average time of " + avgTimeBetweenReqsMs + "ms between calls is too short");
                    }

                    if (avgElapsedCallTimeMs > 0 && avgElapsedCallTimeMs > limits.m_avgElapsedCallTimeMs)
                    {
                        result.AddViolation(ViolationLevel.Warning, "Calls are taking longer than expected to return " + avgElapsedCallTimeMs + "ms");
                    }

                    if (maxElapsedCallTimeMs > 0 && maxElapsedCallTimeMs > limits.m_maxElapsedCallTimeMs)
                    {
                        result.AddViolation(ViolationLevel.Warning, "The maximum call time for calls is greater than allowed " + maxElapsedCallTimeMs + "ms");
                    }
                }
            }

            result.Results.Add("Total Calls", m_stats == null ? 0 : m_stats.m_numCalls);
            result.Results.Add("Times Sustained Exceeded", m_endpointSustainedViolations);
            result.Results.Add("Times Burst Exceeded", m_endpointBurstViolations);

            return(result);
        }
        public JObject ReportRule(RuleResult rule)
        {
            JObject jsonRule = new JObject();

            if (rule == null)
            {
                return(null);
            }

            if (!s_supportedRules.Contains(rule.RuleName))
            {
                return(null);
            }

            JObject jsonResult = new JObject();

            jsonRule["Name"]        = rule.RuleName;
            jsonRule["Description"] = rule.RuleDescription;

            foreach (var data in rule.Results)
            {
                jsonResult[data.Key] = data.Value.ToString();
            }

            jsonRule["ResultData"] = jsonResult;

            foreach (ViolationLevel level in System.Enum.GetValues(typeof(ViolationLevel)))
            {
                jsonRule[System.Enum.GetName(typeof(ViolationLevel), level)] = rule.Violations.Count(v => v.m_level == level);
            }

            if (jsonRule[System.Enum.GetName(typeof(ViolationLevel), ViolationLevel.Error)].ToObject <Int32>() > 0)
            {
                jsonRule["Result"] = System.Enum.GetName(typeof(ViolationLevel), ViolationLevel.Error);
            }
            else if (jsonRule[System.Enum.GetName(typeof(ViolationLevel), ViolationLevel.Warning)].ToObject <Int32>() > 0)
            {
                jsonRule["Result"] = System.Enum.GetName(typeof(ViolationLevel), ViolationLevel.Warning);
            }
            else
            {
                jsonRule["Result"] = "Pass";
            }

            JArray jsonViolations = new JArray();

            foreach (var violation in rule.Violations)
            {
                JObject jsonViolation = new JObject();

                jsonViolation["Level"]   = System.Enum.GetName(typeof(ViolationLevel), violation.m_level);
                jsonViolation["Summary"] = violation.m_summary;

                JArray calls = new JArray();

                foreach (var call in violation.m_violatingCalls)
                {
                    JObject jsonCall = new JObject();

                    jsonCall["Call Id"]   = call.m_id;
                    jsonCall["UriMethod"] = call.m_uri;
                    if (call.m_xsapiMethods != null)
                    {
                        jsonCall["CppMethod"]   = call.m_xsapiMethods.Item1;
                        jsonCall["WinRTMethod"] = call.m_xsapiMethods.Item2;
                    }

                    calls.Add(jsonCall);
                }

                jsonViolation["Calls"] = calls;

                jsonViolations.Add(jsonViolation);
            }

            jsonRule["Violations"] = jsonViolations;

            return(jsonRule);
        }
示例#5
0
        public override RuleResult Run(IEnumerable <ServiceCallItem> items, ServiceCallStats stats)
        {
            RuleResult result = InitializeResult(DisplayName, Description);

            if (items.Count() == 0)
            {
                return(result);
            }

            //check invalid log versions
            if (items.Count(item => item.m_logVersion == Constants.Version1509) > 0)
            {
                result.AddViolation(ViolationLevel.Warning, "Data version does not support this rule. You need an updated Xbox Live SDK to support this rule");
                return(result);
            }

            List <ServiceCallItem> allRepeats = new List <ServiceCallItem>();
            var nonShoulderTapItems           = items.Where(item => item.m_isShoulderTap == false);

            List <Sequence> sequences = new List <Sequence>();

            foreach (ServiceCallItem thisItem in nonShoulderTapItems)
            {
                if (thisItem.m_reqHeader.Contains("SocialManager"))
                {
                    continue;
                }

                // Used to skip over already analyzed repeated calls.
                if (allRepeats.Contains(thisItem))
                {
                    continue;
                }

                // Discover all repeats to thisItem
                var myRepeats = from item in nonShoulderTapItems
                                where ((item != thisItem) && (item.m_reqBodyHash == thisItem.m_reqBodyHash) && (item.m_uri == thisItem.m_uri))
                                select item;

                if (myRepeats.Count() > 1)
                {
                    var deltas = BuildDeltas(myRepeats.ToList());
                    sequences.AddRange(GenerateSequences(deltas, m_sameDeltaThresholdPercentage));

                    allRepeats.AddRange(myRepeats);
                }
            }

            if (sequences == null)
            {
                return(result);
            }

            //Process Violations
            StringBuilder description = new StringBuilder();

            foreach (var sequence in sequences.OrderByDescending(s => s.Length))
            {
                description.Clear();

                description.AppendFormat("Polling detected in a sequence of {0} calls at a rate of approximately {1} min:sec",
                                         sequence.Length, TimeSpan.FromTicks((long)sequence.m_averageDelta).ToString(@"mm\:ss\.fff"));

                result.AddViolation(ViolationLevel.Warning, description.ToString(), sequence.m_seqCalls);
            }


            result.Results.Add("Polling Sequences Found", result.ViolationCount);

            return(result);
        }
        // Creates a RuleResult with a cleaner display veersion of the Rule's name, Endpoint and a custom description.
        protected RuleResult InitializeResult(String displayName, String description)
        {
            RuleResult result = new RuleResult(displayName, Endpoint, description);

            return(result);
        }
        public override RuleResult Run(IEnumerable <ServiceCallItem> items, ServiceCallStats stats)
        {
            RuleResult result = InitializeResult(DisplayName, Description);

            m_totalCalls          = items.Count();
            m_throttledCallsCount = items.Where(call => call.m_httpStatusCode == 429).Count();

            // We need to search over all of the calls to the endpoint
            for (int i = 0; i < m_totalCalls;)
            {
                var call = items.ElementAt(i);

                // If its not a throttled call, move to the next call
                if (call.m_httpStatusCode != 429)
                {
                    ++i;
                    continue;
                }

                // If it is throttled, start a list
                List <ServiceCallItem> throttledCallSet = new List <ServiceCallItem>();
                throttledCallSet.Add(items.ElementAt(i));
                var    throttledCall    = throttledCallSet.First();
                string throttleGuidline = string.Empty;

                try
                {
                    if (!string.IsNullOrEmpty(throttledCall.m_rspBody))
                    {
                        JObject response = JObject.Parse(throttledCall.m_rspBody);
                        if (response["maxRequests"] != null && response["periodInSeconds"] != null)
                        {
                            throttleGuidline = $"Allowed: {response["maxRequests"]} over {response["periodInSeconds"]} seconds.";
                        }
                    }
                }
                catch (Exception)
                {
                }


                // If there are 2 or more throttled calls in a row the title is not properly handling the response
                while (++i < m_throttledCallsCount)
                {
                    var nextCall = items.ElementAt(i);

                    if (call.m_httpStatusCode != 429)
                    {
                        ++i;
                        break;
                    }
                    else
                    {
                        throttledCallSet.Add(call);
                    }
                }

                // One call is a warning as we expect that they back off after getting the 429 response
                if (throttledCallSet.Count == 1)
                {
                    result.AddViolation(ViolationLevel.Warning, "Throttled call detected on endpoint. " + throttleGuidline, throttledCall);
                }
                // More that one in a row means that the title didn't handle the 429 and we want them to fix that.
                else
                {
                    result.AddViolation(ViolationLevel.Error, "Sequence of throttled calls detected on endpoint. " + throttleGuidline, throttledCallSet);
                }

                throttledCallSet.Clear();
            }


            result.Results.Add("Total Calls", TotalCalls);
            result.Results.Add("Throttled Calls", ThrottledCallCount);
            result.Results.Add("Percentage", ((double)ThrottledCallCount) / TotalCalls);

            return(result);
        }
示例#8
0
        override public RuleResult Run(IEnumerable <ServiceCallItem> items, ServiceCallStats stats)
        {
            RuleResult result = InitializeResult(DisplayName, Description);

            if (items.Count() == 0)
            {
                return(result);
            }

            //check invalid log versions
            if (items.Count(item => item.m_logVersion == Constants.Version1509) > 0)
            {
                result.AddViolation(ViolationLevel.Warning, "Data version does not support this rule. You need an updated Xbox Live SDK to support this rule");
                return(result);
            }

            StringBuilder description = new StringBuilder();

            List <ServiceCallItem> repeats = new List <ServiceCallItem>();

            m_totalCallsChecked = items.Count();

            foreach (ServiceCallItem thisItem in items.Where(item => item.m_isShoulderTap == false))
            {
                if (thisItem.m_reqHeader.Contains("SocialManager"))
                {
                    continue;
                }

                if (repeats.Contains(thisItem))
                {
                    continue;
                }

                var timeWindow = from item in items.Where(item => item.m_isShoulderTap == false)
                                 where (item.m_reqTimeUTC > thisItem.m_reqTimeUTC && ((item.m_reqTimeUTC - thisItem.m_reqTimeUTC) / TimeSpan.TicksPerMillisecond) < m_minAllowedRepeatIntervalMs)
                                 select item;

                List <ServiceCallItem> repeatedCalls = new List <ServiceCallItem>();

                repeatedCalls.Add(thisItem);

                foreach (var call in timeWindow)
                {
                    if (thisItem.m_reqBodyHash == call.m_reqBodyHash && thisItem.m_uri == call.m_uri)
                    {
                        repeatedCalls.Add(call);
                    }
                }

                if (repeatedCalls.Count > 1)
                {
                    description.Clear();
                    description.AppendFormat("Repeated call found {0} other times in calls to endpoint.", repeatedCalls.Count, thisItem.m_id);

                    result.AddViolation(ViolationLevel.Warning, description.ToString(), repeatedCalls);

                    repeats.AddRange(repeatedCalls);
                }
            }

            m_numberOfRepeats = repeats.Count;


            result.Results.Add("Total Calls", m_totalCallsChecked);
            result.Results.Add("Duplicates", m_numberOfRepeats);
            result.Results.Add("Percentage", ((double)m_numberOfRepeats) / m_totalCallsChecked);

            return(result);
        }
示例#9
0
        public override RuleResult Run(IEnumerable <ServiceCallItem> items, ServiceCallStats stats)
        {
            RuleResult result = InitializeResult(DisplayName, Description);

            //check invalid log versions
            if (items.Count(item => item.m_logVersion == Constants.Version1509) > 0)
            {
                result.AddViolation(ViolationLevel.Warning, "Data version does not support this rule. You need an updated Xbox Live SDK to support this rule");
                return(result);
            }

            StringBuilder description = new StringBuilder();

            // Traverse through each pattern set found in rule parameter
            foreach (var pattern in m_MatchPatterns)
            {
                Dictionary <ServiceCallItem, int> matchesFoundDict = new Dictionary <ServiceCallItem, int>();

                foreach (ServiceCallItem thisItem in items)
                {
                    Match match = Regex.Match(thisItem.m_uri, pattern.Key);
                    if (match.Success)
                    {
                        JObject requestBodyJSON = JObject.Parse(thisItem.m_reqBody);
                        var     values          = requestBodyJSON.SelectToken(pattern.Value) as JArray;
                        if (values != null)
                        {
                            matchesFoundDict.Add(thisItem, values.Count);
                        }
                    }
                }  // finished traversing calls made to endpoint

                m_totalBatchCallCount = (UInt32)matchesFoundDict.Count;

                // For all the matches found, report on batch sets which happened within a specific time window
                int numDictItems = matchesFoundDict.Count;
                if (numDictItems >= 2)
                {
                    int startWindowIdx = 0;
                    List <ServiceCallItem> callsWithinWindow = new List <ServiceCallItem>();
                    int totalXUIDsForWindow = 0;
                    totalXUIDsForWindow += matchesFoundDict.Values.ElementAt(startWindowIdx);
                    callsWithinWindow.Add(matchesFoundDict.Keys.ElementAt(startWindowIdx));
                    for (int endWindowIdx = 1; endWindowIdx < matchesFoundDict.Count(); ++endWindowIdx)
                    {
                        UInt64 timeElapsed = (UInt64)Math.Abs((float)
                                                              (matchesFoundDict.Keys.ElementAt(endWindowIdx).m_reqTimeUTC - matchesFoundDict.Keys.ElementAt(startWindowIdx).m_reqTimeUTC) / TimeSpan.TicksPerMillisecond);
                        if (timeElapsed <= m_BatchSetDetectionWindowsMs)
                        {
                            callsWithinWindow.Add(matchesFoundDict.Keys.ElementAt(endWindowIdx));
                            totalXUIDsForWindow += matchesFoundDict.Values.ElementAt(endWindowIdx);
                        }
                        else //exceeded window
                        {
                            if (callsWithinWindow.Count >= 2)
                            {
                                result.AddViolation(ViolationLevel.Warning, $"A set of {callsWithinWindow.Count} Batch Calls was found within a time window of ({m_BatchSetDetectionWindowsMs}ms) to endpoint. Total XUID count ({totalXUIDsForWindow}). Consider combining into one call.", callsWithinWindow);
                            }

                            startWindowIdx = endWindowIdx; // shift window
                            //reset figures
                            totalXUIDsForWindow = 0;
                            callsWithinWindow.Clear();
                        }
                    }
                    // in case we exited the last for early because we never exceeded the time window, then call
                    // the following function once more to handle any dangling reports.
                    if (callsWithinWindow.Count >= 2)
                    {
                        result.AddViolation(ViolationLevel.Warning, $"A set of {callsWithinWindow.Count} Batch Calls was found within a time window of ({m_BatchSetDetectionWindowsMs}ms) to endpoint. Total XUID count ({totalXUIDsForWindow}). Consider combining into one call.", callsWithinWindow);
                    }
                }
            } // end of foreach pattern in patterns


            result.Results.Add("Total Batch Calls", m_totalBatchCallCount);
            result.Results.Add("Allowed Time Between Calls in ms", m_BatchSetDetectionWindowsMs);
            result.Results.Add("Times Exceeded", result.ViolationCount);
            result.Results.Add("Potential Reduced Call Count", m_totalBatchCallCount - result.ViolationCount);

            return(result);
        }
示例#10
0
        override public RuleResult Run(IEnumerable <ServiceCallItem> items, ServiceCallStats stats)
        {
            RuleResult result = InitializeResult(DisplayName, Description);

            m_stats = stats;
            m_endpointSustainedViolations = 0;
            m_endpointBurstViolations     = 0;

            // Look through items to determine where excess calls occurred
            var sustainedExcessCallsPerWindow = Utils.GetExcessCallsForTimeWindow(items, m_sustainedTimePeriodSeconds * 1000, m_sustainedCallLimit);
            var burstExcessCallsPerWindow     = Utils.GetExcessCallsForTimeWindow(items, m_burstTimePeriodSeconds * 1000, m_burstCallLimit);

            foreach (var excessCalls in sustainedExcessCallsPerWindow)
            {
                if (excessCalls.Count >= m_sustainedCallLimit * 10)
                {
                    var desc = $"Exceeding service rate limits required for title certification( limit of {m_sustainedCallLimit * 10} calls with {excessCalls.Count} calls in {m_sustainedTimePeriodSeconds} seconds).  Failure to adhere to the specified limits may block a title from release, and in-production issues with released titles may result in service suspension up to and including title removal.";
                    result.AddViolation(ViolationLevel.Error, desc, excessCalls);
                }
                else
                {
                    var desc = $"Call frequency above the sustained call limit of {m_sustainedCallLimit} with {excessCalls.Count} calls in {m_sustainedTimePeriodSeconds} seconds to endpoint.";
                    result.AddViolation(ViolationLevel.Warning, desc, excessCalls);
                }
                m_endpointSustainedViolations++;
            }

            foreach (var excessCalls in burstExcessCallsPerWindow)
            {
                var desc = $"Call frequency above the burst call limit of {m_burstCallLimit} with {excessCalls.Count} calls {m_burstTimePeriodSeconds} seconds to endpoint.";
                result.AddViolation(ViolationLevel.Warning, desc, excessCalls);
                m_endpointBurstViolations++;
            }

            // The following is information that would only be useful for internal purposes.
            if (RulesEngine.m_isInternal)
            {
                UInt64 avgTimeBetweenReqsMs = stats.m_avgTimeBetweenReqsMs;
                UInt64 avgElapsedCallTimeMs = stats.m_avgElapsedCallTimeMs;
                UInt64 maxElapsedCallTimeMs = stats.m_maxElapsedCallTimeMs;


                if (avgTimeBetweenReqsMs > 0 && avgTimeBetweenReqsMs < m_avgTimeBetweenReqsMs)
                {
                    result.AddViolation(ViolationLevel.Warning, "Average time of " + avgTimeBetweenReqsMs + "ms between calls is too short");
                }

                if (avgElapsedCallTimeMs > 0 && avgElapsedCallTimeMs > m_avgElapsedCallTimeMs)
                {
                    result.AddViolation(ViolationLevel.Warning, "Calls are taking longer than expected to return " + avgElapsedCallTimeMs + "ms");
                }

                if (maxElapsedCallTimeMs > 0 && maxElapsedCallTimeMs > m_maxElapsedCallTimeMs)
                {
                    result.AddViolation(ViolationLevel.Warning, "The maximum call time for calls is greater than allowed " + maxElapsedCallTimeMs + "ms");
                }
            }


            result.Results.Add("Total Calls", m_stats == null ? 0 : m_stats.m_numCalls);
            result.Results.Add("Sustained Call Period", m_sustainedTimePeriodSeconds.ToString() + "sec.");
            result.Results.Add("Sustained Call Limit", m_sustainedCallLimit);
            result.Results.Add("Times Sustained Exceeded", m_endpointSustainedViolations);
            result.Results.Add("Burst Call Period", m_burstTimePeriodSeconds.ToString() + "sec.");
            result.Results.Add("Burst Call Limit", m_burstCallLimit);
            result.Results.Add("Times Burst Exceeded", m_endpointBurstViolations);

            return(result);
        }
示例#11
0
        override public RuleResult Run(IEnumerable <ServiceCallItem> items, ServiceCallStats stats)
        {
            RuleResult result = InitializeResult(DisplayName, Description);

            StringBuilder description = new StringBuilder();

            m_stats = stats;
            m_endpointSustainedViolations = 0;
            m_endpointBurstViolations     = 0;

            // Look through items to determine where excess calls occurred
            var sustainedExcessCallsPerWindow = Utils.GetExcessCallsForTimeWindow(items, m_sustainedTimePeriodSeconds * 1000, (UInt32)(m_sustainedCallLimit * .9));
            var burstExcessCallsPerWindow     = Utils.GetExcessCallsForTimeWindow(items, m_burstTimePeriodSeconds * 1000, (UInt32)(m_burstCallLimit * .9));

            foreach (var excessCalls in sustainedExcessCallsPerWindow)
            {
                description.Clear();
                if (excessCalls.Count < m_sustainedCallLimit)
                {
                    description.AppendFormat("Call frequency nearing the sustained call limit of {0} with {1} calls to endpoint.", m_sustainedCallLimit, excessCalls.Count);
                    result.AddViolation(ViolationLevel.Warning, description.ToString(), excessCalls);
                }
                else
                {
                    m_endpointSustainedViolations++;
                    description.AppendFormat("Call frequency above the sustained call limit of {0} with {1} calls to endpoint.", m_sustainedCallLimit, excessCalls.Count);
                    result.AddViolation(ViolationLevel.Error, description.ToString(), excessCalls);
                }
            }

            foreach (var excessCalls in burstExcessCallsPerWindow)
            {
                description.Clear();
                if (excessCalls.Count < m_burstCallLimit)
                {
                    description.AppendFormat("Call frequency nearing the burst call limit of {0} with {1} calls to endpoint.", m_burstCallLimit, excessCalls.Count);
                    result.AddViolation(ViolationLevel.Warning, description.ToString(), excessCalls);
                }
                else
                {
                    m_endpointBurstViolations++;
                    description.AppendFormat("Call frequency above the burst call limit of {0} with {1} calls to endpoint.", m_burstCallLimit, excessCalls.Count);
                    result.AddViolation(ViolationLevel.Error, description.ToString(), excessCalls);
                }
            }

            // The following is information that would only be useful for internal purposes.
            if (RulesEngine.m_isInternal)
            {
                UInt64 avgTimeBetweenReqsMs = stats.m_avgTimeBetweenReqsMs;
                UInt64 avgElapsedCallTimeMs = stats.m_avgElapsedCallTimeMs;
                UInt64 maxElapsedCallTimeMs = stats.m_maxElapsedCallTimeMs;


                if (avgTimeBetweenReqsMs > 0 && avgTimeBetweenReqsMs < m_avgTimeBetweenReqsMs)
                {
                    result.AddViolation(ViolationLevel.Warning, "Average time of " + avgTimeBetweenReqsMs + "ms between calls is too short");
                }

                if (avgElapsedCallTimeMs > 0 && avgElapsedCallTimeMs > m_avgElapsedCallTimeMs)
                {
                    result.AddViolation(ViolationLevel.Warning, "Calls are taking longer than expected to return " + avgElapsedCallTimeMs + "ms");
                }

                if (maxElapsedCallTimeMs > 0 && maxElapsedCallTimeMs > m_maxElapsedCallTimeMs)
                {
                    result.AddViolation(ViolationLevel.Warning, "The maximum call time for calls is greater than allowed " + maxElapsedCallTimeMs + "ms");
                }
            }


            result.Results.Add("Total Calls", m_stats == null ? 0 : m_stats.m_numCalls);
            result.Results.Add("Sustained Call Period", m_sustainedTimePeriodSeconds.ToString() + "sec.");
            result.Results.Add("Sustained Call Limit", m_sustainedCallLimit);
            result.Results.Add("Times Sustained Exceeded", m_endpointSustainedViolations);
            result.Results.Add("Burst Call Period", m_burstTimePeriodSeconds.ToString() + "sec.");
            result.Results.Add("Burst Call Limit", m_burstCallLimit);
            result.Results.Add("Times Burst Exceeded", m_endpointBurstViolations);

            return(result);
        }