move plugins from from ccsdk to dcaegen2
[dcaegen2/platform/plugins.git] / clamp-policy / tests / log_ctx.py
1 # ================================================================================
2 # Copyright (c) 2019 Wipro Limited Intellectual Property. All rights reserved.
3 # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
4 # ================================================================================
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 #      http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 # ============LICENSE_END=========================================================
17 #
18
19 """:@CtxLogger.log_ctx: decorator for logging the cloudify ctx before and after operation"""
20
21 import json
22 import traceback
23 from functools import wraps
24
25 from cloudify import ctx
26 from cloudify.context import NODE_INSTANCE, RELATIONSHIP_INSTANCE
27
28
29 class CtxLogger(object):
30     """static class for logging cloudify context ctx"""
31     @staticmethod
32     def _get_ctx_node_info(ctx_node):
33         if not ctx_node:
34             return {}
35         return {'id': ctx_node.id, 'name': ctx_node.name, 'type': ctx_node.type,
36                 'type_hierarchy': ctx_node.type_hierarchy, 'properties': ctx_node.properties}
37
38     @staticmethod
39     def _get_ctx_instance_info(ctx_instance):
40         if not ctx_instance:
41             return {}
42         return {'id' : ctx_instance.id, 'runtime_properties' : ctx_instance.runtime_properties,
43                 'relationships' : CtxLogger._get_ctx_instance_relationships_info(ctx_instance)}
44
45     @staticmethod
46     def _get_ctx_instance_relationships_info(ctx_instance):
47         if not ctx_instance or not ctx_instance.relationships:
48             return []
49         return [{'target': CtxLogger._get_ctx_source_target_info(r.target), \
50                  'type':r.type, 'type_hierarchy':r.type_hierarchy} \
51                 for r in ctx_instance.relationships]
52
53     @staticmethod
54     def _get_ctx_source_target_info(ctx_source_target):
55         if not ctx_source_target:
56             return {}
57         return {'node': CtxLogger._get_ctx_node_info(ctx_source_target.node),
58                 'instance' : CtxLogger._get_ctx_instance_info(ctx_source_target.instance)}
59
60     @staticmethod
61     def get_ctx_info():
62         """collect the context data from ctx"""
63         context = {
64             'type': ctx.type,
65             'blueprint.id': ctx.blueprint.id,
66             'deployment.id': ctx.deployment.id,
67             'execution_id': ctx.execution_id,
68             'workflow_id': ctx.workflow_id,
69             'task_id': ctx.task_id,
70             'task_name': ctx.task_name,
71             'task_queue': ctx.task_queue,
72             'task_target': ctx.task_target,
73             'operation': {
74                 'name': ctx.operation.name,
75                 'retry_number': ctx.operation.retry_number,
76                 'max_retries': ctx.operation.max_retries
77             },
78             'plugin': {
79                 'name': ctx.plugin.name,
80                 'package_name': ctx.plugin.package_name,
81                 'package_version': ctx.plugin.package_version,
82                 'prefix': ctx.plugin.prefix,
83                 'workdir': ctx.plugin.workdir
84             }
85         }
86         if ctx.type == NODE_INSTANCE:
87             context['node'] = CtxLogger._get_ctx_node_info(ctx.node)
88             context['instance'] = CtxLogger._get_ctx_instance_info(ctx.instance)
89         elif ctx.type == RELATIONSHIP_INSTANCE:
90             context['source'] = CtxLogger._get_ctx_source_target_info(ctx.source)
91             context['target'] = CtxLogger._get_ctx_source_target_info(ctx.target)
92
93         return context
94
95     @staticmethod
96     def log_ctx_info(func_name):
97         ctx.logger.info("NODE_INSTANCE: {}",NODE_INSTANCE)
98         """shortcut for logging of the ctx of the function"""
99         try:
100             ctx.logger.info("NODE_INSTANCE: {}",NODE_INSTANCE)
101             if ctx.type == NODE_INSTANCE:
102                 ctx.logger.info("{0} {1} context: {2}".format(\
103                     func_name, ctx.instance.id, json.dumps(CtxLogger.get_ctx_info())))
104             elif ctx.type == RELATIONSHIP_INSTANCE:
105                 ctx.logger.info("{0} context: {1}".format(\
106                     func_name, json.dumps(CtxLogger.get_ctx_info())))
107         except Exception as ex:
108             ctx.logger.error("Failed to log the node context: {0}: {1}" \
109                 .format(str(ex), traceback.format_exc()))
110
111     @staticmethod
112     def log_ctx(pre_log=True, after_log=False, exe_task=None):
113         """Decorate each operation on the node to log the context - before and after.
114         Optionally save the current function name into runtime_properties[exe_task]
115         """
116         def log_ctx_info_decorator(func, **arguments):
117             """Decorate each operation on the node to log the context"""
118             if func is not None:
119                 @wraps(func)
120                 def wrapper(*args, **kwargs):
121                     """the actual logger before and after"""
122                     try:
123                         if ctx.type == NODE_INSTANCE and exe_task:
124                             ctx.instance.runtime_properties[exe_task] = func.__name__
125                     except Exception as ex:
126                         ctx.logger.error("Failed to set exe_task {0}: {1}: {2}" \
127                             .format(exe_task, str(ex), traceback.format_exc()))
128                     if pre_log:
129                         CtxLogger.log_ctx_info('before ' + func.__name__)
130
131                     result = func(*args, **kwargs)
132
133                     if after_log:
134                         CtxLogger.log_ctx_info('after ' + func.__name__)
135
136                     return result
137                 return wrapper
138         return log_ctx_info_decorator