Changeset 3251
- Timestamp:
- 07/11/07 17:40:45 (1 year ago)
- Files:
-
- branches/1.1/turbogears/visit/api.py (modified) (14 diffs)
- branches/1.1/turbogears/visit/savisit.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/1.1/turbogears/visit/api.py
r2961 r3251 8 8 import pkg_resources 9 9 from cherrypy.filters.basefilter import BaseFilter 10 11 10 import turbogears 12 11 13 14 12 log = logging.getLogger("turbogears.visit") 15 13 16 14 # Global VisitManager 17 _manager = None15 _manager = None 18 16 19 17 # Global list of plugins for the Visit Tracking framework 20 _plugins = []18 _plugins = list() 21 19 22 20 # Accessor functions for getting and setting the current visit information. 23 21 def current(): 24 22 ''' 25 Retrieve the current visit record. 26 ''' 27 return getattr( cherrypy.request, "tg_visit", None ) 28 29 def set_current( visit ): 30 ''' 31 Set the current visit record. 32 ''' 33 cherrypy.request.tg_visit= visit 34 23 Retrieve the current visit record from the cherrypy request. 24 ''' 25 return getattr(cherrypy.request, "tg_visit", None) 26 27 def set_current(visit): 28 ''' 29 Set the current visit record on the cherrypy request being processed. 30 ''' 31 cherrypy.request.tg_visit = visit 35 32 36 33 def _create_visit_manager(timeout): … … 38 35 Create a VisitManager based on the plugin specified in the config file. 39 36 ''' 40 plugin_name = turbogears.config.get( "visit.manager", "sqlobject")41 plugins = pkg_resources.iter_entry_points("turbogears.visit.manager",42 plugin_name )43 44 log.debug( "Loading visit manager from plugin: %s", plugin_name)37 plugin_name = turbogears.config.get("visit.manager", "sqlobject") 38 plugins = pkg_resources.iter_entry_points("turbogears.visit.manager", 39 plugin_name) 40 41 log.debug("Loading visit manager from plugin: %s", plugin_name) 45 42 46 43 for entrypoint in plugins: 47 plugin = entrypoint.load()48 return plugin( timeout)49 50 raise RuntimeError( "VisitManager plugin missing: %s" % plugin_name)44 plugin = entrypoint.load() 45 return plugin(timeout) 46 47 raise RuntimeError("VisitManager plugin missing: %s" % plugin_name) 51 48 52 49 # Interface for the TurboGears extension 53 50 def start_extension(): 54 51 # Bail out if the application hasn't enabled this extension 55 if not turbogears.config.get( "visit.on", False):52 if not turbogears.config.get("visit.on", False): 56 53 return 57 54 # Bail out if this extension is already running … … 59 56 if _manager: 60 57 return 61 log.info( "Visit Tracking starting" ) 58 59 log.info("Visit Tracking starting") 62 60 # How long may the visit be idle before a new visit ID is assigned? 63 61 # The default is 20 minutes. 64 timeout = timedelta( minutes=turbogears.config.get( "visit.timeout", 20 ))62 timeout = timedelta(minutes=turbogears.config.get("visit.timeout", 20)) 65 63 # Create the thread that manages updating the visits 66 _manager = _create_visit_manager( timeout)67 68 filter = VisitFilter()64 _manager = _create_visit_manager(timeout) 65 66 filter = VisitFilter() 69 67 # Temporary until tg-admin can call create_extension_model 70 68 create_extension_model() 71 69 # Install Filter into the root filter chain 72 70 if not hasattr(cherrypy.root, "_cp_filters"): 73 cherrypy.root._cp_filters = []74 cherrypy.root._cp_filters.append( filter ) 75 71 cherrypy.root._cp_filters = list() 72 73 cherrypy.root._cp_filters.append(filter) 76 74 77 75 def shutdown_extension(): … … 80 78 if not _manager: 81 79 return 82 log.info( "Visit Tracking shutting down")80 log.info("Visit Tracking shutting down") 83 81 _manager.shutdown() 84 82 _manager = None 85 86 83 87 84 def create_extension_model(): … … 90 87 _manager.create_model() 91 88 92 93 def enable_visit_plugin( plugin ): 89 def enable_visit_plugin(plugin): 94 90 ''' 95 91 Register a visit tracking plugin. These plugins will be called for each 96 92 request. 97 93 ''' 98 _plugins.append( plugin ) 99 94 _plugins.append(plugin) 100 95 101 96 class Visit(object): … … 103 98 Basic container for visit related data. 104 99 ''' 105 def __init__( self, key, is_new ): 106 self.key= key 107 self.is_new= is_new 108 100 def __init__(self, key, is_new): 101 self.key = key 102 self.is_new = is_new 109 103 110 104 class VisitFilter(BaseFilter): … … 113 107 ''' 114 108 115 def __init__( self):116 log.info( "Visit filter initialised")117 get =turbogears.config.get109 def __init__(self): 110 log.info("Visit filter initialised") 111 get = turbogears.config.get 118 112 119 113 # Get the name to use for the identity cookie. 120 self.cookie_name = get( "visit.cookie.name", "tg-visit" ) 121 # The path should probably default to whatever the root is masquerading 122 # as in the event of a virtual path filter. 123 self.cookie_path= get( "visit.cookie.path", "/" ) 114 self.cookie_name = get("visit.cookie.name", "tg-visit") 115 # TODO: The path should probably default to whatever 116 # the root is masquerading as in the event of a 117 # virtual path filter. 118 self.cookie_path = get("visit.cookie.path", "/") 124 119 # The secure bit should be set for HTTPS only sites 125 self.cookie_secure = get( "visit.cookie.secure", False)120 self.cookie_secure = get("visit.cookie.secure", False) 126 121 # By default, I don't specify the cookie domain. 127 self.cookie_domain = get( "visit.cookie.domain", None)128 assert self.cookie_domain !="localhost", \122 self.cookie_domain = get("visit.cookie.domain", None) 123 assert self.cookie_domain != "localhost", \ 129 124 "localhost is not a valid value for visit.cookie.domain. Try None instead." 130 125 … … 134 129 an existing visit. 135 130 ''' 136 if not turbogears.config.get( "visit.on", True):137 set_current( None)131 if not turbogears.config.get("visit.on", True): 132 set_current(None) 138 133 return 139 134 140 visit= None 141 cookies= cherrypy.request.simple_cookie 142 if self.cookie_name in cookies: 143 # Process visit based on cookie 144 visit_key= cookies[self.cookie_name].value 145 visit= _manager.visit_for_key( visit_key ) 135 visit = current() 136 cookies = cherrypy.request.simple_cookie 146 137 147 138 if not visit: 148 visit_key=self._generate_key() 149 visit= _manager.new_visit_with_key( visit_key ) 150 self.send_cookie( visit_key ) 151 152 set_current( visit ) 139 if self.cookie_name in cookies: 140 # Process visit based on cookie 141 visit_key = cookies[self.cookie_name].value 142 visit = _manager.visit_for_key(visit_key) 143 144 if not visit: 145 visit_key = self._generate_key() 146 visit = _manager.new_visit_with_key(visit_key) 147 self.send_cookie(visit_key) 148 149 set_current(visit) 153 150 154 151 # Inform all the plugins that a request has been made for the current … … 157 154 try: 158 155 for plugin in _plugins: 159 plugin.record_request( visit ) 156 plugin.record_request(visit) 157 160 158 except cherrypy.InternalRedirect, e: 161 159 # Can't allow an InternalRedirect here because CherryPy is dumb, 162 160 # instead change cherrypy.request.object_path to the url desired. 163 cherrypy.request.object_path = e.path161 cherrypy.request.object_path = e.path 164 162 165 163 def _generate_key(self): … … 176 174 return sha.new(key_string).hexdigest() 177 175 178 def clear_cookie( self):176 def clear_cookie(self): 179 177 ''' 180 178 Clear any existing visit ID cookie. … … 183 181 184 182 # clear the cookie 185 log.debug( "Clearing visit ID cookie")186 cookies[self.cookie_name] = ''187 cookies[self.cookie_name]['path'] = self.cookie_path188 cookies[self.cookie_name]['expires'] = 0189 190 def send_cookie( self, visit_key):183 log.debug("Clearing visit ID cookie") 184 cookies[self.cookie_name] = '' 185 cookies[self.cookie_name]['path'] = self.cookie_path 186 cookies[self.cookie_name]['expires'] = 0 187 188 def send_cookie(self, visit_key): 191 189 ''' 192 190 Send an visit ID cookie back to the browser. 193 191 ''' 194 cookies = cherrypy.response.simple_cookie195 cookies[self.cookie_name] = visit_key196 cookies[self.cookie_name]['path'] = self.cookie_path192 cookies = cherrypy.response.simple_cookie 193 cookies[self.cookie_name] = visit_key 194 cookies[self.cookie_name]['path'] = self.cookie_path 197 195 if self.cookie_secure: 198 cookies[self.cookie_name]['secure']= True 196 cookies[self.cookie_name]['secure'] = True 197 199 198 if self.cookie_domain: 200 cookies[self.cookie_name]['domain']= self.cookie_domain 201 log.debug( "Sending visit ID cookie: %s", 202 cookies[self.cookie_name].output() ) 199 cookies[self.cookie_name]['domain'] = self.cookie_domain 200 201 log.debug("Sending visit ID cookie: %s", 202 cookies[self.cookie_name].output()) 203 203 204 204 205 205 class BaseVisitManager(threading.Thread): 206 206 def __init__(self, timeout): 207 super(BaseVisitManager,self).__init__( name="VisitManager")208 self.timeout = timeout209 self.queue = dict()210 self.lock = threading.Lock()211 self._shutdown = threading.Event()212 self.interval = 30207 super(BaseVisitManager,self).__init__(name="VisitManager") 208 self.timeout = timeout 209 self.queue = dict() 210 self.lock = threading.Lock() 211 self._shutdown = threading.Event() 212 self.interval = 30 213 213 self.setDaemon(True) 214 214 self.start() … … 239 239 try: 240 240 self.lock.acquire() 241 self.queue[visit_key] = expiry241 self.queue[visit_key] = expiry 242 242 finally: 243 243 self.lock.release() … … 245 245 def shutdown(self, timeout=None): 246 246 self._shutdown.set() 247 self.join( timeout)247 self.join(timeout) 248 248 if self.isAlive(): 249 log.error( "Visit Manager thread failed to shutdown.")249 log.error("Visit Manager thread failed to shutdown.") 250 250 251 251 def run(self): … … 258 258 queue = self.queue.copy() 259 259 self.queue.clear() 260 260 261 finally: 261 262 self.lock.release() 263 262 264 if queue is not None: 263 265 self.update_queued_visits(queue) 266 264 267 self._shutdown.wait(self.interval) 265 268 branches/1.1/turbogears/visit/savisit.py
r2802 r3251 36 36 expiry=datetime.now()+self.timeout) 37 37 session.save(visit) 38 session.flush() 38 39 return Visit(visit_key, True) 39 40