[or-cvs] r12849: Add python logging support, better message templates, and su (in bridgedb/trunk: . lib/bridgedb)

nickm at seul.org nickm at seul.org
Tue Dec 18 03:34:02 UTC 2007


Author: nickm
Date: 2007-12-17 22:34:02 -0500 (Mon, 17 Dec 2007)
New Revision: 12849

Modified:
   bridgedb/trunk/
   bridgedb/trunk/bridgedb.conf
   bridgedb/trunk/lib/bridgedb/Bridges.py
   bridgedb/trunk/lib/bridgedb/Dist.py
   bridgedb/trunk/lib/bridgedb/Main.py
   bridgedb/trunk/lib/bridgedb/Server.py
Log:
 r17219 at catbus:  nickm | 2007-12-17 22:33:55 -0500
 Add python logging support, better message templates, and support for partially empty rings.



Property changes on: bridgedb/trunk
___________________________________________________________________
 svk:merge ticket from /bridgedb/trunk [r17219] on 8246c3cf-6607-4228-993b-4d95d33730f1

Modified: bridgedb/trunk/bridgedb.conf
===================================================================
--- bridgedb/trunk/bridgedb.conf	2007-12-18 03:34:00 UTC (rev 12848)
+++ bridgedb/trunk/bridgedb.conf	2007-12-18 03:34:02 UTC (rev 12849)
@@ -9,6 +9,11 @@
 # Either a file in which to write our pid, or None
 PIDFILE = "bridgedb.pid"
 
+# Either a file to log to, or None if we should log to the console.
+LOGFILE = "bridgedb.log"
+# One of "DEBUG", "INFO", "WARNING", "ERROR"...
+LOGLEVEL = "INFO"
+
 # Files from which we read descriptors on start and SIGHUP
 # XXXX SIGHUP not implemented.
 BRIDGE_FILES = [ "./cached-descriptors", "./cached-descriptors.new" ]

Modified: bridgedb/trunk/lib/bridgedb/Bridges.py
===================================================================
--- bridgedb/trunk/lib/bridgedb/Bridges.py	2007-12-18 03:34:00 UTC (rev 12848)
+++ bridgedb/trunk/lib/bridgedb/Bridges.py	2007-12-18 03:34:02 UTC (rev 12849)
@@ -5,6 +5,7 @@
 import binascii
 import bisect
 import hmac
+import logging
 import re
 import sha
 import socket
@@ -153,6 +154,7 @@
         self.hmac = get_hmac_fn(key, hex=False)
         self.isSorted = False
         self.sortedKeys = []
+        self.name = "Ring"
 
     def __len__(self):
         return len(self.bridgesByID)
@@ -165,6 +167,7 @@
             self.isSorted = False
         self.bridges[pos] = bridge
         self.bridgesByID[id] = bridge
+        logging.debug("Adding %s to %s", bridge.getConfigLine(), self.name)
 
     def sort(self):
         if not self.isSorted:
@@ -270,7 +273,7 @@
 
 class UnallocatedHolder(BridgeHolder):
     def insert(self, bridge):
-        pass
+        logging.debug("Leaving %s unallocated", bridge.getConfigLine())
 
     def assignmentsArePersistent(self):
         return False

Modified: bridgedb/trunk/lib/bridgedb/Dist.py
===================================================================
--- bridgedb/trunk/lib/bridgedb/Dist.py	2007-12-18 03:34:00 UTC (rev 12848)
+++ bridgedb/trunk/lib/bridgedb/Dist.py	2007-12-18 03:34:02 UTC (rev 12849)
@@ -4,6 +4,7 @@
 
 import bridgedb.Bridges
 
+import logging
 import re
 import socket
 
@@ -24,6 +25,7 @@
         for n in xrange(nClusters):
             key1 = bridgedb.Bridges.get_hmac(key, "Order-Bridges-In-Ring-%d"%n)
             self.rings.append( bridgedb.Bridges.BridgeRing(key1) )
+            self.rings[-1].name = "IP ring %s"%len(self.rings)
 
         key2 = bridgedb.Bridges.get_hmac(key, "Assign-Bridges-To-Rings")
         self.splitter = bridgedb.Bridges.FixedBridgeSplitter(key2, self.rings)
