diff --git a/examples/extension_service/server.py b/examples/extension_service/server.py
index 64bc3cf5ef3cb3bf21ed8d0175855932bbfb9ff5..0ad07b7ad31210ae861c968e7c9457a3a6870038 100644
--- a/examples/extension_service/server.py
+++ b/examples/extension_service/server.py
@@ -1,4 +1,5 @@
 import grpc
+import logging
 
 from concurrent import futures
 from perxis.collections import collections_pb2_grpc
@@ -11,10 +12,16 @@ from perxis.interceptors import header_adder_interceptor
 from servicer import Servicer
 from constants.extension import get_extension_descriptor
 
+logging.basicConfig(level=logging.INFO)
+
+logger = logging.getLogger(__name__)
+
 
 def main():
     my_extension_descriptor = get_extension_descriptor(host="demo-ext-backend:50051")
 
+    logger.info(f"Инициализация сервиса расширения {my_extension_descriptor.extension}")
+
     interceptor = header_adder_interceptor(
         'x-perxis-access', 'system'
     )
@@ -34,10 +41,16 @@ def main():
                         )
                     )
 
+                    logger.info(
+                        f"Изменилась версия расширения {my_extension_descriptor.extension} ({ext.version} -> {my_extension_descriptor.version})"
+                    )
+
         ext_manager_stub.RegisterExtensions(manager_pb2.RegisterExtensionsRequest(
             extensions=[my_extension_descriptor]
         ))
 
+        logger.info(f"Расширение {my_extension_descriptor.extension} зарегистрировано в perxis")
+
         with grpc.insecure_channel("content:9020") as content_channel:
             intercepted_content_channel = grpc.intercept_channel(content_channel, interceptor)
 
diff --git a/perxis/extensions/extension_service.py b/perxis/extensions/extension_service.py
index aabf5b6938f468206306ed85c70493c2b91b4bcc..198c7f454f7d126864baf6751217b2e5749934c3 100644
--- a/perxis/extensions/extension_service.py
+++ b/perxis/extensions/extension_service.py
@@ -1,4 +1,5 @@
 import grpc
+import logging
 
 from perxis.extensions import extension_pb2, extension_pb2_grpc
 from perxis.roles import roles_pb2_grpc, roles_pb2
@@ -20,6 +21,7 @@ class ExtensionService(extension_pb2_grpc.ExtensionServicer):
                  roles_service: roles_pb2_grpc.RolesStub,
                  clients_service: clients_pb2_grpc.ClientsStub,
     ):
+        self.logger = logging.getLogger(__name__)
         self.collections_service = collections_service
         self.environments_service = environments_service
         self.roles_service = roles_service
@@ -39,15 +41,45 @@ class ExtensionService(extension_pb2_grpc.ExtensionServicer):
         for client in self.clients or []:
             self.extension_setup.add_client(client)
 
-    def Install(self, request: extension_pb2.InstallRequest, context):
+    def write_result_log(self, operation, request, response):
+        log_func = self.get_log_func_by_state(response.results[0].state)
+
+        log_func(
+            "Результат %s расширения %s для окружения %s пространства %s: \r\n"
+            "State: %s\r\n"
+            "Msg: %s\r\n"
+            "Error: %s" % (
+                operation,
+                self.extension_id,
+                request.env_id,
+                request.space_id,
+                response.results[0].state,
+                response.results[0].msg,
+                response.results[0].error
+            )
+        )
+
+    def get_log_func_by_state(self, state):
+        if state == extension_pb2.ExtensionRequestResult.State.OK:
+            return self.logger.info
+        else:
+            return self.logger.error
+
+    def ext_request_results_from_exception(self, e: Exception) -> extension_pb2.ExtensionRequestResult:
+        return [
+            extension_pb2.ExtensionRequestResult(
+                extension=self.extension_id,
+                state=extension_pb2.ExtensionRequestResult.State.ERROR,
+                error=str(e),
+                msg=None
+            )
+        ]
+
+    def _Install(self, request: extension_pb2.InstallRequest, context):
         errors_list = self.extension_setup.install(
             request.space_id, request.env_id, request.force
         )
 
-        if errors_list:
-            context.set_code(grpc.StatusCode.UNKNOWN)
-            context.set_details("; ".join(errors_list))
-
         response_state = extension_pb2.ExtensionRequestResult.State.OK \
             if not errors_list \
             else extension_pb2.ExtensionRequestResult.State.ERROR
@@ -61,14 +93,35 @@ class ExtensionService(extension_pb2_grpc.ExtensionServicer):
             )]
         )
 
