SEBA-439 Log changes to data model fields in synchronizer

Change-Id: I83c5f448687ecde49b7c27d294bc3d00ce324b8d
diff --git a/VERSION b/VERSION
index bfac6fc..b9975ae 100644
--- a/VERSION
+++ b/VERSION
@@ -1,2 +1,2 @@
-2.1.36
+2.1.37
 
diff --git a/containers/xos/Dockerfile.client b/containers/xos/Dockerfile.client
index eed6feb..cc8c026 100644
--- a/containers/xos/Dockerfile.client
+++ b/containers/xos/Dockerfile.client
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 # xosproject/xos-client
-FROM xosproject/xos-libraries:2.1.36
+FROM xosproject/xos-libraries:2.1.37
 
 # Install XOS client
 COPY lib/xos-api /tmp/xos-api
diff --git a/containers/xos/Dockerfile.libraries b/containers/xos/Dockerfile.libraries
index c96f241..66f9f01 100644
--- a/containers/xos/Dockerfile.libraries
+++ b/containers/xos/Dockerfile.libraries
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 # xosproject/xos-libraries
-FROM xosproject/xos-base:2.1.36
+FROM xosproject/xos-base:2.1.37
 
 # Add libraries
 COPY lib /opt/xos/lib
diff --git a/containers/xos/Dockerfile.synchronizer-base b/containers/xos/Dockerfile.synchronizer-base
index 2ae3ed4..9230cd9 100644
--- a/containers/xos/Dockerfile.synchronizer-base
+++ b/containers/xos/Dockerfile.synchronizer-base
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 # xosproject/xos-synchronizer-base
-FROM xosproject/xos-client:2.1.36
+FROM xosproject/xos-client:2.1.37
 
 COPY xos/synchronizers/new_base /opt/xos/synchronizers/new_base
 COPY xos/xos/logger.py /opt/xos/xos/logger.py
diff --git a/containers/xos/Dockerfile.xos-core b/containers/xos/Dockerfile.xos-core
index aa1eb15..0a92707 100644
--- a/containers/xos/Dockerfile.xos-core
+++ b/containers/xos/Dockerfile.xos-core
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 # xosproject/xos-core
-FROM xosproject/xos-libraries:2.1.36
+FROM xosproject/xos-libraries:2.1.37
 
 # Install XOS
 ADD xos /opt/xos
diff --git a/lib/xos-api/xosapi/orm.py b/lib/xos-api/xosapi/orm.py
index 398d199..41d775f 100644
--- a/lib/xos-api/xosapi/orm.py
+++ b/lib/xos-api/xosapi/orm.py
@@ -18,6 +18,7 @@
 import threading
 import time
 import imp
+import traceback
 from xosconfig import Config
 from multistructlog import create_logger
 
@@ -47,6 +48,17 @@
 
 convenience_wrappers = {}
 
+# Find the topmost synchronizer-specific function in the call stack
+def get_synchronizer_function():
+    result = None
+    for file,line,func,stmt in traceback.extract_stack():
+        if file.startswith("/opt/xos/synchronizers"):
+            if not result:
+                result = "%s:%s()" % (file,func)
+            if not file.startswith("/opt/xos/synchronizers/new_base"):
+                result = "%s:%s()" % (file,func)
+                break
+    return result
 
 class ORMGenericContentNotFoundException(Exception):
     pass
@@ -409,13 +421,19 @@
         is_sync_save=False,
         is_policy_save=False,
     ):
+        classname = self._wrapped_class.__class__.__name__
         if self.is_new:
+            log.debug("save(): is new", classname=classname, syncstep=get_synchronizer_function())
             new_class = self.stub.invoke(
-                "Create%s" % self._wrapped_class.__class__.__name__, self._wrapped_class
+                "Create%s" % classname, self._wrapped_class
             )
             self._wrapped_class = new_class
             self.is_new = False
         else:
+            if self.has_changed:
+              log.debug("save(): updated", classname=classname, changed_fields=self.changed_fields, syncstep=get_synchronizer_function())
+            else:
+              log.debug("save(): no changes", classname=classname, syncstep=get_synchronizer_function())
             metadata = []
             if update_fields:
                 metadata.append(("update_fields", ",".join(update_fields)))
@@ -426,7 +444,7 @@
             if is_sync_save:
                 metadata.append(("is_sync_save", "1"))
             self.stub.invoke(
-                "Update%s" % self._wrapped_class.__class__.__name__,
+                "Update%s" % classname,
                 self._wrapped_class,
                 metadata=metadata,
             )