in Source/Rules/ThrottledCallsRule.cs [39:116]
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.Warning, "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;
}