-    def Update(self, request: extension_pb2.UpdateRequest, context):
-        errors_list = self.extension_setup.update(
-            request.space_id, request.env_id, request.force
+    def Install(self, request: extension_pb2.InstallRequest, context):
+        self.logger.info(
+            "Установка расширения %s для окружения %s пространства %s. %s force" % (
+                self.extension_id,
+                request.env_id,
+                request.space_id,
+                "С" if request.force else "Без"
+            )
         )
 
-        if errors_list:
+        try:
+            response = self._Install(request, context)
+        except Exception as e:
+            response = extension_pb2.InstallResponse(
+                results=self.ext_request_results_from_exception(e)
+            )
+
+        if response.results[0].state != extension_pb2.ExtensionRequestResult.State.OK:
             context.set_code(grpc.StatusCode.UNKNOWN)
-            context.set_details("; ".join(errors_list))
+            context.set_details(response.results[0].error)
+
+        self.write_result_log("установки", request, response)
+
+        return response
+
+    def _Update(self, request: extension_pb2.UpdateRequest, context):
+        errors_list = self.extension_setup.update(
+            request.space_id, request.env_id, request.force
+        )
 
         response_state = extension_pb2.ExtensionRequestResult.State.OK \
             if not errors_list \
@@ -83,7 +136,32 @@ class ExtensionService(extension_pb2_grpc.ExtensionServicer):
             )]
         )
 
-    def Uninstall(self, request: extension_pb2.UninstallRequest, context):
+    def Update(self, request: extension_pb2.UpdateRequest, context):
+        self.logger.info(
+            "Обновление расширения %s для окружения %s пространства %s. %s force" % (
+                self.extension_id,
+                request.env_id,
+                request.space_id,
+                "С" if request.force else "Без"
+            )
+        )
+
+        try:
+            response = self._Update(request, context)
+        except Exception as e:
+            response = extension_pb2.UpdateResponse(
+                results=self.ext_request_results_from_exception(e)
+            )
+
+        if response.results[0].state != extension_pb2.ExtensionRequestResult.State.OK:
+            context.set_code(grpc.StatusCode.UNKNOWN)
+            context.set_details(response.results[0].error)
+
+        self.write_result_log("обновления", request, response)
+
+        return response
+
+    def _Uninstall(self, request: extension_pb2.UninstallRequest, context):
         errors_list: list[str] = self.extension_setup.uninstall(request.space_id, request.env_id, request.remove)
 
         response_state = extension_pb2.ExtensionRequestResult.State.OK \
@@ -99,12 +177,33 @@ class ExtensionService(extension_pb2_grpc.ExtensionServicer):
             )]
         )
 
-    def Check(self, request: extension_pb2.CheckRequest, context):
-        errors_list = self.extension_setup.check(request.space_id, request.env_id)
+    def Uninstall(self, request: extension_pb2.UninstallRequest, context):
+        self.logger.info(
+            "Удаление расширения %s для окружения %s пространства %s. %s remove" % (
+                self.extension_id,
+                request.env_id,
+                request.space_id,
+                "С" if request.remove else "Без"
+            )
+        )
 
-        if errors_list:
+        try:
+            response = self._Uninstall(request, context)
+        except Exception as e:
+            response = extension_pb2.UninstallResponse(
+                results=self.ext_request_results_from_exception(e)
+            )
+
+        if response.results[0].state != extension_pb2.ExtensionRequestResult.State.OK:
             context.set_code(grpc.StatusCode.UNKNOWN)
-            context.set_details("; ".join(errors_list))
+            context.set_details(response.results[0].error)
+
+        self.write_result_log("удаления", request, response)
+
+        return response
+
+    def _Check(self, request: extension_pb2.CheckRequest, context):
+        errors_list = self.extension_setup.check(request.space_id, request.env_id)
 
         response_state = extension_pb2.ExtensionRequestResult.State.OK \
             if not errors_list \
@@ -119,6 +218,30 @@ class ExtensionService(extension_pb2_grpc.ExtensionServicer):
             )]
         )
 
+    def Check(self, request: extension_pb2.CheckRequest, context):
+        self.logger.info(
+            "Проверка расширения %s для окружения %s пространства %s" % (
+                self.extension_id,
+                request.env_id,
+                request.space_id,
+            )
+        )
+
+        try:
+            response = self._Check(request, context)
+        except Exception as e:
+            response = extension_pb2.CheckResponse(
+                results=self.ext_request_results_from_exception(e)
+            )
+
+        if response.results[0].state != extension_pb2.ExtensionRequestResult.State.OK:
+            context.set_code(grpc.StatusCode.UNKNOWN)
+            context.set_details(response.results[0].error)
+
+        self.write_result_log("проверки", request, response)
+
+        return response
+
     def Action(self, request: extension_pb2.ActionRequest, context):
         context.set_code(grpc.StatusCode.UNKNOWN)
         context.set_details("Unknown action")
diff --git a/setup.py b/setup.py
index 97684b0a88e9b10112224c6939f5ac6d5ad724c9..0b35fb6bc6739aaa4dddd2641ed0bc68f7db69f3 100644
--- a/setup.py
+++ b/setup.py
@@ -14,7 +14,7 @@ def load_requirements():
 
 setup(
     name='perxis',
-    version='0.0.17',
+    version='0.0.18',
     description='Perxis python client',
     long_description=long_description,
     long_description_content_type='text/markdown',