You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by pq...@apache.org on 2010/01/06 00:42:22 UTC

svn commit: r896276 - in /incubator/libcloud/trunk/libcloud: __init__.py base.py

Author: pquerna
Date: Tue Jan  5 23:42:21 2010
New Revision: 896276

URL: http://svn.apache.org/viewvc?rev=896276&view=rev
Log:
Add http tracing.  To enable either set the enviroment variable LIBCLOUD_DEBUG to a file path or 1.

You can also enable it programtically by calling libcloud.enable_debug(file_like_object)

Modified:
    incubator/libcloud/trunk/libcloud/__init__.py
    incubator/libcloud/trunk/libcloud/base.py

Modified: incubator/libcloud/trunk/libcloud/__init__.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/libcloud/__init__.py?rev=896276&r1=896275&r2=896276&view=diff
==============================================================================
--- incubator/libcloud/trunk/libcloud/__init__.py (original)
+++ incubator/libcloud/trunk/libcloud/__init__.py Tue Jan  5 23:42:21 2010
@@ -19,4 +19,30 @@
 @var __version__: Current version of libcloud
 """
 
-__version__ = "0.1.1-dev"
\ No newline at end of file
+__all__ = ["__version__", "enable_debug"]
+
+__version__ = "0.1.1-dev"
+
+
+def enable_debug(fo):
+    """
+    Enable library wide debugging to a file-like object.
+
+    @param fo: Where to append debugging information
+    @type fo: File like object, only write operations are used.
+    """
+    import httplib
+    from libcloud.base import ConnectionKey,LoggingHTTPSConnection
+    LoggingHTTPSConnection.log = fo
+    ConnectionKey.conn_classes = (httplib.HTTPConnection, LoggingHTTPSConnection)
+
+def _init_once():
+    import os
+    d = os.getenv("LIBCLOUD_DEBUG")
+    if d:
+        if d.isdigit():
+            d = "/tmp/libcloud_debug.log"
+        fo = open(d, "a")
+        enable_debug(fo)
+
+_init_once()

Modified: incubator/libcloud/trunk/libcloud/base.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/libcloud/base.py?rev=896276&r1=896275&r2=896276&view=diff
==============================================================================
--- incubator/libcloud/trunk/libcloud/base.py (original)
+++ incubator/libcloud/trunk/libcloud/base.py Tue Jan  5 23:42:21 2010
@@ -27,6 +27,7 @@
 from libcloud.interface import INodeSizeFactory, INodeSize
 from libcloud.interface import INodeImageFactory, INodeImage
 import hashlib
+import StringIO
 from pipes import quote as pquote
 
 class Node(object):
@@ -192,33 +193,74 @@
 
 #TODO: Move this to a better location/package
 class LoggingHTTPSConnection(httplib.HTTPSConnection):
-  """
-  Debug class to log all HTTP(s) requests as they could be made
-  with the C{curl} command.
-
-  @cvar logfile: Path to logfile used to log curl commands
-  """
-  logfile = "/tmp/libcloud.log"
-
-  def _to_curl(self, method, url, body, headers):
-    cmd = ["curl", "--compressed"]
-
-    cmd.extend(["-X", pquote(method)])
-
-    for h in headers:
-      cmd.extend(["-H", pquote("%s: %s" % (h, headers[h]))])
+    """
+    Debug class to log all HTTP(s) requests as they could be made
+    with the C{curl} command.
 
-    if body is not None and len(body) > 0:
-      cmd.extend(["--data-binary", pquote(body)])
-    
-    cmd.extend([pquote("https://%s:%d%s" % (self.host, self.port, url))])
-    return " ".join(cmd)
+    @cvar log: file-like object that logs entries are written to.
+    """
+    log = None
 
-  def request(self, method, url, body=None, headers=None):
-    fp = open(self.logfile, 'a')
-    fp.write(self._to_curl(method, url, body, headers) + "\n")
-    fp.close()
-    return httplib.HTTPSConnection.request(self, method, url, body, headers)
+    def _log_response(self, r):
+        rv = "# -------- begin %d response ----------\n" % (id(r))
+        ht = ""
+        v = r.version
+        if r.version == 10:
+            v = "HTTP/1.0"
+        if r.version == 11:
+            v = "HTTP/1.1"
+        ht += "%s %s %s\r\n" % (v, r.status, r.reason)
+        body = r.read()
+        for h in r.getheaders():
+            ht += "%s: %s\r\n" % (h[0].title(), h[1])
+        ht += "\r\n"
+        # this is evil. laugh with me. ha arharhrhahahaha
+        class fakesock:
+            def __init__(self, s):
+                self.s = s
+            def makefile(self, mode, foo):
+                return StringIO.StringIO(self.s)
+        rr = r
+        if r.chunked:
+            ht += "%x\r\n" % (len(body))
+            ht += body
+            ht += "\r\n0\r\n"
+        else:
+            ht += body
+        rr = httplib.HTTPResponse(fakesock(ht),
+                                    method=r._method,
+                                    debuglevel=r.debuglevel)
+        rr.begin()
+        rv += ht
+        rv += "# -------- end %d response ----------\n" % (id(r))
+        return (rr, rv)
+
+    def getresponse(self):
+        r = httplib.HTTPSConnection.getresponse(self)
+        if self.log is not None:
+            r, rv = self._log_response(r)
+            self.log.write(rv + "\n")
+        return r
+
+    def _log_curl(self, method, url, body, headers):
+        cmd = ["curl", "-i"]
+
+        cmd.extend(["-X", pquote(method)])
+
+        for h in headers:
+          cmd.extend(["-H", pquote("%s: %s" % (h, headers[h]))])
+
+        # TODO: in python 2.6, body can be a file-like object.
+        if body is not None and len(body) > 0:
+          cmd.extend(["--data-binary", pquote(body)])
+
+        cmd.extend([pquote("https://%s:%d%s" % (self.host, self.port, url))])
+        return " ".join(cmd)
+
+    def request(self, method, url, body=None, headers=None):
+        if self.log is not None:
+            self.log.write(self._log_curl(method, url, body, headers) + "\n")
+        return httplib.HTTPSConnection.request(self, method, url, body, headers)
 
 class ConnectionKey(object):
     """