SEBA-439 Log changes to data model fields in synchronizer

Change-Id: I83c5f448687ecde49b7c27d294bc3d00ce324b8d
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,
             )