def install_handler(self): logger = logging.getLogger(self._logger_name) self._handler = ThreadBufferedHandler() logger.addHandler(self._handler)
class FirePythonBase(object): FIREPYTHON_UA = re.compile(r'\sX-FirePython/(?P<ver>[0-9\.]+)', re.IGNORECASE) FIREPYTHON_HEADER = re.compile(r'^FirePython', re.IGNORECASE) DEEP_LOCALS = True JSONPICKLE_DEPTH = 8 def __init__(self): raise NotImplementedError("Must be subclassed") def install_handler(self): logger = logging.getLogger(self._logger_name) self._handler = ThreadBufferedHandler() logger.addHandler(self._handler) def uninstall_handler(self): if self._handler is None: return logger = logging.getLogger(self._logger_name) logger.removeHandler(self._handler) self._handler = None def _ua_check(self, user_agent): check = self.FIREPYTHON_UA.search(user_agent) if not check: return False version = check.group('ver') if firepython.__version__ != version: logging.warning('FireBug part of FirePython is version %s, but Python part is %s', version, firepython.__version__) return True def _password_check(self, token): if self._password is None: raise Exception("self._password must be set!") return firepython.utils.get_auth_token(self._password) == token def _encode(self, data): data = jsonpickle.encode(data, unpicklable=False, max_depth=self.JSONPICKLE_DEPTH) data = data.encode('utf-8') data = base64.encodestring(data) return data.splitlines() def republish(self, headers): firepython_headers = [] for key, value in headers.iteritems(): if self.FIREPYTHON_HEADER.match(key): firepython_headers.append((key, value)) self._handler.republish(firepython_headers) def _flush_records(self, add_header): """ Flush collected logs into response. Argument ``add_header`` should be a function receiving two arguments: ``name`` and ``value`` of header. """ records = self._handler.get_records() self._handler.clear_records() republished = self._handler.get_republished() self._handler.clear_republished() for name, value in republished: add_header(name, value) logs = [] for record in records: logs.append(self._prepare_log_record(record)) chunks = self._encode({"logs": logs}) guid = "%08x" % random.randint(0,0xFFFFFFFF) for i, chunk in enumerate(chunks): add_header('FirePython-%s-%d' % (guid, i), chunk) def _prepare_log_record(self, record): data = { "level": self._log_level(record.levelno), "message": self._handler.format(record), "template": record.msg, "timestamp": long(record.created * 1000 * 1000), "time": (time.strftime("%H:%M:%S", time.localtime(record.created)) + (".%03d" % ((record.created - long(record.created)) * 1000))) } props = ["args", "pathname", "lineno", "exc_text", "name", "process", "thread", "threadName"] for p in props: try: data[p] = getattr(record, p) except AttributeError: pass try: exc_info = getattr(record, 'exc_info') if exc_info is not None: exc_type = exc_info[0] exc_value = exc_info[1] exc_traceback = exc_info[2] if exc_traceback is not None: exc_traceback = traceback.extract_tb(exc_traceback) data['exc_info'] = (exc_type, exc_value, exc_traceback) frames = [] t = exc_info[2] while t: try: d = {} for k,v in t.tb_frame.f_locals.iteritems(): if self.DEEP_LOCALS: d[unicode(k)] = v else: d[unicode(k)] = repr(v) frames.append(d) except: frames.append('?') t = t.tb_next data['exc_frames'] = frames except AttributeError: pass return data def _log_level(self, level): if level >= logging.CRITICAL: return "critical" elif level >= logging.ERROR: return "error" elif level >= logging.WARNING: return "warning" elif level >= logging.INFO: return "info" else: return "debug" def _start(self): self._handler.start() def _finish(self): self._handler.finish()
class FirePythonBase(object): FIREPYTHON_UA = re.compile(r'\sX-FirePython/(?P<ver>[0-9\.]+)') def __init__(self): raise NotImplementedError("Must be subclassed") def install_handler(self): logger = logging.getLogger(self._logger_name) self._handler = ThreadBufferedHandler() logger.addHandler(self._handler) def uninstall_handler(self): if self._handler is None: return logger = logging.getLogger(self._logger_name) logger.removeHandler(self._handler) self._handler = None def _ua_check(self, user_agent): check = self.FIREPYTHON_UA.search(user_agent) if not check: return False version = check.group('ver') if firepython.__version__ != version: logging.warning('FireBug part of FirePython is version %s, but Python part is %s', version, firepython.__version__) return True def _password_check(self, password): if self._password is None: raise Exception("self._password must be set!") return md5('#FirePythonPassword#%s#' % self._password).hexdigest() == password def _encode(self, data): data = jsonpickle.encode(data, unpicklable=False) data = data.encode('utf-8') data = base64.encodestring(data) return data.splitlines() def _flush_records(self, add_header): """ Flush collected logs into response. Argument ``add_header`` should be a function receiving two arguments: ``name`` and ``value`` of header. """ records = self._handler.get_records() self._handler.clear_records() logs = [] for record in records: logs.append(self._prepare_log_record(record)) chunks = self._encode({"logs": logs}) for i, chunk in enumerate(chunks): add_header('FirePython-%d' % i, chunk) def _prepare_log_record(self, record): data = { "level": self._log_level(record.levelno), "message": self._handler.format(record), "template": record.msg, "timestamp": long(record.created * 1000 * 1000), "time": (time.strftime("%H:%M:%S", time.localtime(record.created)) + (".%03d" % ((record.created - long(record.created)) * 1000))) } props = ["args", "pathname", "lineno", "exc_text", "name", "process", "thread", "threadName"] for p in props: try: data[p] = getattr(record, p) except AttributeError: pass try: exc_info = getattr(record, 'exc_info') if exc_info is not None: exc_type = exc_info[0] exc_value = exc_info[1] exc_traceback = exc_info[2] if exc_traceback is not None: exc_traceback = traceback.extract_tb(exc_traceback) data['exc_info'] = (exc_type, exc_value, exc_traceback) except AttributeError: pass return data def _log_level(self, level): if level >= logging.CRITICAL: return "critical" elif level >= logging.ERROR: return "error" elif level >= logging.WARNING: return "warning" elif level >= logging.INFO: return "info" else: return "debug" def _start(self): self._handler.start() def _finish(self): self._handler.finish()