def _filter_trace_components(trace, args):
        """
        This function walks up the component causal chain. It only returns
        properties in the causal chain and nothing else.
        """
        # check if any filtering is desired
        if not (args.execution or args.rule or args.trigger_instance):
            return trace

        component_id = None
        component_type = None

        # pick the right component type
        if args.execution:
            component_id = args.execution
            component_type = "action_execution"
        elif args.rule:
            component_id = args.rule
            component_type = "rule"
        elif args.trigger_instance:
            component_id = args.trigger_instance
            component_type = "trigger_instance"

        # Initialize collection to use
        action_executions = []
        rules = []
        trigger_instances = []

        # setup flag to properly manage termination conditions
        search_target_found = component_id and component_type

        while search_target_found:
            components_list = []
            if component_type == "action_execution":
                components_list = trace.action_executions
                to_update_list = action_executions
            elif component_type == "rule":
                components_list = trace.rules
                to_update_list = rules
            elif component_type == "trigger_instance":
                components_list = trace.trigger_instances
                to_update_list = trigger_instances
            # Look for search_target in the right collection and
            # once found look up the caused_by to keep movig up
            # the chain.
            search_target_found = False
            # init to default value
            component_caused_by_id = None
            for component in components_list:
                test_id = component["object_id"]
                if test_id == component_id:
                    caused_by = component.get("caused_by", {})
                    component_id = caused_by.get("id", None)
                    component_type = caused_by.get("type", None)
                    # If provided the component_caused_by_id must match as well. This is mostly
                    # applicable for rules since the same rule may appear multiple times and can
                    # only be distinguished by causing TriggerInstance.
                    if (
                        component_caused_by_id
                        and component_caused_by_id != component_id
                    ):
                        continue
                    component_caused_by_id = None
                    to_update_list.append(component)
                    # In some cases the component_id and the causing component are combined to
                    # provide the complete causation chain. Think rule + triggerinstance
                    if component_id and ":" in component_id:
                        component_id_split = component_id.split(":")
                        component_id = component_id_split[0]
                        component_caused_by_id = component_id_split[1]
                    search_target_found = True
                    break

        trace.action_executions = action_executions
        trace.rules = rules
        trace.trigger_instances = trigger_instances
        return trace

        This function walks up the component causal chain. It only returns
        properties in the causal chain and nothing else.
        
st2client/st2client/commands/trace.py