Commits

dccmx committed 01fc2fc

update kids client

Comments (0)

Files changed (2)

starry/utils/kids.py

+#!/usr/bin/python
+# coding=utf-8
+import sys
+import os
+import logging
+import time
+import redis
+
+if hasattr(sys, 'frozen'):  # support for py2exe
+    _srcfile = "kids%s__init__%s" % (os.sep, __file__[-4:])
+elif __file__[-4:].lower() in ['.pyc', '.pyo']:
+    _srcfile = __file__[:-4] + '.py'
+else:
+    _srcfile = __file__
+_srcfile = os.path.normcase(_srcfile)
+
+
+def currentframe():
+    """Return the frame object for the caller's stack frame."""
+    try:
+        raise Exception
+    except:
+        return sys.exc_info()[2].tb_frame.f_back
+
+
+class Kids(redis.Redis):
+    def __init__(self, host='localhost', port=6379,
+                 db=0, password=None, socket_timeout=None,
+                 connection_pool=None,
+                 charset='utf-8', errors='strict', unix_socket_path=None, topic=None, reconnect_period=None):
+        """
+        get topic name from first not None of follow
+        1. topic param
+        2. module name prefixed by 'zhihu.'
+        3. 'zhihu.notopic'
+        """
+        self.reconnect_period = reconnect_period
+        self.last_fail_time = None
+        redis.Redis.__init__(self, host, port, db, password, socket_timeout, connection_pool, charset, errors, unix_socket_path)
+        if topic is not None:
+            self._topic = topic
+        else:
+            f = currentframe()
+            if f is not None:
+                f = f.f_back
+            pathname = None
+            while hasattr(f, "f_code"):
+                co = f.f_code
+                pathname = os.path.normcase(co.co_filename)
+                if pathname == _srcfile:
+                    f = f.f_back
+                    continue
+                break
+            try:
+                filename = os.path.basename(pathname)
+                module = 'zhihu.' + os.path.splitext(filename)[0]
+            except (TypeError, ValueError, AttributeError):
+                module = 'zhihu.notopic'
+            self._topic = module
+
+    def log(self, arg1, arg2=None):
+        if self.reconnect_period is not None and self.last_fail_time is not None:
+            if time.time() - self.last_fail_time < self.reconnect_period:
+                return
+        try:
+            if arg2 is not None:
+                self.publish(arg1, arg2)
+            else:
+                self.publish(self._topic, arg1)
+            self.last_fail_time = None
+        except redis.exceptions.ConnectionError, e:
+            self.last_fail_time = time.time()
+            raise e
+        except Exception, e:
+            self.last_fail_time = None
+            raise e
+
+
+class KidsHandler(logging.Handler):
+    def __init__(self, host='localhost', port=6379,
+                 db=0, password=None, socket_timeout=None,
+                 connection_pool=None,
+                 charset='utf-8', errors='strict', unix_socket_path=None, topic=None, reconnect_period=None):
+        logging.Handler.__init__(self)
+        self._topic = topic
+        self._kids = Kids(host, port, db, password, socket_timeout, connection_pool, charset, errors, unix_socket_path, reconnect_period)
+
+    def emit(self, record):
+        """
+        get topic name from first not None of follow
+        1. topic from extra param
+        2. handler's topic
+        3. logger's name
+        4. module name prefixed by 'zhihu.'
+        """
+        try:
+            topic = 'zhihu.' + record.module
+            if not record.name == 'root':
+                topic = record.name
+            if self._topic is not None:
+                topic = self._topic
+            if hasattr(record, 'topic'):
+                topic = record.topic
+            self._kids.log(topic, self.format(record))
+        except (KeyboardInterrupt, SystemExit):
+            raise
+        except:
+            self.handleError(record)
+
+
+if __name__ == '__main__':
+    kids = Kids(host='127.0.0.1', port=3388)
+    kids.log('测试', '测试日志')
+    logger = logging.getLogger('kids.test.logging')
+    logger.setLevel(logging.INFO)
+    logger.propagate = False  # Stop propagating to upper level (e.g. console)
+    ch = KidsHandler(host='127.0.0.1', port=3388)
+    ch.setLevel(logging.INFO)
+    ch.setFormatter(logging.Formatter('[%(levelname)s][%(asctime)s] %(name)s: %(message)s'))
+    logger.addHandler(ch)
+    logger.error('error log')
+    logger.error('error log', extra={'topic': 'kids.testing.logging'})

starry/utils/loghandler.py

 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 import logging
+from kids import Kids
+
 
 class KidsHandler(logging.Handler):
     def __init__(self, topic=None, host='localhost', port=6379, **kwargs):
         logging.Handler.__init__(self)
         self._topic = topic
-        from redis import Redis
-        self._kids = Redis(host, port, **kwargs)
+        self._kids = Kids(host, port, **kwargs)
 
     def emit(self, record):
         """