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