def METHOD_NAME(self, dxo: DXO, shareable, fl_ctx: FLContext) -> DXO:
    if not dxo.data:
        self.log_debug(fl_ctx, "DXO has no data to filter")
        return dxo
    filter_name = self.__class__.__name__
    result = self.process_dxo(dxo, shareable, fl_ctx)
    if not result:
        # not filtered
        result = dxo
    elif not isinstance(result, DXO):
        raise RuntimeError(f"Result from {filter_name} is {type(result)} - must be DXO")
    else:
        if result != dxo:
            # result is a new DXO - copy filter history from original dxo
            result.add_filter_history(dxo.get_filter_history())
        result.add_filter_history(filter_name)
        chain_type = self.get_prop(FilterContextKey.CHAIN_TYPE, "?")
        source = self.get_prop(FilterContextKey.SOURCE, "?")
        add_job_audit_event(fl_ctx=fl_ctx, msg=f"applied filter: {filter_name}@{source} on {chain_type}")
    return result