[CalendarServer-changes] [2319] CalendarServer/branches/users/wsanchez/logging/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Wed Apr 16 12:19:33 PDT 2008


Revision: 2319
          http://trac.macosforge.org/projects/calendarserver/changeset/2319
Author:   wsanchez at apple.com
Date:     2008-04-16 12:19:33 -0700 (Wed, 16 Apr 2008)

Log Message:
-----------
First pass at level-based logging support.

Added Paths:
-----------
    CalendarServer/branches/users/wsanchez/logging/twistedcaldav/log.py
    CalendarServer/branches/users/wsanchez/logging/twistedcaldav/test/test_log.py

Added: CalendarServer/branches/users/wsanchez/logging/twistedcaldav/log.py
===================================================================
--- CalendarServer/branches/users/wsanchez/logging/twistedcaldav/log.py	                        (rev 0)
+++ CalendarServer/branches/users/wsanchez/logging/twistedcaldav/log.py	2008-04-16 19:19:33 UTC (rev 2319)
@@ -0,0 +1,120 @@
+##
+# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+"""
+Classes and functions to do better logging.
+
+Example usage in a module:
+
+    from twistedcaldav.log import Logger
+    log = Logger()
+
+    log.info("Blah blah")
+
+Or in a class:
+
+    from twistedcaldav.log import LoggingMixIn
+
+    class Foo (object, LoggingMixIn):
+        def oops(self):
+            self.error("Oops!")
+"""
+
+__all__ = [
+    "logLevels",
+    "Logger",
+    "LoggingMixIn",
+]
+
+import inspect
+
+from twisted.python import log
+
+logLevels = (
+    "debug",
+    "info",
+    "warn",
+    "error",
+)
+
+logLevelIndexes = dict(zip(logLevels, xrange(0, len(logLevels))))
+
+class Logger (object):
+    """
+    Logging object.
+    """
+    def __init__(self, namespace=None):
+        """
+        @param namespace: The namespace for this logger.  Uses a
+            dotted notation, as used by python modules.  If not
+            C{None}, then the name of the module of the caller
+            is used.
+        """
+        if namespace is None:
+            currentFrame = inspect.currentframe()
+            callerFrame  = currentFrame.f_back
+            callerModule = callerFrame.f_globals["__name__"]
+
+            namespace = callerModule
+
+        self.namespace = namespace
+
+    def emit(self, level, message, **kwargs):
+        log.msg(
+            str(message),
+            isError = (level == "error"),
+            level = level,
+            namespace = self.namespace,
+            **kwargs
+        )
+
+class LoggingMixIn (object):
+    """
+    Mix-in class for logging methods.
+    """
+    def _getLogger(self):
+        try:
+            return self._logger
+        except AttributeError:
+            namespace = repr(self.__class__)[8:-2]
+
+            assert repr(self.__class__)[:8] == "<class '"
+            assert repr(self.__class__)[-2:] == "'>"
+            assert namespace.find("'") == -1
+
+            self._logger = Logger(namespace)
+
+        return self._logger
+
+    def _setLogger(self, value):
+        self._logger = value
+
+    logger = property(_getLogger, _setLogger)
+
+for level in logLevels:
+    def log_level(self, message, level=level, **kwargs):
+        self.emit(level, message, **kwargs)
+    setattr(Logger, level, log_level)
+
+    def log_level(self, message, level=level, **kwargs):
+        self.logger.emit(level, message, **kwargs)
+    setattr(LoggingMixIn, "log_%s" % (level,), log_level)
+
+del level, log_level
+
+# Add some compatibility with twisted's log module
+Logger.msg = Logger.info
+Logger.err = Logger.error

Added: CalendarServer/branches/users/wsanchez/logging/twistedcaldav/test/test_log.py
===================================================================
--- CalendarServer/branches/users/wsanchez/logging/twistedcaldav/test/test_log.py	                        (rev 0)
+++ CalendarServer/branches/users/wsanchez/logging/twistedcaldav/test/test_log.py	2008-04-16 19:19:33 UTC (rev 2319)
@@ -0,0 +1,75 @@
+##
+# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from twistedcaldav.log import Logger, LoggingMixIn, logLevels
+
+import twisted.trial.unittest
+
+class TestLogger (Logger):
+    def __init__(self, namespace=None, test_emit=None):
+        super(TestLogger, self).__init__(namespace)
+        self._test_emit = test_emit
+
+    def emit(self, level, message, **kwargs):
+        if self._test_emit is not None:
+            self._test_emit(level, message, **kwargs)
+        super(TestLogger, self).emit(level, message, **kwargs)
+
+class LoggingEnabledObject (LoggingMixIn):
+    pass
+
+class Logging (twisted.trial.unittest.TestCase):
+    def test_namespace_default(self):
+        """
+        Default namespace is module name.
+        """
+        log = Logger()
+        self.assertEquals(log.namespace, __name__)
+
+    def test_namespace_mixin(self):
+        """
+        Default namespace for classes using L{LoggingMixIn} is the class name.
+        """
+        object = LoggingEnabledObject()
+        self.assertEquals(object.logger.namespace, "twistedcaldav.test.test_log.LoggingEnabledObject")
+
+    def test_basic(self):
+        """
+        Test that log levels and messages are emitted correctly.
+        Tests both Logger and LoggingMixIn.
+        """
+        object = LoggingEnabledObject()
+
+        for level in logLevels:
+            message = "This is a %s message" % (level,)
+
+            def test_emit(emit_level, emit_message, **kwargs):
+                emitted["level"  ] = emit_level
+                emitted["message"] = emit_message
+                emitted["junk"   ] = kwargs["junk"]
+
+            log = TestLogger(test_emit=test_emit)
+            object.logger = log
+
+            for method in (getattr(log, level), getattr(object, "log_" + level)):
+                emitted = {}
+
+                method(message, junk=message)
+
+                # Ensure that test_emit got called with expected arguments
+                self.failUnless(emitted["level"  ] == level  )
+                self.failUnless(emitted["message"] == message)
+                self.failUnless(emitted["junk"   ] == message)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080416/329a6b1e/attachment.html


More information about the calendarserver-changes mailing list