[CalendarServer-changes] [10159] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Dec 12 09:18:55 PST 2012


Revision: 10159
          http://trac.calendarserver.org//changeset/10159
Author:   cdaboo at apple.com
Date:     2012-12-12 09:18:55 -0800 (Wed, 12 Dec 2012)
Log Message:
-----------
More stats socket enhancements.

Modified Paths:
--------------
    CalendarServer/trunk/calendarserver/accesslog.py
    CalendarServer/trunk/contrib/tools/readStats.py

Added Paths:
-----------
    CalendarServer/trunk/calendarserver/logAnalysis.py

Removed Paths:
-------------
    CalendarServer/trunk/calendarserver/methodDescriptor.py

Modified: CalendarServer/trunk/calendarserver/accesslog.py
===================================================================
--- CalendarServer/trunk/calendarserver/accesslog.py	2012-12-12 16:37:28 UTC (rev 10158)
+++ CalendarServer/trunk/calendarserver/accesslog.py	2012-12-12 17:18:55 UTC (rev 10159)
@@ -35,7 +35,8 @@
     psutil = None
 import time
 
-from calendarserver.methodDescriptor import getAdjustedMethodName
+from calendarserver.logAnalysis import getAdjustedMethodName, \
+    getAdjustedClientName
 
 from twext.python.log import Logger
 from twext.web2 import iweb
@@ -468,27 +469,34 @@
             }
 
         return {
-            "requests" : 0,
-            "method"   : collections.defaultdict(int),
-            "uid"      : collections.defaultdict(int),
-            "500"      : 0,
-            "t"        : 0.0,
-            "t-resp-wr": 0.0,
-            "slots"    : 0,
-            "T"        : initTimeHistogram(),
-            "T-RESP-WR": initTimeHistogram(),
-            "T-MAX"    : 0.0,
-            "cpu"      : self.systemStats.items["cpu use"],
+            "requests"   : 0,
+            "method"     : collections.defaultdict(int),
+            "method-t"   : collections.defaultdict(float),
+            "uid"        : collections.defaultdict(int),
+            "user-agent" : collections.defaultdict(int),
+            "500"        : 0,
+            "t"          : 0.0,
+            "t-resp-wr"  : 0.0,
+            "slots"      : 0,
+            "T"          : initTimeHistogram(),
+            "T-RESP-WR"  : initTimeHistogram(),
+            "T-MAX"      : 0.0,
+            "cpu"        : self.systemStats.items["cpu use"],
         }
 
 
     def updateStats(self, current, stats):
         # Gather specific information and aggregate into our persistent stats
+        adjustedMethod = getAdjustedMethodName(stats)
+        adjustedClient = getAdjustedClientName(stats)
+
         if current["requests"] == 0:
             current["cpu"] = 0.0
         current["requests"] += 1
-        current["method"][getAdjustedMethodName(stats["method"], stats["uri"], stats)] += 1
+        current["method"][adjustedMethod] += 1
+        current["method-t"][adjustedMethod] += stats.get("t", 0.0)
         current["uid"][stats["uid"]] += 1
+        current["user-agent"][adjustedClient] += 1
         if stats["statusCode"] >= 500:
             current["500"] += 1
         current["t"] += stats.get("t", 0.0)
@@ -532,8 +540,12 @@
         current["requests"] += stats["requests"]
         for method in stats["method"].keys():
             current["method"][method] += stats["method"][method]
+        for method in stats["method-t"].keys():
+            current["method-t"][method] += stats["method-t"][method]
         for uid in stats["uid"].keys():
             current["uid"][uid] += stats["uid"][uid]
+        for ua in stats["user-agent"].keys():
+            current["user-agent"][ua] += stats["user-agent"][ua]
         current["500"] += stats["500"]
         current["t"] += stats["t"]
         current["t-resp-wr"] += stats["t-resp-wr"]

