[CalendarServer-changes] [7750] CalendarServer/trunk/contrib/performance/loadtest

source_changes at macosforge.org source_changes at macosforge.org
Fri Jul 8 14:04:13 PDT 2011


Revision: 7750
          http://trac.macosforge.org/projects/calendarserver/changeset/7750
Author:   exarkun at twistedmatrix.com
Date:     2011-07-08 14:04:12 -0700 (Fri, 08 Jul 2011)
Log Message:
-----------
Check per-request statistics and report failure if any thresholds are exceeded.

Modified Paths:
--------------
    CalendarServer/trunk/contrib/performance/loadtest/population.py
    CalendarServer/trunk/contrib/performance/loadtest/test_population.py
    CalendarServer/trunk/contrib/performance/loadtest/test_sim.py

Modified: CalendarServer/trunk/contrib/performance/loadtest/population.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/population.py	2011-07-08 20:20:17 UTC (rev 7749)
+++ CalendarServer/trunk/contrib/performance/loadtest/population.py	2011-07-08 21:04:12 UTC (rev 7750)
@@ -20,6 +20,8 @@
 certain usage parameters.
 """
 
+from __future__ import division
+
 from tempfile import mkdtemp
 from itertools import izip
 
@@ -314,11 +316,48 @@
             [fmt for (label, width, fmt) in self._fields],
             sorted(self._perMethodTimes.items()))
 
+    _FAILED_REASON = "Greater than %(cutoff)0.f%% %(method)s failed"
+    _THREESEC_REASON = "Greater than %(cutoff)0.f%% %(method)s exceeded 3 second response time"
+    _FIVESEC_REASON = "Greater than %(cutoff)0.f%% %(method)s exceeded 5 second response time"
+
+    def failures(self):
         # TODO
-        # Check for >1% request failure rate
-        #           >1% >5sec response rate
-        #           >5% >3sec response rate
-        # 
+        reasons = []
+
+        # Upper limit on ratio of failed requests to total requests
+        failCutoff = 0.01
+
+        # Upper limit on ratio of >3sec requests to total requests
+        threeSecCutoff = 0.05
+
+        # Upper limit on ratio of >5sec requests to total requests
+        fiveSecCutoff = 0.01
+
+        failures = 0
+        threeSec = 0
+        fiveSec = 0
+
+        for (method, times) in self._perMethodTimes.iteritems():
+            for success, duration in times:
+                if not success:
+                    failures += 1
+                if duration > 5:
+                    fiveSec += 1
+                elif duration > 3:
+                    threeSec += 1
+
+            checks = [
+                (failures, failCutoff, self._FAILED_REASON),
+                (threeSec, threeSecCutoff, self._THREESEC_REASON),
+                (fiveSec, fiveSecCutoff, self._FIVESEC_REASON),
+                ]
+
+            for count, cutoff, reason in checks:
+                if count / len(times) > cutoff:
+                    reasons.append(reason % dict(
+                            method=method, cutoff=cutoff * 100))
+
+        return reasons
         
 
 

Modified: CalendarServer/trunk/contrib/performance/loadtest/test_population.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/test_population.py	2011-07-08 20:20:17 UTC (rev 7749)
+++ CalendarServer/trunk/contrib/performance/loadtest/test_population.py	2011-07-08 21:04:12 UTC (rev 7750)
@@ -39,3 +39,73 @@
                     type='response', method='GET', success=True,
                     duration=1.23, user=user))
         self.assertEqual(len(users), logger.countUsers())
+
+
+    def test_noFailures(self):
+        """
+        If fewer than 1% of requests fail, fewer than 1% of requests take 5
+        seconds or more, and fewer than 5% of requests take 3 seconds or more,
+        L{ReportStatistics.failures} returns an empty list.
+        """
+        logger = ReportStatistics()
+        logger.observe(dict(
+                type='response', method='GET', success=True,
+                duration=2.5, user='user01'))
+        self.assertEqual([], logger.failures())
+
+
+    def test_requestFailures(self):
+        """
+        If more than 1% of requests fail, L{ReportStatistics.failures} returns a
+        list containing a string describing this.
+        """
+        logger = ReportStatistics()
+        for i in range(98):
+            logger.observe(dict(
+                    type='response', method='GET', success=True,
+                    duration=2.5, user='user01'))
+        logger.observe(dict(
+                type='response', method='GET', success=False,
+                duration=2.5, user='user01'))
+        self.assertEqual(
+            ["Greater than 1% GET failed"],
+            logger.failures())
+
+
+    def test_threeSecondFailure(self):
+        """
+        If more than 5% of requests take longer than 3 seconds,
+        L{ReportStatistics.failures} returns a list containing a string
+        describing that.
+        """
+        logger = ReportStatistics()
+        for i in range(94):
+            logger.observe(dict(
+                    type='response', method='GET', success=True,
+                    duration=2.5, user='user01'))
+        for i in range(5):
+            logger.observe(dict(
+                    type='response', method='GET', success=True,
+                    duration=3.5, user='user02'))
+        self.assertEqual(
+            ["Greater than 5% GET exceeded 3 second response time"],
+            logger.failures())
+
+
+    def test_fiveSecondFailure(self):
+        """
+        If more than 1% of requests take longer than 5 seconds,
+        L{ReportStatistics.failures} returns a list containing a string
+        describing that.
+        """
+        logger = ReportStatistics()
+        for i in range(98):
+            logger.observe(dict(
+                    type='response', method='GET', success=True,
+                    duration=2.5, user='user01'))
+        logger.observe(dict(
+                type='response', method='GET', success=True,
+                duration=5.5, user='user01'))
+        self.assertEqual(
+            ["Greater than 1% GET exceeded 5 second response time"],
+            logger.failures())

Modified: CalendarServer/trunk/contrib/performance/loadtest/test_sim.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/test_sim.py	2011-07-08 20:20:17 UTC (rev 7749)
+++ CalendarServer/trunk/contrib/performance/loadtest/test_sim.py	2011-07-08 21:04:12 UTC (rev 7750)
@@ -162,7 +162,10 @@
         self.reported = True
 
 
+    def failures(self):
+        return []
 
+
 class NullArrival(object):
     def run(self, sim):
         pass
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110708/47f2812f/attachment.html>


More information about the calendarserver-changes mailing list