From 155cb48bca9b66fa5188e5c1c63adf696cd6d127 Mon Sep 17 00:00:00 2001
From: Akihiro MOTOKI <motoki@da.jp.nec.com>
Date: Sat, 7 Sep 2013 02:10:57 +0900
Subject: [PATCH] Make neutron.common.log.log print module path

Closes-Bug: #1221663

neutron.common.log.log is useful for logging arguments of a method.
It outputs class name and method name, but module path is not output.
A module path is useful to search the log message.

Change-Id: Ic2903da750cc13980d5cdee153bb079f7d4ee122
---
 neutron/common/log.py                 |  5 +-
 neutron/tests/unit/test_common_log.py | 70 +++++++++++++++++++++++++++
 2 files changed, 73 insertions(+), 2 deletions(-)
 create mode 100644 neutron/tests/unit/test_common_log.py

diff --git a/neutron/common/log.py b/neutron/common/log.py
index fcc57b896ac..85e4dce80d7 100644
--- a/neutron/common/log.py
+++ b/neutron/common/log.py
@@ -25,10 +25,11 @@ def log(method):
     """Decorator helping to log method calls."""
     def wrapper(*args, **kwargs):
         instance = args[0]
-        data = {"class_name": instance.__class__.__name__,
+        data = {"class_name": (instance.__class__.__module__ + '.'
+                               + instance.__class__.__name__),
                 "method_name": method.__name__,
                 "args": args[1:], "kwargs": kwargs}
         LOG.debug(_('%(class_name)s method %(method_name)s'
-                    ' called with arguments %(args)s %(kwargs)s '), data)
+                    ' called with arguments %(args)s %(kwargs)s'), data)
         return method(*args, **kwargs)
     return wrapper
diff --git a/neutron/tests/unit/test_common_log.py b/neutron/tests/unit/test_common_log.py
new file mode 100644
index 00000000000..318613a1b5b
--- /dev/null
+++ b/neutron/tests/unit/test_common_log.py
@@ -0,0 +1,70 @@
+# Copyright (c) 2013 OpenStack Foundation.
+#
+#    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.
+
+import mock
+
+from neutron.common import log as call_log
+from neutron.tests import base
+
+
+MODULE_NAME = 'neutron.tests.unit.test_common_log'
+
+
+class TargetKlass(object):
+
+    @call_log.log
+    def test_method(self, arg1, arg2, *args, **kwargs):
+        pass
+
+
+class TestCallLog(base.BaseTestCase):
+    def setUp(self):
+        super(TestCallLog, self).setUp()
+        self.klass = TargetKlass()
+        self.expected_format = ('%(class_name)s method %(method_name)s '
+                                'called with arguments %(args)s %(kwargs)s')
+        self.expected_data = {'class_name': MODULE_NAME + '.TargetKlass',
+                              'method_name': 'test_method',
+                              'args': (),
+                              'kwargs': {}}
+
+    def test_call_log_all_args(self):
+        self.expected_data['args'] = (10, 20)
+        with mock.patch.object(call_log.LOG, 'debug') as log_debug:
+            self.klass.test_method(10, 20)
+            log_debug.assert_called_once_with(self.expected_format,
+                                              self.expected_data)
+
+    def test_call_log_all_kwargs(self):
+        self.expected_data['kwargs'] = {'arg1': 10, 'arg2': 20}
+        with mock.patch.object(call_log.LOG, 'debug') as log_debug:
+            self.klass.test_method(arg1=10, arg2=20)
+            log_debug.assert_called_once_with(self.expected_format,
+                                              self.expected_data)
+
+    def test_call_log_known_args_unknown_args_kwargs(self):
+        self.expected_data['args'] = (10, 20, 30)
+        self.expected_data['kwargs'] = {'arg4': 40}
+        with mock.patch.object(call_log.LOG, 'debug') as log_debug:
+            self.klass.test_method(10, 20, 30, arg4=40)
+            log_debug.assert_called_once_with(self.expected_format,
+                                              self.expected_data)
+
+    def test_call_log_known_args_kwargs_unknown_kwargs(self):
+        self.expected_data['args'] = (10,)
+        self.expected_data['kwargs'] = {'arg2': 20, 'arg3': 30, 'arg4': 40}
+        with mock.patch.object(call_log.LOG, 'debug') as log_debug:
+            self.klass.test_method(10, arg2=20, arg3=30, arg4=40)
+            log_debug.assert_called_once_with(self.expected_format,
+                                              self.expected_data)