Copied: CalendarServer/trunk/calendarserver/logAnalysis.py (from rev 10157, CalendarServer/trunk/calendarserver/methodDescriptor.py)
===================================================================
--- CalendarServer/trunk/calendarserver/logAnalysis.py	                        (rev 0)
+++ CalendarServer/trunk/calendarserver/logAnalysis.py	2012-12-12 17:18:55 UTC (rev 10159)
@@ -0,0 +1,373 @@
+##
+# Copyright (c) 2012 Apple Inc. 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.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License 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.
+##
+
+# Adjust method names
+
+# PROPFINDs
+METHOD_PROPFIND_CALENDAR_HOME = "PROPFIND Calendar Home"
+METHOD_PROPFIND_CACHED_CALENDAR_HOME = "PROPFIND cached Calendar Home"
+METHOD_PROPFIND_CALENDAR = "PROPFIND Calendar"
+METHOD_PROPFIND_INBOX = "PROPFIND Inbox"
+METHOD_PROPFIND_ADDRESSBOOK_HOME = "PROPFIND Adbk Home"
+METHOD_PROPFIND_CACHED_ADDRESSBOOK_HOME = "PROPFIND cached Adbk Home"
+METHOD_PROPFIND_ADDRESSBOOK = "PROPFIND Adbk"
+METHOD_PROPFIND_DIRECTORY = "PROPFIND Directory"
+METHOD_PROPFIND_PRINCIPALS = "PROPFIND Principals"
+METHOD_PROPFIND_CACHED_PRINCIPALS = "PROPFIND cached Principals"
+
+# PROPPATCHs
+METHOD_PROPPATCH_CALENDAR = "PROPPATCH Calendar"
+METHOD_PROPPATCH_ADDRESSBOOK = "PROPPATCH Adbk Home"
+
+# REPORTs
+METHOD_REPORT_CALENDAR_MULTIGET = "REPORT cal-multi"
+METHOD_REPORT_CALENDAR_QUERY = "REPORT cal-query"
+METHOD_REPORT_CALENDAR_FREEBUSY = "REPORT freebusy"
+METHOD_REPORT_CALENDAR_SYNC = "REPORT cal-sync"
+METHOD_REPORT_ADDRESSBOOK_MULTIGET = "REPORT adbk-multi"
+METHOD_REPORT_ADDRESSBOOK_QUERY = "REPORT adbk-query"
+METHOD_REPORT_DIRECTORY_QUERY = "REPORT dir-query"
+METHOD_REPORT_ADDRESSBOOK_SYNC = "REPORT adbk-sync"
+METHOD_REPORT_P_SEARCH_P_SET = "REPORT p-set"
+METHOD_REPORT_P_P_SEARCH = "REPORT p-search"
+METHOD_REPORT_EXPAND_P = "REPORT expand"
+
+# POSTs
+METHOD_POST_CALENDAR_HOME = "POST Calendar Home"
+METHOD_POST_CALENDAR = "POST Calendar"
+METHOD_POST_CALENDAR_OBJECT = "POST Calendar Object"
+METHOD_POST_ADDRESSBOOK_HOME = "POST Adbk Home"
+METHOD_POST_ADDRESSBOOK = "POST Adbk"
+METHOD_POST_ISCHEDULE_FREEBUSY = "POST Freebusy iSchedule"
+METHOD_POST_ISCHEDULE = "POST iSchedule"
+METHOD_POST_TIMEZONES = "POST Timezones"
+METHOD_POST_FREEBUSY = "POST Freebusy"
+METHOD_POST_ORGANIZER = "POST Organizer"
+METHOD_POST_ATTENDEE = "POST Attendee"
+METHOD_POST_OUTBOX = "POST Outbox"
+METHOD_POST_APNS = "POST apns"
+
+# PUTs
+METHOD_PUT_ICS = "PUT ics"
+METHOD_PUT_ORGANIZER = "PUT Organizer"
+METHOD_PUT_ATTENDEE = "PUT Attendee"
+METHOD_PUT_DROPBOX = "PUT dropbox"
+METHOD_PUT_VCF = "PUT VCF"
+
+# GETs
+METHOD_GET_CALENDAR_HOME = "GET Calendar Home"
+METHOD_GET_CALENDAR = "GET Calendar"
+METHOD_GET_ICS = "GET ics"
+METHOD_GET_INBOX_ICS = "GET inbox ics"
+METHOD_GET_DROPBOX = "GET dropbox"
+METHOD_GET_ADDRESSBOOK_HOME = "GET Adbk Home"
+METHOD_GET_ADDRESSBOOK = "GET Adbk"
+METHOD_GET_VCF = "GET VCF"
+METHOD_GET_TIMEZONES = "GET Timezones"
+
+# DELETEs
+METHOD_DELETE_CALENDAR_HOME = "DELETE Calendar Home"
+METHOD_DELETE_CALENDAR = "DELETE Calendar"
+METHOD_DELETE_ICS = "DELETE ics"
+METHOD_DELETE_INBOX_ICS = "DELETE inbox ics"
+METHOD_DELETE_DROPBOX = "DELETE dropbox"
+METHOD_DELETE_ADDRESSBOOK_HOME = "DELETE Adbk Home"
+METHOD_DELETE_ADDRESSBOOK = "DELETE Adbk"
+METHOD_DELETE_VCF = "DELETE vcf"
+
+
+def getAdjustedMethodName(stats):
+
+    method = stats["method"]
+    uribits = stats["uri"].rstrip("/").split('/')[1:]
+    if len(uribits) == 0:
+        uribits = [stats["uri"]]
+
+    calendar_specials = ("attachments", "dropbox", "notification", "freebusy", "outbox",)
+    adbk_specials = ("notification",)
+
+    def _PROPFIND():
+        cached = "cached" in stats
+
+        if uribits[0] == "calendars":
+
+            if len(uribits) == 3:
+                return METHOD_PROPFIND_CACHED_CALENDAR_HOME if cached else METHOD_PROPFIND_CALENDAR_HOME
+            elif len(uribits) > 3:
+                if uribits[3] in calendar_specials:
+                    return "PROPFIND %s" % (uribits[3],)
+                elif len(uribits) == 4:
+                    if uribits[3] == "inbox":
+                        return METHOD_PROPFIND_INBOX
+                    else:
+                        return METHOD_PROPFIND_CALENDAR
+
+        elif uribits[0] == "addressbooks":
+
+            if len(uribits) == 3:
+                return METHOD_PROPFIND_CACHED_ADDRESSBOOK_HOME if cached else METHOD_PROPFIND_ADDRESSBOOK_HOME
+            elif len(uribits) > 3:
+                if uribits[3] in adbk_specials:
+                    return "PROPFIND %s" % (uribits[3],)
+                elif len(uribits) == 4:
+                    return METHOD_PROPFIND_ADDRESSBOOK
+
+        elif uribits[0] == "directory":
+            return METHOD_PROPFIND_DIRECTORY
+
+        elif uribits[0] == "principals":
+            return METHOD_PROPFIND_CACHED_PRINCIPALS if cached else METHOD_PROPFIND_PRINCIPALS
+
+        return method
+
+
+    def _REPORT():
+
+        if "(" in method:
+            report_type = method.split("}" if "}" in method else ":")[1][:-1]
+            if report_type == "addressbook-query":
+                if uribits[0] == "directory":
+                    report_type = "directory-query"
+            if report_type == "sync-collection":
+                if uribits[0] == "calendars":
+                    report_type = "cal-sync"
+                elif uribits[0] == "addressbooks":
+                    report_type = "adbk-sync"
+            mappedNames = {
+                "calendar-multiget"             : METHOD_REPORT_CALENDAR_MULTIGET,
+                "calendar-query"                : METHOD_REPORT_CALENDAR_QUERY,
+                "free-busy-query"               : METHOD_REPORT_CALENDAR_FREEBUSY,
+                "cal-sync"                      : METHOD_REPORT_CALENDAR_SYNC,
+                "addressbook-multiget"          : METHOD_REPORT_ADDRESSBOOK_MULTIGET,
+                "addressbook-query"             : METHOD_REPORT_ADDRESSBOOK_QUERY,
+                "directory-query"               : METHOD_REPORT_DIRECTORY_QUERY,
+                "adbk-sync"                     : METHOD_REPORT_ADDRESSBOOK_SYNC,
+                "principal-search-property-set" : METHOD_REPORT_P_SEARCH_P_SET,
+                "principal-property-search"     : METHOD_REPORT_P_P_SEARCH,
+                "expand-property"               : METHOD_REPORT_EXPAND_P,
+            }
+            return mappedNames.get(report_type, "REPORT %s" % (report_type,))
+
+        return method
+
+
+    def _PROPPATCH():
+
+        if uribits[0] == "calendars":
+            return METHOD_PROPPATCH_CALENDAR
+        elif uribits[0] == "addressbooks":
+            return METHOD_PROPPATCH_ADDRESSBOOK
+
+        return method
+
+
+    def _POST():
+
+        if uribits[0] == "calendars":
+
+            if len(uribits) == 3:
+                return METHOD_POST_CALENDAR_HOME
+            elif len(uribits) == 4:
+                if uribits[3] == "outbox":
+                    if "recipients" in stats:
+                        return METHOD_POST_FREEBUSY
+                    elif "freebusy" in stats:
+                        return METHOD_POST_FREEBUSY
+                    elif "itip.request" in stats or "itip.cancel" in stats:
+                        return METHOD_POST_ORGANIZER
+                    elif "itip.reply" in stats:
+                        return METHOD_POST_ATTENDEE
+                    else:
+                        return METHOD_POST_OUTBOX
+                elif uribits[3] in calendar_specials:
+                    pass
+                else:
+                    return METHOD_POST_CALENDAR
+            elif len(uribits) == 5:
+                return METHOD_POST_CALENDAR_OBJECT
+
+        elif uribits[0] == "addressbooks":
+
+            if len(uribits) == 3:
+                return METHOD_POST_ADDRESSBOOK_HOME
+            elif len(uribits) == 4:
+                if uribits[3] in adbk_specials:
+                    pass
+                else:
+                    return METHOD_POST_ADDRESSBOOK
+
+        elif uribits[0] == "ischedule":
+            if "fb-cached" in stats or "fb-uncached" in stats or "freebusy" in stats:
+                return METHOD_POST_ISCHEDULE_FREEBUSY
+            else:
+                return METHOD_POST_ISCHEDULE
+
+        elif uribits[0].startswith("timezones"):
+            return METHOD_POST_TIMEZONES
+
+        elif uribits[0].startswith("apns"):
+            return METHOD_POST_APNS
+
+        return method
+
+
+    def _PUT():
+
+        if uribits[0] == "calendars":
+            if len(uribits) > 3:
+                if uribits[3] in calendar_specials:
+                    return "PUT %s" % (uribits[3],)
+                elif len(uribits) == 4:
+                    pass
+                else:
+                    if "itip.requests" in stats:
+                        return METHOD_PUT_ORGANIZER
+                    elif "itip.reply" in stats:
+                        return METHOD_PUT_ATTENDEE
+                    else:
+                        return METHOD_PUT_ICS
+
+        elif uribits[0] == "addressbooks":
+            if len(uribits) > 3:
+                if uribits[3] in adbk_specials:
+                    return "PUT %s" % (uribits[3],)
+                elif len(uribits) == 4:
+                    pass
+                else:
+                    return METHOD_PUT_VCF
+
+        return method
+
+
+    def _GET():
+
+        if uribits[0] == "calendars":
+
+            if len(uribits) == 3:
+                return METHOD_GET_CALENDAR_HOME
+            elif len(uribits) > 3:
+                if uribits[3] in calendar_specials:
+                    return "GET %s" % (uribits[3],)
+                elif len(uribits) == 4:
+                    return METHOD_GET_CALENDAR
+                elif uribits[3] == "inbox":
+                    return METHOD_GET_INBOX_ICS
+                else:
+                    return METHOD_GET_ICS
+
+        elif uribits[0] == "addressbooks":
+
+            if len(uribits) == 3:
+                return METHOD_GET_ADDRESSBOOK_HOME
+            elif len(uribits) > 3:
+                if uribits[3] in adbk_specials:
+                    return "GET %s" % (uribits[3],)
+                elif len(uribits) == 4:
+                    return METHOD_GET_ADDRESSBOOK
+                else:
+                    return METHOD_GET_VCF
+
+        elif uribits[0].startswith("timezones"):
+            return METHOD_GET_TIMEZONES
+
+        return method
+
+
+    def _DELETE():
+
+        if uribits[0] == "calendars":
+
+            if len(uribits) == 3:
+                return METHOD_DELETE_CALENDAR_HOME
+            elif len(uribits) > 3:
+                if uribits[3] in calendar_specials:
+                    return "DELETE %s" % (uribits[3],)
+                elif len(uribits) == 4:
+                    return METHOD_DELETE_CALENDAR
+                elif uribits[3] == "inbox":
+                    return METHOD_DELETE_INBOX_ICS
+                else:
+                    return METHOD_DELETE_ICS
+
+        elif uribits[0] == "addressbooks":
+
+            if len(uribits) == 3:
+                return METHOD_DELETE_ADDRESSBOOK_HOME
+            elif len(uribits) > 3:
+                if uribits[3] in adbk_specials:
+                    return "DELETE %s" % (uribits[3],)
+                elif len(uribits) == 4:
+                    return METHOD_DELETE_ADDRESSBOOK
+                else:
+                    return METHOD_DELETE_VCF
+
+        return method
+
+
+    def _ANY():
+        return method
+
+    return {
+        "DELETE" : _DELETE,
+        "GET" : _GET,
+        "POST" : _POST,
+        "PROPFIND" : _PROPFIND,
+        "PROPPATCH" : _PROPPATCH,
+        "PUT" : _PUT,
+        "REPORT" : _REPORT,
+    }.get(method.split("(")[0], _ANY)()
+
+
+
+versionClients = (
+    "Mac OS X/",
+    "iOS/",
+    "iCal/",
+    "iPhone/",
+    "CalendarAgent",
+    "Calendar/",
+    "CoreDAV/",
+    "Safari/",
+    "dataaccessd",
+    "curl/",
+    "DAVKit",
+)
+
+quickclients = (
+    ("InterMapper/", "InterMapper"),
+    ("CardDAVPlugin/", "CardDAVPlugin"),
+    ("Address%20Book/", "AddressBook"),
+    ("AddressBook/", "AddressBook"),
+    ("Mail/", "Mail"),
+    ("iChat/", "iChat"),
+)
+
+def getAdjustedClientName(stats):
+
+    userAgent = stats["userAgent"]
+    for client in versionClients:
+        index = userAgent.find(client)
+        if index != -1:
+            l = len(client)
+            endex = userAgent[index + l:].find(' ', index)
+            return userAgent[index:] if endex == -1 else userAgent[index:endex + l]
+
+    for quick, result in quickclients:
+        index = userAgent.find(quick)
+        if index != -1:
+            return result
+
+    return userAgent[:20]

