Alex Shatov | 8cdeeeb | 2017-09-26 17:03:11 -0400 | [diff] [blame] | 1 | # ================================================================================ |
Lusheng Ji | cc30700 | 2018-02-12 11:04:54 -0500 | [diff] [blame] | 2 | # Copyright (c) 2017-2018 AT&T Intellectual Property. All rights reserved. |
Alex Shatov | 8cdeeeb | 2017-09-26 17:03:11 -0400 | [diff] [blame] | 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 | # ECOMP is a trademark and service mark of AT&T Intellectual Property. |
| 18 | |
Alex Shatov | 90f2105 | 2018-01-10 11:39:32 -0500 | [diff] [blame] | 19 | """:@CtxLogger.log_ctx: decorator for logging the cloudify ctx before and after operation""" |
| 20 | |
Alex Shatov | 8cdeeeb | 2017-09-26 17:03:11 -0400 | [diff] [blame] | 21 | import json |
Alex Shatov | 90f2105 | 2018-01-10 11:39:32 -0500 | [diff] [blame] | 22 | import traceback |
Alex Shatov | 8cdeeeb | 2017-09-26 17:03:11 -0400 | [diff] [blame] | 23 | from functools import wraps |
| 24 | |
| 25 | from cloudify import ctx |
| 26 | from cloudify.context import NODE_INSTANCE, RELATIONSHIP_INSTANCE |
| 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: |
Alex Shatov | 90f2105 | 2018-01-10 11:39:32 -0500 | [diff] [blame] | 105 | ctx.logger.error("Failed to log the node context: {0}: {1}" \ |
| 106 | .format(str(ex), traceback.format_exc())) |
Alex Shatov | 8cdeeeb | 2017-09-26 17:03:11 -0400 | [diff] [blame] | 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: |
Alex Shatov | 90f2105 | 2018-01-10 11:39:32 -0500 | [diff] [blame] | 123 | ctx.logger.error("Failed to set exe_task {0}: {1}: {2}" \ |
| 124 | .format(exe_task, str(ex), traceback.format_exc())) |
Alex Shatov | 8cdeeeb | 2017-09-26 17:03:11 -0400 | [diff] [blame] | 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 |