@@ -38,20 +40,25 @@
         self.splitter.insert(bridge)
 
     def getBridgesForIP(self, ip, epoch, N=1):
+        if not len(self.splitter):
+            return []
+
         area = self.areaMapper(ip)
 
         # Which bridge cluster should we look at?
-        h = int( self.areaClusterHmac(area)[:8], 16 )
+        h = int( self.areaClusterHmac(area)[:8], 16)
         clusterNum = h % len(self.rings)
         ring = self.rings[clusterNum]
+        # If a ring is empty, consider the next.
+        while not len(ring):
+            clusterNum = (clusterNum + 1) % len(self.rings)
+            ring = self.rings[clusterNum]
 
         # Now get the bridge.
         pos = self.areaOrderHmac("<%s>%s" % (epoch, area))
         return ring.getBridges(pos, N)
 
 
-
-
 # These characters are the ones that RFC2822 allows.
 #ASPECIAL = '!#$%&*+-/=?^_`{|}~'
 #ASPECIAL += "\\\'"
@@ -129,6 +136,7 @@
 
         key2 = bridgedb.Bridges.get_hmac(key, "Order-Bridges-In-Ring")
         self.ring = bridgedb.Bridges.BridgeRing(key2)
+        self.ring.name = "email ring"
         self.store = store
         self.domainmap = domainmap
 
@@ -141,8 +149,11 @@
             return [] #XXXX raise an exception.
         if self.store.has_key(emailaddress):
             result = []
-            ids = self.store[emailaddress]
-            for id in bridgedb.Bridges.chopString(ids, bridgedb.Bridges.ID_LEN):
+            ids_str = self.store[emailaddress]
+            ids = bridgedb.Bridges.chopString(ids_str, bridgedb.Bridges.ID_LEN)
+            logging.info("We've seen %r before. Sending the same %d bridges"
+                         " as last time", emailaddress, len(ids))
+            for id in ids:
                 b = self.ring.getBridgeByID(id)
                 if b != None:
                     result.append(b)
@@ -165,4 +176,3 @@
             print normal
         except BadEmail, e:
             print line, e
-        

Modified: bridgedb/trunk/lib/bridgedb/Main.py
===================================================================
--- bridgedb/trunk/lib/bridgedb/Main.py	2007-12-18 03:34:00 UTC (rev 12848)
+++ bridgedb/trunk/lib/bridgedb/Main.py	2007-12-18 03:34:02 UTC (rev 12849)
@@ -6,6 +6,7 @@
 import os
 import signal
 import sys
+import logging
 
 from twisted.internet import reactor
 
@@ -22,6 +23,9 @@
     RUN_IN_DIR = ".",
 
     PIDFILE = "bridgedb.pid",
+    LOGFILE = None,
+    LOGLEVEL = "DEBUG",
+
     BRIDGE_FILES = [ "./cached-descriptors", "./cached-descriptors.new" ],
     BRIDGE_PURPOSE = "bridge",
     DB_FILE = "./bridgedist.db",
@@ -53,6 +57,18 @@
     RESERVED_SHARE=2,
   )
 