Deleted: CalendarServer/trunk/calendarserver/methodDescriptor.py
===================================================================
--- CalendarServer/trunk/calendarserver/methodDescriptor.py	2012-12-12 16:37:28 UTC (rev 10158)
+++ CalendarServer/trunk/calendarserver/methodDescriptor.py	2012-12-12 17:18:55 UTC (rev 10159)
@@ -1,330 +0,0 @@
-##
-# Copyright (c) 2012 Apple Inc. 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.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License 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.
-##
-
-# Adjust method names
-
-# PROPFINDs
-METHOD_PROPFIND_CALENDAR_HOME = "PROPFIND Calendar Home"
-METHOD_PROPFIND_CACHED_CALENDAR_HOME = "PROPFIND cached Calendar Home"
-METHOD_PROPFIND_CALENDAR = "PROPFIND Calendar"
-METHOD_PROPFIND_INBOX = "PROPFIND Inbox"
-METHOD_PROPFIND_ADDRESSBOOK_HOME = "PROPFIND Adbk Home"
-METHOD_PROPFIND_CACHED_ADDRESSBOOK_HOME = "PROPFIND cached Adbk Home"
-METHOD_PROPFIND_ADDRESSBOOK = "PROPFIND Adbk"
-METHOD_PROPFIND_DIRECTORY = "PROPFIND Directory"
-METHOD_PROPFIND_PRINCIPALS = "PROPFIND Principals"
-METHOD_PROPFIND_CACHED_PRINCIPALS = "PROPFIND cached Principals"
-
-# PROPPATCHs
-METHOD_PROPPATCH_CALENDAR = "PROPPATCH Calendar"
-METHOD_PROPPATCH_ADDRESSBOOK = "PROPPATCH Adbk Home"
-
-# REPORTs
-METHOD_REPORT_CALENDAR_MULTIGET = "REPORT cal-multi"
-METHOD_REPORT_CALENDAR_QUERY = "REPORT cal-query"
-METHOD_REPORT_CALENDAR_FREEBUSY = "REPORT freebusy"
-METHOD_REPORT_CALENDAR_SYNC = "REPORT cal-sync"
-METHOD_REPORT_ADDRESSBOOK_MULTIGET = "REPORT adbk-multi"
-METHOD_REPORT_ADDRESSBOOK_QUERY = "REPORT adbk-query"
-METHOD_REPORT_DIRECTORY_QUERY = "REPORT dir-query"
-METHOD_REPORT_ADDRESSBOOK_SYNC = "REPORT adbk-sync"
-METHOD_REPORT_P_SEARCH_P_SET = "REPORT p-set"
-METHOD_REPORT_P_P_SEARCH = "REPORT p-search"
-METHOD_REPORT_EXPAND_P = "REPORT expand"
-
-# POSTs
-METHOD_POST_CALENDAR_HOME = "POST Calendar Home"
-METHOD_POST_CALENDAR = "POST Calendar"
-METHOD_POST_CALENDAR_OBJECT = "POST Calendar Object"
-METHOD_POST_ADDRESSBOOK_HOME = "POST Adbk Home"
-METHOD_POST_ADDRESSBOOK = "POST Adbk"
-METHOD_POST_ISCHEDULE_FREEBUSY = "POST Freebusy iSchedule"
-METHOD_POST_ISCHEDULE = "POST iSchedule"
-METHOD_POST_TIMEZONES = "POST Timezones"
-METHOD_POST_FREEBUSY = "POST Freebusy"
-METHOD_POST_ORGANIZER = "POST Organizer"
-METHOD_POST_ATTENDEE = "POST Attendee"
-METHOD_POST_OUTBOX = "POST Outbox"
-METHOD_POST_APNS = "POST apns"
-
-# PUTs
-METHOD_PUT_ICS = "PUT ics"
-METHOD_PUT_ORGANIZER = "PUT Organizer"
-METHOD_PUT_ATTENDEE = "PUT Attendee"
-METHOD_PUT_DROPBOX = "PUT dropbox"
-METHOD_PUT_VCF = "PUT VCF"
-
-# GETs
-METHOD_GET_CALENDAR_HOME = "GET Calendar Home"
-METHOD_GET_CALENDAR = "GET Calendar"
-METHOD_GET_ICS = "GET ics"
-METHOD_GET_INBOX_ICS = "GET inbox ics"
-METHOD_GET_DROPBOX = "GET dropbox"
-METHOD_GET_ADDRESSBOOK_HOME = "GET Adbk Home"
-METHOD_GET_ADDRESSBOOK = "GET Adbk"
-METHOD_GET_VCF = "GET VCF"
-METHOD_GET_TIMEZONES = "GET Timezones"
-
-# DELETEs
-METHOD_DELETE_CALENDAR_HOME = "DELETE Calendar Home"
-METHOD_DELETE_CALENDAR = "DELETE Calendar"
-METHOD_DELETE_ICS = "DELETE ics"
-METHOD_DELETE_INBOX_ICS = "DELETE inbox ics"
-METHOD_DELETE_DROPBOX = "DELETE dropbox"
-METHOD_DELETE_ADDRESSBOOK_HOME = "DELETE Adbk Home"
-METHOD_DELETE_ADDRESSBOOK = "DELETE Adbk"
-METHOD_DELETE_VCF = "DELETE vcf"
-
-
-def getAdjustedMethodName(method, uri, extended):
-
-    uribits = uri.rstrip("/").split('/')[1:]
-    if len(uribits) == 0:
-        uribits = [uri]
-
-    calendar_specials = ("attachments", "dropbox", "notification", "freebusy", "outbox",)
-    adbk_specials = ("notification",)
-
-    def _PROPFIND():
-        cached = "cached" in extended
-
-        if uribits[0] == "calendars":
-
-            if len(uribits) == 3:
-                return METHOD_PROPFIND_CACHED_CALENDAR_HOME if cached else METHOD_PROPFIND_CALENDAR_HOME
-            elif len(uribits) > 3:
-                if uribits[3] in calendar_specials:
-                    return "PROPFIND %s" % (uribits[3],)
-                elif len(uribits) == 4:
-                    if uribits[3] == "inbox":
-                        return METHOD_PROPFIND_INBOX
-                    else:
-                        return METHOD_PROPFIND_CALENDAR
-
-        elif uribits[0] == "addressbooks":
-
-            if len(uribits) == 3:
-                return METHOD_PROPFIND_CACHED_ADDRESSBOOK_HOME if cached else METHOD_PROPFIND_ADDRESSBOOK_HOME
-            elif len(uribits) > 3:
-                if uribits[3] in adbk_specials:
-                    return "PROPFIND %s" % (uribits[3],)
-                elif len(uribits) == 4:
-                    return METHOD_PROPFIND_ADDRESSBOOK
-
-        elif uribits[0] == "directory":
-            return METHOD_PROPFIND_DIRECTORY
-
-        elif uribits[0] == "principals":
-            return METHOD_PROPFIND_CACHED_PRINCIPALS if cached else METHOD_PROPFIND_PRINCIPALS
-
-        return method
-
-
-    def _REPORT():
-
-        if "(" in method:
-            report_type = method.split("}" if "}" in method else ":")[1][:-1]
-            if report_type == "addressbook-query":
-                if uribits[0] == "directory":
-                    report_type = "directory-query"
-            if report_type == "sync-collection":
-                if uribits[0] == "calendars":
-                    report_type = "cal-sync"
-                elif uribits[0] == "addressbooks":
-                    report_type = "adbk-sync"
-            mappedNames = {
-                "calendar-multiget"             : METHOD_REPORT_CALENDAR_MULTIGET,
-                "calendar-query"                : METHOD_REPORT_CALENDAR_QUERY,
-                "free-busy-query"               : METHOD_REPORT_CALENDAR_FREEBUSY,
-                "cal-sync"                      : METHOD_REPORT_CALENDAR_SYNC,
-                "addressbook-multiget"          : METHOD_REPORT_ADDRESSBOOK_MULTIGET,
-                "addressbook-query"             : METHOD_REPORT_ADDRESSBOOK_QUERY,
-                "directory-query"               : METHOD_REPORT_DIRECTORY_QUERY,
-                "adbk-sync"                     : METHOD_REPORT_ADDRESSBOOK_SYNC,
-                "principal-search-property-set" : METHOD_REPORT_P_SEARCH_P_SET,
-                "principal-property-search"     : METHOD_REPORT_P_P_SEARCH,
-                "expand-property"               : METHOD_REPORT_EXPAND_P,
-            }
-            return mappedNames.get(report_type, "REPORT %s" % (report_type,))
-
-        return method
-
-
-    def _PROPPATCH():
-
-        if uribits[0] == "calendars":
-            return METHOD_PROPPATCH_CALENDAR
-        elif uribits[0] == "addressbooks":
-            return METHOD_PROPPATCH_ADDRESSBOOK
-
-        return method
-
-
-    def _POST():
-
-        if uribits[0] == "calendars":
-
-            if len(uribits) == 3:
-                return METHOD_POST_CALENDAR_HOME
-            elif len(uribits) == 4:
-                if uribits[3] == "outbox":
-                    if "recipients" in extended:
-                        return METHOD_POST_FREEBUSY
-                    elif "freebusy" in extended:
-                        return METHOD_POST_FREEBUSY
-                    elif "itip.request" in extended or "itip.cancel" in extended:
-                        return METHOD_POST_ORGANIZER
-                    elif "itip.reply" in extended:
-                        return METHOD_POST_ATTENDEE
-                    else:
-                        return METHOD_POST_OUTBOX
-                elif uribits[3] in calendar_specials:
-                    pass
-                else:
-                    return METHOD_POST_CALENDAR
-            elif len(uribits) == 5:
-                return METHOD_POST_CALENDAR_OBJECT
-
-        elif uribits[0] == "addressbooks":
-
-            if len(uribits) == 3:
-                return METHOD_POST_ADDRESSBOOK_HOME
-            elif len(uribits) == 4:
-                if uribits[3] in adbk_specials:
-                    pass
-                else:
-                    return METHOD_POST_ADDRESSBOOK
-
-        elif uribits[0] == "ischedule":
-            if "fb-cached" in extended or "fb-uncached" in extended or "freebusy" in extended:
-                return METHOD_POST_ISCHEDULE_FREEBUSY
-            else:
-                return METHOD_POST_ISCHEDULE
-
-        elif uribits[0].startswith("timezones"):
-            return METHOD_POST_TIMEZONES
-
-        elif uribits[0].startswith("apns"):
-            return METHOD_POST_APNS
-
-        return method
-
-
-    def _PUT():
-
-        if uribits[0] == "calendars":
-            if len(uribits) > 3:
-                if uribits[3] in calendar_specials:
-                    return "PUT %s" % (uribits[3],)
-                elif len(uribits) == 4:
-                    pass
-                else:
-                    if "itip.requests" in extended:
-                        return METHOD_PUT_ORGANIZER
-                    elif "itip.reply" in extended:
-                        return METHOD_PUT_ATTENDEE
-                    else:
-                        return METHOD_PUT_ICS
-
-        elif uribits[0] == "addressbooks":
-            if len(uribits) > 3:
-                if uribits[3] in adbk_specials:
-                    return "PUT %s" % (uribits[3],)
-                elif len(uribits) == 4:
-                    pass
-                else:
-                    return METHOD_PUT_VCF
-
-        return method
-
-
-    def _GET():
-
-        if uribits[0] == "calendars":
-
-            if len(uribits) == 3:
-                return METHOD_GET_CALENDAR_HOME
-            elif len(uribits) > 3:
-                if uribits[3] in calendar_specials:
-                    return "GET %s" % (uribits[3],)
-                elif len(uribits) == 4:
-                    return METHOD_GET_CALENDAR
-                elif uribits[3] == "inbox":
-                    return METHOD_GET_INBOX_ICS
-                else:
-                    return METHOD_GET_ICS
-
-        elif uribits[0] == "addressbooks":
-
-            if len(uribits) == 3:
-                return METHOD_GET_ADDRESSBOOK_HOME
-            elif len(uribits) > 3:
-                if uribits[3] in adbk_specials:
-                    return "GET %s" % (uribits[3],)
-                elif len(uribits) == 4:
-                    return METHOD_GET_ADDRESSBOOK
-                else:
-                    return METHOD_GET_VCF
-
-        elif uribits[0].startswith("timezones"):
-            return METHOD_GET_TIMEZONES
-
-        return method
-
-
-    def _DELETE():
-
-        if uribits[0] == "calendars":
-
-            if len(uribits) == 3:
-                return METHOD_DELETE_CALENDAR_HOME
-            elif len(uribits) > 3:
-                if uribits[3] in calendar_specials:
-                    return "DELETE %s" % (uribits[3],)
-                elif len(uribits) == 4:
-                    return METHOD_DELETE_CALENDAR
-                elif uribits[3] == "inbox":
-                    return METHOD_DELETE_INBOX_ICS
-                else:
-                    return METHOD_DELETE_ICS
-
-        elif uribits[0] == "addressbooks":
-
-            if len(uribits) == 3:
-                return METHOD_DELETE_ADDRESSBOOK_HOME
-            elif len(uribits) > 3:
-                if uribits[3] in adbk_specials:
-                    return "DELETE %s" % (uribits[3],)
-                elif len(uribits) == 4:
-                    return METHOD_DELETE_ADDRESSBOOK
-                else:
-                    return METHOD_DELETE_VCF
-
-        return method
-
-
-    def _ANY():
-        return method
-
-    return {
-        "DELETE" : _DELETE,
-        "GET" : _GET,
-        "POST" : _POST,
-        "PROPFIND" : _PROPFIND,
-        "PROPPATCH" : _PROPPATCH,
-        "PUT" : _PUT,
-        "REPORT" : _REPORT,
-    }.get(method.split("(")[0], _ANY)()

