move plugins from from ccsdk to dcaegen2
[dcaegen2/platform/plugins.git] / dcae-policy / tests / log_ctx.py
1 # ================================================================================
2 # Copyright (c) 2017-2020 AT&T 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         """shortcut for logging of the ctx of the function"""
97         try:
98             if ctx.type == NODE_INSTANCE:
99                 ctx.logger.info("{0} {1} context: {2}".format(\
100                     func_name, ctx.instance.id, json.dumps(CtxLogger.get_ctx_info())))
101             elif ctx.type == RELATIONSHIP_INSTANCE:
102                 ctx.logger.info("{0} context: {1}".format(\
103                     func_name, json.dumps(CtxLogger.get_ctx_info())))
104         except Exception as ex:
105             ctx.logger.error("Failed to log the node context: {0}: {1}" \
106                 .format(str(ex), traceback.format_exc()))
107
108     @staticmethod
109     def log_ctx(pre_log=True, after_log=False, exe_task=None):
110         """Decorate each operation on the node to log the context - before and after.
111         Optionally save the current function name into runtime_properties[exe_task]
112         """
113         def log_ctx_info_decorator(func, **arguments):
114             """Decorate each operation on the node to log the context"""
115             if func is not None:
116                 @wraps(func)
117                 def wrapper(*args, **kwargs):
118                     """the actual logger before and after"""
119                     try:
120                         if ctx.type == NODE_INSTANCE and exe_task:
121                             ctx.instance.runtime_properties[exe_task] = func.__name__
122                     except Exception as ex:
123                         ctx.logger.error("Failed to set exe_task {0}: {1}: {2}" \
124                             .format(exe_task, str(ex), traceback.format_exc()))
125                     if pre_log:
126                         CtxLogger.log_ctx_info('before ' + func.__name__)
127
128                     result = func(*args, **kwargs)
129
130                     if after_log:
131                         CtxLogger.log_ctx_info('after ' + func.__name__)
132
133                     return result
134                 return wrapper
135         return log_ctx_info_decorator