+def configureLogging(cfg):
+    level = getattr(cfg, 'LOGLEVEL', 'WARNING')
+    level = getattr(logging, level)
+    extra = {}
+    if getattr(cfg, "LOGFILE"):
+        extra['filename'] = cfg.LOGFILE
+
+    logging.basicConfig(format='%(asctime)s [%(levelname)s] %(message)s',
+                        datefmt="%b %d %H:%M:%S",
+                        level=level,
+                        **extra)
+
 def getKey(fname):
     """Load the key stored in fname, or create a new 32-byte key and store
        it in fname.
@@ -97,7 +113,7 @@
 def startup(cfg):
     cfg.BRIDGE_FILES = [ os.path.expanduser(fn) for fn in cfg.BRIDGE_FILES ]
     for key in ("RUN_IN_DIR", "DB_FILE", "DB_LOG_FILE", "MASTER_KEY_FILE",
-                "HTTPS_CERT_FILE", "HTTPS_KEY_FILE", "PIDFILE"):
+                "HTTPS_CERT_FILE", "HTTPS_KEY_FILE", "PIDFILE", "LOGFILE"):
         v = getattr(cfg, key)
         if v:
             setattr(cfg, key, os.path.expanduser(v))
@@ -110,6 +126,8 @@
         f.write("%s\n"%os.getpid())
         f.close()
 
+    configureLogging(cfg)
+
     key = getKey(cfg.MASTER_KEY_FILE)
     dblogfile = None
     emailDistributor = ipDistributor = None
@@ -149,14 +167,15 @@
                                   Bridges.PrefixStore(store, "ls|"))
     splitter.addTracker(stats)
 
-    print "Loading bridges"
+    logging.info("Loading bridges")
     load(cfg, splitter)
-    print "%d bridges loaded" % len(splitter)
+    logging.info("%d bridges loaded", len(splitter))
     if emailDistributor:
-        print "%d for email" % len(emailDistributor.ring)
+        logging.info("%d for email", len(emailDistributor.ring))
     if ipDistributor:
-        print "%d for web:" % len(ipDistributor.splitter)
-        print "  by location set:", " ".join(str(len(r)) for r in ipDistributor.rings)
+        logging.info("%d for web:", len(ipDistributor.splitter))
+        logging.info("  by location set: %s",
+                     " ".join(str(len(r)) for r in ipDistributor.rings))
 
     if cfg.HTTPS_DIST and cfg.HTTPS_SHARE:
         Server.addWebServer(cfg, ipDistributor, webSchedule)
@@ -172,7 +191,7 @@
     signal.signal(signal.SIGHUP, _handleSIGHUP)
 
     try:
-        print "Starting reactors."
+        logging.info("Starting reactors.")
         Server.runServers()
     finally:
         baseStore.close()

Modified: bridgedb/trunk/lib/bridgedb/Server.py
===================================================================
--- bridgedb/trunk/lib/bridgedb/Server.py	2007-12-18 03:34:00 UTC (rev 12848)
+++ bridgedb/trunk/lib/bridgedb/Server.py	2007-12-18 03:34:02 UTC (rev 12849)
@@ -82,6 +82,7 @@
         else:
             answer = "No bridges available."
 
+        logging.info("Replying to web request from %s", ip)
         return HTML_MESSAGE_TEMPLAY % answer
 
 def addWebServer(cfg, dist, sched):
@@ -125,13 +126,14 @@
     elif clientFromAddr and clientFromAddr[1]:
         clientAddr = clientFromAddr[1]
     else:
-        print "No from header. WTF."
+        logging.info("No From or Sender header on incoming mail.")
         return None,None
     for ln in lines:
         if ln.strip().lower() in ("get bridges", "subject: get bridges"):
             break
     else:
-        print "No request for bridges."
+        logging.info("Got a mail from %r with no bridge request; dropping",
+                     clientAddr)
         return None,None
 
     try:
@@ -139,10 +141,11 @@
         bridges = ctx.distributor.getBridgesForEmail(clientAddr,
                                                      interval, ctx.N)
     except bridgedb.Dist.BadEmail, e:
-        print "Bad email addr in request: %s"%e
+        logging.info("Got a mail from a bad email address %r: %s.",
+                     clientAddr, e)
         return None, None
     if not bridges:
-        print "No bridges available."
+        logging.warning("No bridges available to send to %r", clientAddr)
         return None, None
 
     # Generate the message.
@@ -164,7 +167,7 @@
     return clientAddr, f
 
 def replyToMail(lines, ctx):
-    print "Got complete email; attempting to reply."
+    logging.info("Got a completed email; attempting to reply.")
     sendToUser, response = getMailResponse(lines, ctx)
     if response is None:
         return
@@ -176,7 +179,7 @@
         response,
         d)
     reactor.connectTCP(ctx.smtpServer, ctx.smtpPort, factory)
-    print "Sending reply."
+    logging.info("Sending reply to %r", sendToUser)
     return d
 
 class MailContext:



More information about the tor-commits mailing list