Modified: CalendarServer/trunk/contrib/tools/readStats.py
===================================================================
--- CalendarServer/trunk/contrib/tools/readStats.py	2012-12-12 16:37:28 UTC (rev 10158)
+++ CalendarServer/trunk/contrib/tools/readStats.py	2012-12-12 17:18:55 UTC (rev 10159)
@@ -54,23 +54,23 @@
 
 
 
-def printStats(stats, multimode, showMethods, topUsers):
+def printStats(stats, multimode, showMethods, topUsers, showAgents):
     if len(stats) == 1:
         if "Failed" in stats[0]:
             printFailedStats(stats[0]["Failed"])
         else:
             try:
-                printStat(stats[0], multimode[0], showMethods, topUsers)
+                printStat(stats[0], multimode[0], showMethods, topUsers, showAgents)
             except KeyError, e:
                 printFailedStats("Unable to find key '%s' in statistics from server socket" % (e,))
                 sys.exit(1)
 
     else:
-        printMultipleStats(stats, multimode, showMethods, topUsers)
+        printMultipleStats(stats, multimode, showMethods, topUsers, showAgents)
 
 
 
-def printStat(stats, index, showMethods, topUsers):
+def printStat(stats, index, showMethods, topUsers, showAgents):
 
     print "- " * 40
     print "Server: %s" % (stats["Server"],)
