[CalendarServer-changes] [4059] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Apr 22 09:33:28 PDT 2009


Revision: 4059
          http://trac.macosforge.org/projects/calendarserver/changeset/4059
Author:   cdaboo at apple.com
Date:     2009-04-22 09:33:26 -0700 (Wed, 22 Apr 2009)
Log Message:
-----------
HTTP request/response logging to help with client profiling.

Modified Paths:
--------------
    CalendarServer/trunk/conf/caldavd-test.plist
    CalendarServer/trunk/twext/web2/channel/http.py
    CalendarServer/trunk/twistedcaldav/accounting.py

Modified: CalendarServer/trunk/conf/caldavd-test.plist
===================================================================
--- CalendarServer/trunk/conf/caldavd-test.plist	2009-04-22 15:50:37 UTC (rev 4058)
+++ CalendarServer/trunk/conf/caldavd-test.plist	2009-04-22 16:33:26 UTC (rev 4059)
@@ -375,6 +375,8 @@
     <dict>
       <key>iTIP</key>
       <false/>
+      <key>HTTP</key>
+      <false/>
     </dict>
     <!-- Enable accounting for specific principals -->
     <key>AccountingPrincipals</key>

Modified: CalendarServer/trunk/twext/web2/channel/http.py
===================================================================
--- CalendarServer/trunk/twext/web2/channel/http.py	2009-04-22 15:50:37 UTC (rev 4058)
+++ CalendarServer/trunk/twext/web2/channel/http.py	2009-04-22 16:33:26 UTC (rev 4059)
@@ -18,7 +18,10 @@
 
 from twisted.internet import protocol
 from twisted.python import log
-from twisted.web2.channel.http import HTTPFactory
+from twisted.web2.channel.http import HTTPFactory, HTTPChannelRequest,\
+    HTTPChannel
+from twistedcaldav import accounting
+import time
 
 __all__ = [
     "HTTP503LoggingFactory",
@@ -75,3 +78,82 @@
             setattr(p, arg, value)
 
         return p
+
+class HTTPLoggingChannelRequest(HTTPChannelRequest):
+    
+    class TransportLoggingWrapper(object):
+        
+        def __init__(self, transport, logData):
+            
+            self.transport = transport
+            self.logData = logData
+            
+        def write(self, data):
+            if self.logData is not None and data:
+                self.logData.append(data)
+            self.transport.write(data)
+            
+        def writeSequence(self, seq):
+            if self.logData is not None and seq:
+                self.logData.append(''.join(seq))
+            self.transport.writeSequence(seq)
+
+        def __getattr__(self, attr):
+            return getattr(self.__dict__['transport'], attr)
+            
+    def __init__(self, channel, queued=0):
+        
+        self.logData = [] if accounting.accountingEnabledForCategory("HTTP") else None
+        super(HTTPLoggingChannelRequest, self).__init__(channel, queued)
+        if self.logData is not None:
+            self.transport = HTTPLoggingChannelRequest.TransportLoggingWrapper(self.transport, self.logData)
+    
+    def gotInitialLine(self, initialLine):
+        
+        if self.logData is not None:
+            self.startTime = time.time()
+            self.logData.append(">>>> Request starting at: %.3f\r\n\r\n" % (self.startTime,))
+            self.logData.append("%s\r\n" % (initialLine,))
+        super(HTTPLoggingChannelRequest, self).gotInitialLine(initialLine)
+
+    def lineReceived(self, line):
+        
+        if self.logData is not None:
+            # We don't want to log basic credentials
+            loggedLine = line
+            if line.lower().startswith("authorization:"):
+                bits = line[14:].strip().split(" ")
+                if bits[0].lower() == "basic" and len(bits) == 2:
+                    loggedLine = "%s %s %s" % (line[:14], bits[0], "X" * len(bits[1]))
+            self.logData.append("%s\r\n" % (loggedLine,))
+        super(HTTPLoggingChannelRequest, self).lineReceived(line)
+
+    def handleContentChunk(self, data):
+        
+        if self.logData is not None:
+            self.logData.append(data)
+        super(HTTPLoggingChannelRequest, self).handleContentChunk(data)
+        
+    def handleContentComplete(self):
+        
+        if self.logData is not None:
+            doneTime = time.time()
+            self.logData.append("\r\n\r\n>>>> Request complete at: %.3f (elapsed: %.1f ms)" % (doneTime, 1000 * (doneTime - self.startTime),))
+        super(HTTPLoggingChannelRequest, self).handleContentComplete()
+
+    def writeHeaders(self, code, headers):
+        if self.logData is not None:
+            doneTime = time.time()
+            self.logData.append("\r\n\r\n<<<< Response sending at: %.3f (elapsed: %.1f ms)\r\n\r\n" % (doneTime, 1000 * (doneTime - self.startTime),))
+        super(HTTPLoggingChannelRequest, self).writeHeaders(code, headers)
+
+    def finish(self):
+        
+        super(HTTPLoggingChannelRequest, self).finish()
+
+        if self.logData is not None:
+            doneTime = time.time()
+            self.logData.append("\r\n\r\n<<<< Response complete at: %.3f (elapsed: %.1f ms)\r\n" % (doneTime, 1000 * (doneTime - self.startTime),))
+            accounting.emitAccounting("HTTP", "all", "".join(self.logData))
+
+HTTPChannel.chanRequestFactory = HTTPLoggingChannelRequest

Modified: CalendarServer/trunk/twistedcaldav/accounting.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/accounting.py	2009-04-22 15:50:37 UTC (rev 4058)
+++ CalendarServer/trunk/twistedcaldav/accounting.py	2009-04-22 16:33:26 UTC (rev 4059)
@@ -77,7 +77,15 @@
     @param data: data to write.
     @type data: C{str}
     """    
-    if not accountingEnabled(category, principal):
+    if isinstance(principal, str):
+        principalLogPath = principal
+    elif accountingEnabled(category, principal):
+        principalLogPath = os.path.join(
+            principal.record.guid[0:2],
+            principal.record.guid[2:4],
+            principal.record.guid
+        )
+    else:
         return
 
     try:
@@ -87,9 +95,7 @@
         logRoot = config.AccountingLogRoot
         logDirectory = os.path.join(
             logRoot,
-            principal.record.guid[0:2],
-            principal.record.guid[2:4],
-            principal.record.guid,
+            principalLogPath,
             category
         )
         logFilename = os.path.join(logDirectory, datetime.datetime.now().isoformat())
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090422/1811936f/attachment-0001.html>


More information about the calendarserver-changes mailing list