@@ -91,15 +91,17 @@
         print "Current Memory Used: Unavailable"
     print
     printRequestSummary(stats)
-    printHistogramSummary(stats[index])
+    printHistogramSummary(stats[index], index)
     if showMethods:
         printMethodCounts(stats[index])
     if topUsers:
         printUserCounts(stats[index], topUsers)
+    if showAgents:
+        printAgentCounts(stats[index])
 
 
 
-def printMultipleStats(stats, multimode, showMethods, topUsers):
+def printMultipleStats(stats, multimode, showMethods, topUsers, showAgents):
 
     labels = serverLabels(stats)
 
@@ -130,6 +132,8 @@
         printMultiMethodCounts(stats, multimode[0])
     if topUsers:
         printMultiUserCounts(stats, multimode[0], topUsers)
+    if showAgents:
+        printMultiAgentCounts(stats, multimode[0])
 
 
 
@@ -274,9 +278,9 @@
 
 
 
-def printHistogramSummary(stat):
+def printHistogramSummary(stat, index):
 
-    print "5 minute average response histogram"
+    print "%s average response histogram" % (index,)
     table = tables.Table()
     table.addHeader(
         ("", "<10ms", "10ms<->100ms", "100ms<->1s", "1s<->10s", "10s<->30s", "30s<->60s", ">60s", "Over 1s", "Over 10s"),
@@ -329,41 +333,7 @@
             for k in keys[1:]:
                 totals[i][k] += stat[index][i][k]
 
-    print "%s average response histogram" % (index,)
-    table = tables.Table()
-    table.addHeader(
-        ("", "<10ms", "10ms<->100ms", "100ms<->1s", "1s<->10s", "10s<->30s", "30s<->60s", ">60s", "Over 1s", "Over 10s"),
-    )
-    table.setDefaultColumnFormats(
-       (
-            tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.LEFT_JUSTIFY),
-            tables.Table.ColumnFormat("%d (%.1f%%)", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%d (%.1f%%)", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%d (%.1f%%)", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%d (%.1f%%)", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%d (%.1f%%)", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%d (%.1f%%)", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%d (%.1f%%)", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%.1f%%", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%.1f%%", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-        )
-    )
-    for i in ("T", "T-RESP-WR",):
-        table.addRow((
-            "Overall Response" if i == "T" else "Response Write",
-            (totals[i]["<10ms"], safeDivision(totals[i]["<10ms"], totals[i]["requests"], 100.0)),
-            (totals[i]["10ms<->100ms"], safeDivision(totals[i]["10ms<->100ms"], totals[i]["requests"], 100.0)),
-            (totals[i]["100ms<->1s"], safeDivision(totals[i]["100ms<->1s"], totals[i]["requests"], 100.0)),
-            (totals[i]["1s<->10s"], safeDivision(totals[i]["1s<->10s"], totals[i]["requests"], 100.0)),
-            (totals[i]["10s<->30s"], safeDivision(totals[i]["10s<->30s"], totals[i]["requests"], 100.0)),
-            (totals[i]["30s<->60s"], safeDivision(totals[i]["30s<->60s"], totals[i]["requests"], 100.0)),
-            (totals[i][">60s"], safeDivision(totals[i][">60s"], totals[i]["requests"], 100.0)),
-            safeDivision(totals[i]["Over 1s"], totals[i]["requests"], 100.0),
-            safeDivision(totals[i]["Over 10s"], totals[i]["requests"], 100.0),
-        ))
-    os = StringIO()
-    table.printTable(os=os)
-    print os.getvalue()
+    printHistogramSummary(totals, index)
 
 
 
@@ -372,22 +342,38 @@
     print "Method Counts"
     table = tables.Table()
     table.addHeader(
-        ("Method", "Total", "Percentage"),
+        ("Method", "Count", "%", "Av. Response", "%", "Total Resp. %"),
     )
+    table.addHeader(
+        ("", "", "", "(ms)", "", ""),
+    )
     table.setDefaultColumnFormats(
        (
             tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.LEFT_JUSTIFY),
             tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
             tables.Table.ColumnFormat("%.1f%%", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+            tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+            tables.Table.ColumnFormat("%.1f%%", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+            tables.Table.ColumnFormat("%.1f%%", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
         )
     )
 
-    total = sum(stat["method"].values())
+    response_average = {}
+    for method in stat["method"].keys():
+        response_average[method] = stat["method-t"][method] / stat["method"][method]
+
+    total_count = sum(stat["method"].values())
+    total_avresponse = sum(response_average.values())
+    total_response = sum(stat["method-t"].values())
+
     for method in sorted(stat["method"].keys()):
         table.addRow((
             method,
             stat["method"][method],
-            safeDivision(stat["method"][method], total, 100.0),
+            safeDivision(stat["method"][method], total_count, 100.0),
+            response_average[method],
+            safeDivision(response_average[method], total_avresponse, 100.0),
+            safeDivision(stat["method-t"][method], total_response, 100.0),
         ))
     os = StringIO()
     table.printTable(os=os)
@@ -398,36 +384,17 @@
 def printMultiMethodCounts(stats, index):
 
     methods = collections.defaultdict(int)
+    method_times = collections.defaultdict(float)
     for stat in stats:
         for method in stat[index]["method"]:
             methods[method] += stat[index]["method"][method]
+        for method_time in stat[index]["method-t"]:
+            method_times[method_time] += stat[index]["method-t"][method_time]
 
-    print "Method Counts"
-    table = tables.Table()
-    table.addHeader(
-        ("Method", "Total", "Percentage"),
-    )
-    table.setDefaultColumnFormats(
-       (
-            tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.LEFT_JUSTIFY),
-            tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%.1f%%", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-        )
-    )
+    printMethodCounts({"method": methods, "method-t": method_times})
 
-    total = sum(methods.values())
-    for method in sorted(methods.keys()):
-        table.addRow((
-            method,
-            methods[method],
-            safeDivision(methods[method], total, 100.0),
-        ))
-    os = StringIO()
-    table.printTable(os=os)
-    print os.getvalue()
 
 
-
 def printUserCounts(stat, topUsers):
 
     print "User Counts"
@@ -444,11 +411,11 @@
     )
 
     total = sum(stat["uid"].values())
-    for uid in sorted(stat["uid"].items(), key=lambda x: x[1], reverse=True)[:topUsers]:
+    for uid, value in sorted(stat["uid"].items(), key=lambda x: x[1], reverse=True)[:topUsers]:
         table.addRow((
             uid,
-            stat["uid"][uid],
-            safeDivision(stat["uid"][uid], total, 100.0),
+            value,
+            safeDivision(value, total, 100.0),
         ))
     os = StringIO()
     table.printTable(os=os)
@@ -463,25 +430,31 @@
         for uid in stat[index]["uid"]:
             uids[uid] += stat[index]["uid"][uid]
 
-    print "User Counts"
+    printUserCounts({"uid": uids}, topUsers)
+
+
+
+def printAgentCounts(stat):
+
+    print "User-Agent Counts"
     table = tables.Table()
     table.addHeader(
-        ("User", "Total", "Percentage"),
+        ("User-Agent", "Total", "Percentage"),
     )
     table.setDefaultColumnFormats(
-        (
+       (
             tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.LEFT_JUSTIFY),
             tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
             tables.Table.ColumnFormat("%.1f%%", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
         )
     )
 
-    total = sum(uids.values())
-    for uid, count in sorted(uids.items(), key=lambda x: x[1], reverse=True)[:topUsers]:
+    total = sum(stat["user-agent"].values())
+    for ua in sorted(stat["user-agent"].keys()):
         table.addRow((
-            uid,
-            count,
-            safeDivision(count, total, 100.0),
+            ua,
+            stat["user-agent"][ua],
+            safeDivision(stat["user-agent"][ua], total, 100.0),
         ))
     os = StringIO()
     table.printTable(os=os)
@@ -489,6 +462,17 @@
 
 
 
+def printMultiAgentCounts(stats, index):
+
+    uas = collections.defaultdict(int)
+    for stat in stats:
+        for ua in stat[index]["user-agent"]:
+            uas[ua] += stat[index]["user-agent"][ua]
+
+    printUserCounts({"user-agent": uas})
+
+
+
 def usage(error_msg=None):
     if error_msg:
         print error_msg
@@ -505,6 +489,7 @@
     --60          Display multiserver 1 hour average
     --methods     Include details about HTTP method usage
     --users N     Include details about top N users
+    --agents      Include details about HTTP User-Agent usage
 
 Description:
     This utility will print a summary of statistics read from a
@@ -525,11 +510,12 @@
     useTCP = False
     showMethods = False
     topUsers = 0
+    showAgents = False
 
     multimodes = (("Current", 60,), ("1 Minute", 60,), ("5 Minutes", 5 * 60,), ("1 Hour", 60 * 60,),)
     multimode = multimodes[2]
 
-    options, args = getopt.getopt(sys.argv[1:], "hs:t:", ["tcp=", "0", "1", "5", "60", "methods", "users="])
+    options, args = getopt.getopt(sys.argv[1:], "hs:t:", ["tcp=", "0", "1", "5", "60", "methods", "users=", "agents"])
 
     for option, value in options:
         if option == "-h":
@@ -553,7 +539,9 @@
             showMethods = True
         elif option == "--users":
             topUsers = int(value)
+        elif option == "--agents":
+            showAgents = True
 
     while True:
-        printStats([readSock(server, useTCP) for server in servers], multimode, showMethods, topUsers)
+        printStats([readSock(server, useTCP) for server in servers], multimode, showMethods, topUsers, showAgents)
         time.sleep(delay)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20121212/3cce5bd3/attachment-0001.html>


More information about the calendarserver-changes mailing list