return engine, 'got MySQL engine', 'none' except: print('error :: DB engine not obtained') print(traceback.format_exc()) return None try: engine, log_msg, trace = get_engine() except: print(traceback.format_exc()) if not engine: print('error :: engine not obtained to get fp_ids') try: ionosphere_table, log_msg, trace = ionosphere_table_meta('autobuild', engine) except: print(traceback.format_exc()) # get all fp ids and metric ids from ionosphere table fps_data = [] try: connection = engine.connect() stmt = select([ionosphere_table]).where(ionosphere_table.c.metric_id > 0) result = connection.execute(stmt) for row in result: if row['enabled'] != 1: continue if row['deleted'] == 1: continue fp_id = row['id']
def ionosphere_echo(base_name, mirage_full_duration): logger = logging.getLogger(skyline_app_logger) child_process_pid = os.getpid() context = 'ionosphere_echo' logger.info('ionosphere_echo :: started with child_process_pid - %s for %s' % (str(child_process_pid), base_name)) full_duration_in_hours = int(settings.FULL_DURATION / 60 / 60) try: # Allow for 3 seconds ionosphere_echo_max_fp_create_time = (settings.IONOSPHERE_ECHO_MAX_FP_CREATE_TIME - 3) except: ionosphere_echo_max_fp_create_time = 52 echo_started_at = int(time()) def echo_get_an_engine(): try: engine, fail_msg, trace = get_engine(skyline_app) return engine, fail_msg, trace except: trace = traceback.format_exc() logger.error('%s' % trace) fail_msg = 'error :: ionosphere_echo :: get_an_engine :: failed to get MySQL engine' logger.error('%s' % fail_msg) return None, fail_msg, trace def echo_engine_disposal(engine): try: if engine: try: engine.dispose() logger.info('ionosphere_echo :: MySQL engine disposed of') return True except: logger.error(traceback.format_exc()) logger.error('error :: ionosphere_echo :: calling engine.dispose()') else: logger.info('ionosphere_echo :: no MySQL engine to dispose of') return True except: return False return False # Determine the metric details from the database metrics_id = None metric_db_object = None engine = None # Get the metric db object data to memcache it is exists metric_db_object = get_memcache_metric_object(skyline_app, base_name) if metric_db_object: metrics_id = metric_db_object['id'] logger.info('ionosphere_echo :: determined metric id %s from memcache for %s' % (str(metrics_id), base_name)) else: # Only if no memcache data # Get a MySQL engine try: engine, log_msg, trace = echo_get_an_engine() logger.info('ionosphere_echo :: %s' % log_msg) logger.info('ionosphere_echo :: determining metric id from DB as not found in memcache for %s' % (base_name)) except: logger.error(traceback.format_exc()) logger.error('error :: ionosphere_echo :: could not get a MySQL engine to get metric_db_object') if not engine: logger.error('error :: ionosphere_echo :: engine not obtained to get metric_db_object') logger.info('ionosphere_echo :: exiting this work but not removing work item, as database may be available again before the work expires') return try: metrics_id, metric_db_object = echo_get_metric_from_metrics(base_name, engine) echo_engine_disposal(engine) except: logger.error(traceback.format_exc()) logger.error('error :: ionosphere_echo :: failed get the metric details from the database') logger.info('ionosphere_echo :: exiting this work but not removing work item, as database may be available again before the work expires') if not metrics_id: logger.error('error :: ionosphere_echo :: failed get the metrics_id from the database') logger.info('ionosphere_echo :: exiting this work but not removing work item, as database may be available again before the work expires') echo_engine_disposal(engine) return if not metric_db_object: logger.error('error :: ionosphere_echo :: failed get the metric_db_object from the database') logger.info('ionosphere_echo :: exiting this work but not removing work item, as database may be available again before the work expires') echo_engine_disposal(engine) return # Determine the metric fp ids from the database if not engine: logger.info('ionosphere_echo :: getting MySQL engine to determine fp ids for metric id %s - %s' % (str(metrics_id), base_name)) try: engine, log_msg, trace = echo_get_an_engine() logger.info(log_msg) except: logger.error(traceback.format_exc()) logger.error('error :: ionosphere_echo :: could not get a MySQL engine to get fp_ids') if not engine: logger.error('error :: ionosphere_echo :: engine not obtained to get fp_ids') return try: ionosphere_table, log_msg, trace = ionosphere_table_meta(skyline_app, engine) logger.info(log_msg) logger.info('ionosphere_echo :: ionosphere_table OK') except: logger.error(traceback.format_exc()) logger.error('error :: ionosphere_echo :: failed to get ionosphere_table meta for %s' % base_name) # Determine the fp_ids that exist for the metric echo_fp_ids_result = [] try: connection = engine.connect() stmt = select([ionosphere_table]).where(ionosphere_table.c.metric_id == metrics_id).order_by(desc(ionosphere_table.c.id)) echo_fp_ids = connection.execute(stmt) echo_fp_ids_result = [{column: value for column, value in rowproxy.items()} for rowproxy in echo_fp_ids] connection.close() except: logger.error(traceback.format_exc()) logger.error('error :: ionosphere_echo :: could not determine fp ids from DB for %s' % base_name) return if engine: echo_engine_disposal(engine) if not echo_fp_ids_result: logger.error('error :: ionosphere_echo :: no echo_fp_ids_result - could not determine fp ids from DB for %s' % base_name) else: logger.info('ionosphere_echo :: echo_fp_ids_result - determined fp ids from DB for %s' % base_name) try: db_fp_count = len(echo_fp_ids_result) logger.info('ionosphere_echo :: %s features profile ids found' % str(db_fp_count)) except: logger.error(traceback.format_exc()) logger.error('error :: ionosphere_echo :: could not calculate len of echo_fp_ids_result') echo_enabled_mirage_fp_ids = [] for row in echo_fp_ids_result: if row['enabled'] != 1: continue if row['deleted'] == 1: continue # Only create features profiles at settings.FULL_DURATION for Mirage # features profiles if the fp has been validated if row['validated'] == 0: continue if row['full_duration'] == int(mirage_full_duration): fp_id = row['id'] # @added 20190413 - Bug #2934: Ionosphere - no mirage.redis.24h.json file # Feature #1960: ionosphere_layers # Any features profiles that were created before the introduction of # ionosphere_layers will not have a mirage.redis.24h.json file as the # creation of these resources in the training_data dir was only added at # that point, so they are excluded. Less than 20170307 1488844800 excl. # @modified 20190508 - Bug #2934: Ionosphere - no mirage.redis.24h.json file # Feature #1960: ionosphere_layers # Increased the date as some on the cusp were still erroring, move # forward 2 days to 20170309 # if int(row['anomaly_timestamp']) < 1488844800: if int(row['anomaly_timestamp']) < 1489017600: logger.info('ionosphere_echo :: skipping fp id %s as predates having a mirage.redis json file' % str(fp_id)) continue echo_enabled_mirage_fp_ids.append(fp_id) echo_enabled_mirage_fp_ids_count = len(echo_enabled_mirage_fp_ids) logger.info('ionosphere_echo :: %s Mirage features profile ids found' % str(echo_enabled_mirage_fp_ids_count)) # Check which Mirage features profile do not have has a # settings.FULL_DURATION features profile mirage_fd_fp_count = 0 echo_create_fd_fp_for = [] for validated_mirage_fp_id in echo_enabled_mirage_fp_ids: mirage_fd_fp_exists = False for row in echo_fp_ids_result: if int(row['parent_id']) != int(validated_mirage_fp_id): continue if int(row['full_duration']) == int(settings.FULL_DURATION): mirage_fd_fp_exists = True mirage_fd_fp_count += 1 if not mirage_fd_fp_exists: echo_create_fd_fp_for.append(int(validated_mirage_fp_id)) del echo_enabled_mirage_fp_ids logger.info('ionosphere_echo :: there are %s FULL_DURATION features profiles for %s' % (str(mirage_fd_fp_count), base_name)) echo_create_fd_fp_for_count = len(echo_create_fd_fp_for) logger.info('ionosphere_echo :: %s FULL_DURATION features profiles to be created for %s' % (str(echo_create_fd_fp_for_count), base_name)) echo_created_fp_count = 0 # @added 20190404 - Bug #2904: Initial Ionosphere echo load and Ionosphere feedback # Feature #2484: FULL_DURATION feature profiles # Rate limit the creation of ionosphere_echo FULL_DURATION features profiles # this only effects managing the creation of lots of features profiles if # Ionosphere echo is enabled on a Skyline instance with lots of existing # features profiles for Mirage metrics. Only create 5 FULL_DURATION # features profiles from the latest Mirage based features profiles, which # takes around 10 seconds if echo_create_fd_fp_for_count > 5: logger.info('ionosphere_echo :: rate limiting and only creating the 5 least FULL_DURATION features profiles for %s' % (base_name)) # Reverse, newest first, using slicing to produce a reversed copy reverse_echo_create_fd_fp_for = echo_create_fd_fp_for[::-1] rate_limit_echo_create_fd_fp_for = reverse_echo_create_fd_fp_for[0:5] echo_create_fd_fp_for = rate_limit_echo_create_fd_fp_for last_created_fp = int(time()) for mirage_fp_id in echo_create_fd_fp_for: fp_timestamp = None for row in echo_fp_ids_result: if int(row['id']) != int(mirage_fp_id): continue else: fp_timestamp = int(row['anomaly_timestamp']) fp_generation = int(row['generation']) if not fp_timestamp: continue if not fp_generation: fp_generation = 0 time_check_now = int(time()) echo_runtime = time_check_now - echo_started_at if echo_runtime >= ionosphere_echo_max_fp_create_time: logger.info('ionosphere_echo :: ionosphere_echo running for %s seconds, exiting before IONOSPHERE_ECHO_MAX_FP_CREATE_TIME of %s seconds is breached' % (str(echo_runtime), str(ionosphere_echo_max_fp_create_time))) break logger.info('ionosphere_echo :: creating FULL_DURATION features profile based on data from fp id %s - %s' % (str(mirage_fp_id), base_name)) context = 'ionosphere_echo' ionosphere_job = 'learn_fp_human' generation = fp_generation + 1 fp_learn = False # What is the path of the features profile files metric_timeseries_dir = base_name.replace('.', '/') metric_fp_data_dir = '%s/%s/%s' % ( settings.IONOSPHERE_PROFILES_FOLDER, metric_timeseries_dir, str(fp_timestamp)) # What is the path of the new training data dir to copy the files to # and create it created_ts = int(time()) # Ensure features profile creation timestamps do not overlap if last_created_fp == created_ts: sleep(1) created_ts = int(time()) last_created_fp = created_ts metric_training_data_dir = '%s/%s/%s' % ( settings.IONOSPHERE_DATA_FOLDER, str(created_ts), metric_timeseries_dir) if not os.path.exists(metric_training_data_dir): try: mkdir_p(metric_training_data_dir) logger.info('ionosphere_echo :: training data dir created - %s' % metric_training_data_dir) except: logger.error('error :: ionosphere_echo :: failed to create training data dir - %s' % metric_training_data_dir) continue if not os.path.isdir(metric_fp_data_dir): logger.error('error :: ionosphere_echo :: features profile data dir does not exist - %s' % metric_fp_data_dir) continue data_files = [] try: glob_path = '%s/*.*' % metric_fp_data_dir data_files = glob.glob(glob_path) except: trace = traceback.format_exc() logger.error('%s' % trace) logger.error('error :: ionosphere_echo :: glob could not read - %s' % metric_fp_data_dir) # Make a list of the files to copy copy_files = [] for i_file in data_files: # Exclude all the file resources related to the Mirage # full_duration features profile if 'matched.fp_id' in i_file: continue if 'fp.created.txt' in i_file: continue if 'fp.details.txt' in i_file: continue if 'csv.features.transposed.csv' in i_file: continue # Specifically include the required files if 'graphite_now' in i_file: copy_files.append(i_file) echo_metric_txt = '%s.txt' % base_name if echo_metric_txt in i_file: copy_files.append(i_file) echo_metric_json = '%s.json' % base_name if echo_metric_json in i_file: copy_files.append(i_file) if 'mirage.graphite' in i_file: copy_files.append(i_file) if 'mirage.redis' in i_file: copy_files.append(i_file) # Copy the required files to the new training_data dir for i_file in copy_files: copying_filename = os.path.basename(i_file) dest_file = '%s/%s' % (metric_training_data_dir, copying_filename) if not os.path.isfile(dest_file): try: shutil.copy(i_file, metric_training_data_dir) # logger.info('ionosphere_echo :: training data copied - %s' % (i_file)) except shutil.Error as e: trace = traceback.format_exc() logger.error('%s' % trace) logger.error('error :: ionosphere_echo :: shutil error - training data not copied to %s' % metric_training_data_dir) logger.error('error :: ionosphere_echo :: %s' % (e)) # Any error saying that the directory doesn't exist except OSError as e: trace = traceback.format_exc() logger.error('%s' % trace) logger.error('error :: ionosphere_echo :: OSError error - training data not copied to %s' % metric_training_data_dir) logger.error('error :: %s' % (e)) calculated_feature_file = '%s/%s.tsfresh.input.csv.features.transposed.csv' % (metric_training_data_dir, base_name) calculated_feature_file_found = False fp_csv = None if os.path.isfile(calculated_feature_file): calculated_feature_file_found = True fp_csv = calculated_feature_file logger.info('ionosphere_echo :: calculated features file is available - %s' % (calculated_feature_file)) echo_json_file = '%s.mirage.redis.%sh.json' % (base_name, str(full_duration_in_hours)) if not calculated_feature_file_found: logger.info('ionosphere_echo :: calculating features from mirage.redis data ts json - %s' % (echo_json_file)) str_created_ts = str(created_ts) try: fp_csv, successful, fp_exists, fp_id, log_msg, traceback_format_exc, f_calc = calculate_features_profile(skyline_app, str_created_ts, base_name, context) except: logger.error(traceback.format_exc()) logger.error('error :: ionosphere_echo :: failed to calculate features') continue else: logger.info('ionosphere_echo :: using available calculated features file') if os.path.isfile(calculated_feature_file): logger.info('ionosphere_echo :: calculated features - %s' % (calculated_feature_file)) else: logger.error('error :: ionosphere_echo :: failed to calculate features no file found - %s' % calculated_feature_file) continue # Create the new settings.FULL_DURATION features profile ionosphere_job = 'learn_fp_human' # @added 20190503 - Branch #2646: slack # Added slack_ionosphere_job slack_ionosphere_job = ionosphere_job fp_learn = False try: # @modified 20190503 - Branch #2646: slack # Added slack_ionosphere_job # fp_id, fp_in_successful, fp_exists, fail_msg, traceback_format_exc = create_features_profile(skyline_app, created_ts, base_name, context, ionosphere_job, mirage_fp_id, generation, fp_learn) # @modified 20190922 - Feature #3230: users DB table # Ideas #2476: Label and relate anomalies # Feature #2516: Add label to features profile # Added user_id # fp_id, fp_in_successful, fp_exists, fail_msg, traceback_format_exc = create_features_profile(skyline_app, created_ts, base_name, context, ionosphere_job, mirage_fp_id, generation, fp_learn, slack_ionosphere_job, user_id) user_id = 1 # @modified 20191030 - Feature #2516: Add label to features profile # Added missing label label = 'echo' fp_id, fp_in_successful, fp_exists, fail_msg, traceback_format_exc = create_features_profile(skyline_app, created_ts, base_name, context, ionosphere_job, mirage_fp_id, generation, fp_learn, slack_ionosphere_job, user_id, label) except: logger.error(traceback.format_exc()) logger.error('error :: ionosphere_echo :: failed to create a settings.FULL_DURATION features profile from fp_id %s for %s' % (str(mirage_fp_id), base_name)) continue if not fp_in_successful: logger.error(traceback.format_exc()) logger.error('error :: ionosphere_echo :: create_features_profile failed') continue else: echo_created_fp_count += 1 logger.info( 'ionosphere_echo :: new generation %s features profile with id %s settings.FULL_DURATION created from parent feature profile with id %s' % ( str(generation), str(fp_id), str(mirage_fp_id))) del echo_create_fd_fp_for if engine: echo_engine_disposal(engine) logger.info('ionosphere_echo :: created %s of %s FULL_DURATION features profile that were to be created for %s' % (str(echo_created_fp_count), str(echo_create_fd_fp_for_count), base_name)) return
def get_ionosphere_fp_db_row(current_skyline_app, fp_id): """ Return the ionosphere table database row as a dict """ function_str = 'functions.database.queries.get_ionosphere_fp_db_row' log_msg = None trace = None current_skyline_app_logger = current_skyline_app + 'Log' current_logger = logging.getLogger(current_skyline_app_logger) fp_id_row = {} try: engine, fail_msg, trace = get_engine(current_skyline_app) except Exception as e: trace = traceback.format_exc() current_logger.error(trace) fail_msg = 'error :: %s :: could not get a MySQL engine - %s' % (function_str, e) current_logger.error('%s' % fail_msg) if engine: engine_disposal(current_skyline_app, engine) if current_skyline_app == 'webapp': # Raise to webapp raise return fp_id_row try: ionosphere_table, log_msg, trace = ionosphere_table_meta(current_skyline_app, engine) except Exception as e: current_logger.error(traceback.format_exc()) current_logger.error('error :: %s :: failed to get ionosphere_table meta for fp id %s - %s' % ( function_str, str(fp_id), e)) if engine: engine_disposal(engine) if current_skyline_app == 'webapp': # Raise to webapp raise return fp_id_row try: connection = engine.connect() stmt = select([ionosphere_table]).where(ionosphere_table.c.id == int(fp_id)) result = connection.execute(stmt) row = result.fetchone() try: fp_id_row = dict(row) except Exception as e: trace = traceback.format_exc() connection.close() current_logger.error(trace) fail_msg = 'error :: %s :: could not convert db ionosphere row to dict for fp id %s - %s' % ( function_str, str(fp_id), e) current_logger.error('%s' % fail_msg) if engine: engine_disposal(engine) if current_skyline_app == 'webapp': # Raise to webapp raise return fp_id_row connection.close() except Exception as e: current_logger.error(traceback.format_exc()) current_logger.error('error :: %s :: could not get ionosphere row for fp id %s - %s' % ( function_str, str(fp_id), e)) if engine: engine_disposal(engine) if current_skyline_app == 'webapp': # Raise to webapp raise return fp_id_row if engine: engine_disposal(current_skyline_app, engine) if log_msg: del log_msg if trace: del trace return fp_id_row
def create_features_profile(current_skyline_app, requested_timestamp, data_for_metric, context, ionosphere_job, fp_parent_id, fp_generation, fp_learn): """ Add a features_profile to the Skyline ionosphere database table. :param current_skyline_app: Skyline app name :param requested_timestamp: The timestamp of the dir that the features profile data is in :param data_for_metric: The base_name of the metric :param context: The context of the caller :param ionosphere_job: The ionosphere_job name related to creation request valid jobs are ``learn_fp_human``, ``learn_fp_generation``, ``learn_fp_learnt`` and ``learn_fp_automatic``. :param fp_parent_id: The id of the parent features profile that this was learnt from, 0 being an original human generated features profile :param fp_generation: The number of generations away for the original human generated features profile, 0 being an original human generated features profile. :param fp_learn: Whether Ionosphere should learn at use_full_duration_days :type current_skyline_app: str :type requested_timestamp: int :type data_for_metric: str :type context: str :type ionosphere_job: str :type fp_parent_id: int :type fp_generation: int :type fp_learn: boolean :return: fp_id, fp_in_successful, fp_exists, fail_msg, traceback_format_exc :rtype: str, boolean, boolean, str, str """ current_skyline_app_logger = current_skyline_app + 'Log' current_logger = logging.getLogger(current_skyline_app_logger) base_name = data_for_metric.replace(settings.FULL_NAMESPACE, '', 1) if context == 'training_data': log_context = 'training data' ionosphere_learn_job = 'learn_fp_human' if context == 'features_profiles': log_context = 'features profile data' # @added 20170113 - Feature #1854: Ionosphere learn if context == 'ionosphere_learn': log_context = 'learn' current_logger.info('create_features_profile :: %s :: requested for %s at %s' % ( context, str(base_name), str(requested_timestamp))) metric_timeseries_dir = base_name.replace('.', '/') if context == 'training_data': metric_training_data_dir = '%s/%s/%s' % ( settings.IONOSPHERE_DATA_FOLDER, str(requested_timestamp), metric_timeseries_dir) if context == 'features_profiles': metric_training_data_dir = '%s/%s/%s' % ( settings.IONOSPHERE_PROFILES_FOLDER, metric_timeseries_dir, str(requested_timestamp)) # @added 20170113 - Feature #1854: Ionosphere learn if context == 'ionosphere_learn': # @modified 20170116 - Feature #1854: Ionosphere learn # Allowing ionosphere_learn to create a features profile for a training # data set that it has learnt is not anomalous if ionosphere_job != 'learn_fp_automatic': metric_training_data_dir = '%s/%s/%s' % ( settings.IONOSPHERE_LEARN_FOLDER, str(requested_timestamp), metric_timeseries_dir) else: metric_training_data_dir = '%s/%s/%s' % ( settings.IONOSPHERE_DATA_FOLDER, str(requested_timestamp), metric_timeseries_dir) features_file = '%s/%s.tsfresh.input.csv.features.transposed.csv' % ( metric_training_data_dir, base_name) features_profile_dir = '%s/%s' % ( settings.IONOSPHERE_PROFILES_FOLDER, metric_timeseries_dir) ts_features_profile_dir = '%s/%s/%s' % ( settings.IONOSPHERE_PROFILES_FOLDER, metric_timeseries_dir, str(requested_timestamp)) features_profile_created_file = '%s/%s.%s.fp.created.txt' % ( metric_training_data_dir, str(requested_timestamp), base_name) features_profile_details_file = '%s/%s.%s.fp.details.txt' % ( metric_training_data_dir, str(requested_timestamp), base_name) anomaly_check_file = '%s/%s.txt' % (metric_training_data_dir, base_name) trace = 'none' fail_msg = 'none' new_fp_id = False calculated_with_tsfresh = False calculated_time = False fcount = None fsum = None # @added 20170104 - Feature #1842: Ionosphere - Graphite now graphs # Added the ts_full_duration parameter so that the appropriate graphs can be # embedded for the user in the training data page ts_full_duration = '0' if context == 'ionosphere_learn': if not path.isfile(features_profile_details_file): current_logger.error('error :: create_features_profile :: no features_profile_details_file - %s' % features_profile_details_file) return 'none', False, False, fail_msg, trace if path.isfile(features_profile_details_file): current_logger.info('create_features_profile :: getting features profile details from from - %s' % features_profile_details_file) # Read the details file with open(features_profile_details_file, 'r') as f: fp_details_str = f.read() fp_details = literal_eval(fp_details_str) calculated_with_tsfresh = fp_details[1] calculated_time = str(fp_details[2]) fcount = str(fp_details[3]) fsum = str(fp_details[4]) try: ts_full_duration = str(fp_details[5]) except: current_logger.error('error :: create_features_profile :: could not determine the full duration from - %s' % features_profile_details_file) ts_full_duration = '0' if context != 'ionosphere_learn': if ts_full_duration == '0': if path.isfile(anomaly_check_file): current_logger.info('create_features_profile :: determining the full duration from anomaly_check_file - %s' % anomaly_check_file) # Read the details file with open(anomaly_check_file, 'r') as f: anomaly_details = f.readlines() for i, line in enumerate(anomaly_details): if 'full_duration' in line: _ts_full_duration = '%s' % str(line).split("'", 2) full_duration_array = literal_eval(_ts_full_duration) ts_full_duration = str(int(full_duration_array[1])) current_logger.info('create_features_profile :: determined the full duration as - %s' % str(ts_full_duration)) if path.isfile(features_profile_created_file): # Read the created file with open(features_profile_created_file, 'r') as f: fp_created_str = f.read() fp_created = literal_eval(fp_created_str) new_fp_id = fp_created[0] return str(new_fp_id), True, True, fail_msg, trace # Have data if path.isfile(features_file): current_logger.info('create_features_profile :: features_file exists: %s' % features_file) else: trace = traceback.format_exc() current_logger.error(trace) fail_msg = 'error :: create_features_profile :: features_file does not exist: %s' % features_file current_logger.error('%s' % fail_msg) if context == 'training' or context == 'features_profile': # Raise to webbapp I believe to provide traceback to user in UI raise else: return False, False, False, fail_msg, trace features_data = [] with open(features_file, 'rb') as fr: reader = csv.reader(fr, delimiter=',') for i, line in enumerate(reader): feature_name_item = False fname_id = False f_value = False feature_name = str(line[0]) feature_name_item = filter( lambda x: x[1] == feature_name, TSFRESH_FEATURES) if feature_name_item: feature_name_id = feature_name_item[0] if feature_name_item: feature_name_list = feature_name_item[0] fname_id = int(feature_name_list[0]) f_value = str(line[1]) if fname_id and f_value: features_data.append([fname_id, f_value]) # @added 20170113 - Feature #1854: Ionosphere learn - generations # Set the learn generations variables with the IONOSPHERE_LEARN_DEFAULT_ and any # settings.IONOSPHERE_LEARN_NAMESPACE_CONFIG values. These will later be # overridden by any database values determined for the specific metric if # they exist. # Set defaults use_full_duration_days = int(settings.IONOSPHERE_LEARN_DEFAULT_FULL_DURATION_DAYS) valid_learning_duration = int(settings.IONOSPHERE_LEARN_DEFAULT_VALID_TIMESERIES_OLDER_THAN_SECONDS) max_generations = int(settings.IONOSPHERE_LEARN_DEFAULT_MAX_GENERATIONS) max_percent_diff_from_origin = float(settings.IONOSPHERE_LEARN_DEFAULT_MAX_PERCENT_DIFF_FROM_ORIGIN) try: use_full_duration, valid_learning_duration, use_full_duration_days, max_generations, max_percent_diff_from_origin = get_ionosphere_learn_details(current_skyline_app, base_name) learn_full_duration_days = use_full_duration_days except: current_logger.error(traceback.format_exc()) current_logger.error('error :: create_features_profile :: failed to get_ionosphere_learn_details') current_logger.info('create_features_profile :: learn_full_duration_days :: %s days' % (str(learn_full_duration_days))) current_logger.info('create_features_profile :: valid_learning_duration :: %s seconds' % (str(valid_learning_duration))) current_logger.info('create_features_profile :: max_generations :: %s' % (str(max_generations))) current_logger.info('create_features_profile :: max_percent_diff_from_origin :: %s' % (str(max_percent_diff_from_origin))) current_logger.info('create_features_profile :: getting MySQL engine') try: engine, fail_msg, trace = fp_create_get_an_engine(current_skyline_app) current_logger.info(fail_msg) except: trace = traceback.format_exc() current_logger.error(trace) fail_msg = 'error :: create_features_profile :: could not get a MySQL engine' current_logger.error('%s' % fail_msg) if context == 'training' or context == 'features_profile': # Raise to webbapp I believe to provide traceback to user in UI raise else: return False, False, False, fail_msg, trace if not engine: trace = 'none' fail_msg = 'error :: create_features_profile :: engine not obtained' current_logger.error(fail_msg) if context == 'training' or context == 'features_profile': # Raise to webbapp I believe to provide traceback to user in UI raise else: return False, False, False, fail_msg, trace # Get metric details from the database metrics_id = False # Use the learn details as per config metric_learn_full_duration_days = int(use_full_duration_days) metric_learn_valid_ts_older_than = int(valid_learning_duration) metric_max_generations = int(max_generations) metric_max_percent_diff_from_origin = int(max_percent_diff_from_origin) metrics_table = None try: metrics_table, fail_msg, trace = metrics_table_meta(current_skyline_app, engine) current_logger.info(fail_msg) except: trace = traceback.format_exc() current_logger.error('%s' % trace) fail_msg = 'error :: create_features_profile :: failed to get metrics_table meta for %s' % base_name current_logger.error('%s' % fail_msg) if context == 'training' or context == 'features_profile': # @added 20170806 - Bug #2130: MySQL - Aborted_clients # Added missing disposal if engine: fp_create_engine_disposal(current_skyline_app, engine) # Raise to webbapp I believe to provide traceback to user in UI raise else: current_logger.info('create_features_profile :: disposing of any engine') fp_create_engine_disposal(current_skyline_app, engine) return False, False, False, fail_msg, trace current_logger.info('create_features_profile :: metrics_table OK') metric_db_object = None try: connection = engine.connect() # @modified 20161209 - - Branch #922: ionosphere # Task #1658: Patterning Skyline Ionosphere # result = connection.execute('select id from metrics where metric=\'%s\'' % base_name) # for row in result: # while not metrics_id: # metrics_id = row['id'] stmt = select([metrics_table]).where(metrics_table.c.metric == base_name) result = connection.execute(stmt) for row in result: metrics_id = row['id'] # @added 20170113 - Feature #1854: Ionosphere learn - generations # Added Ionosphere LEARN generation related variables try: metric_learn_full_duration_days = int(row['learn_full_duration_days']) metric_learn_valid_ts_older_than = int(row['learn_valid_ts_older_than']) metric_max_generations = int(row['max_generations']) metric_max_percent_diff_from_origin = float(row['max_percent_diff_from_origin']) except: current_logger.error('error :: create_features_profile :: failed to determine learn related values from DB for %s' % base_name) row = result.fetchone() # metric_db_object = row connection.close() current_logger.info('create_features_profile :: determined db metric id: %s' % str(metrics_id)) current_logger.info('create_features_profile :: determined db metric learn_full_duration_days: %s' % str(metric_learn_full_duration_days)) current_logger.info('create_features_profile :: determined db metric learn_valid_ts_older_than: %s' % str(metric_learn_valid_ts_older_than)) current_logger.info('create_features_profile :: determined db metric max_generations: %s' % str(metric_max_generations)) current_logger.info('create_features_profile :: determined db metric max_percent_diff_from_origin: %s' % str(metric_max_percent_diff_from_origin)) except: trace = traceback.format_exc() current_logger.error(trace) fail_msg = 'error :: create_features_profile :: could not determine id of metric from DB: %s' % base_name current_logger.error('%s' % fail_msg) if metric_learn_full_duration_days: learn_full_duration_days = metric_learn_full_duration_days # learn_full_duration = int(learn_full_duration_days) * 86400 if metric_learn_valid_ts_older_than: learn_valid_ts_older_than = metric_learn_valid_ts_older_than if metric_max_generations: max_generations = metric_max_generations if metric_max_percent_diff_from_origin: max_percent_diff_from_origin = metric_max_percent_diff_from_origin current_logger.info('create_features_profile :: generation info - learn_full_duration_days :: %s' % (str(learn_full_duration_days))) current_logger.info('create_features_profile :: generation info - learn_valid_ts_older_than :: %s' % (str(learn_valid_ts_older_than))) current_logger.info('create_features_profile :: generation info - max_generations :: %s' % (str(max_generations))) current_logger.info('create_features_profile :: generation info - max_percent_diff_from_origin :: %s' % (str(max_percent_diff_from_origin))) # @added 20170120 - Feature #1854: Ionosphere learn # Always use the timestamp from the anomaly file use_anomaly_timestamp = int(requested_timestamp) if context == 'ionosphere_learn': if path.isfile(anomaly_check_file): current_logger.info('create_features_profile :: determining the full duration from anomaly_check_file - %s' % anomaly_check_file) # Read the details file with open(anomaly_check_file, 'r') as f: anomaly_details = f.readlines() for i, line in enumerate(anomaly_details): if 'metric_timestamp' in line: _metric_timestamp = '%s' % str(line).split("'", 2) metric_timestamp_array = literal_eval(_metric_timestamp) use_anomaly_timestamp = (int(metric_timestamp_array[1])) current_logger.info('create_features_profile :: determined the anomaly metric_timestamp as - %s' % str(use_anomaly_timestamp)) ionosphere_table = None try: ionosphere_table, fail_msg, trace = ionosphere_table_meta(current_skyline_app, engine) current_logger.info(fail_msg) except: trace = traceback.format_exc() current_logger.error('%s' % trace) fail_msg = 'error :: create_features_profile :: failed to get ionosphere_table meta for %s' % base_name current_logger.error('%s' % fail_msg) if context == 'training' or context == 'features_profile': # Raise to webbapp I believe to provide traceback to user in UI # @added 20170806 - Bug #2130: MySQL - Aborted_clients # Added missing disposal if engine: fp_create_engine_disposal(current_skyline_app, engine) raise else: current_logger.info('create_features_profile :: disposing of any engine') fp_create_engine_disposal(current_skyline_app, engine) return False, False, False, fail_msg, trace current_logger.info('create_features_profile :: ionosphere_table OK') # @added 20170403 - Feature #2000: Ionosphere - validated # Set all learn_fp_human features profiles to validated. fp_validated = 0 if ionosphere_job == 'learn_fp_human': fp_validated = 1 # @added 20170424 - Feature #2000: Ionosphere - validated # Set all generation 0 and 1 as validated if int(fp_generation) <= 1: fp_validated = 1 new_fp_id = False try: connection = engine.connect() # @added 20170113 - Feature #1854: Ionosphere learn # Added learn values parent_id, generation # @modified 20170120 - Feature #1854: Ionosphere learn # Added anomaly_timestamp # @modified 20170403 - Feature #2000: Ionosphere - validated ins = ionosphere_table.insert().values( metric_id=int(metrics_id), full_duration=int(ts_full_duration), anomaly_timestamp=int(use_anomaly_timestamp), enabled=1, tsfresh_version=str(tsfresh_version), calc_time=calculated_time, features_count=fcount, features_sum=fsum, parent_id=fp_parent_id, generation=fp_generation, validated=fp_validated) result = connection.execute(ins) connection.close() new_fp_id = result.inserted_primary_key[0] current_logger.info('create_features_profile :: new ionosphere fp_id: %s' % str(new_fp_id)) except: trace = traceback.format_exc() current_logger.error('%s' % trace) fail_msg = 'error :: create_features_profile :: failed to insert a new record into the ionosphere table for %s' % base_name current_logger.error('%s' % fail_msg) if context == 'training' or context == 'features_profile': # @added 20170806 - Bug #2130: MySQL - Aborted_clients # Added missing disposal if engine: fp_create_engine_disposal(current_skyline_app, engine) # Raise to webbapp I believe to provide traceback to user in UI raise else: current_logger.info('create_features_profile :: disposing of any engine') fp_create_engine_disposal(current_skyline_app, engine) return False, False, False, fail_msg, trace if not RepresentsInt(new_fp_id): trace = traceback.format_exc() current_logger.error('%s' % trace) fail_msg = 'error :: create_features_profile :: unknown new ionosphere new_fp_id for %s' % base_name current_logger.error('%s' % fail_msg) if context == 'training' or context == 'features_profile': # @added 20170806 - Bug #2130: MySQL - Aborted_clients # Added missing disposal if engine: fp_create_engine_disposal(current_skyline_app, engine) # Raise to webbapp I believe to provide traceback to user in UI raise else: current_logger.info('create_features_profile :: disposing of any engine') fp_create_engine_disposal(current_skyline_app, engine) return False, False, False, fail_msg, trace # Create z_fp_<metric_id> table fp_table_created = False fp_table_name = 'z_fp_%s' % str(metrics_id) try: fp_meta = MetaData() # @modified 20161222 - Task #1812: z_fp table type # Changed to InnoDB from MyISAM as no files open issues and MyISAM clean # up, there can be LOTS of file_per_table z_fp_ tables/files without # the MyISAM issues. z_fp_ tables are mostly read and will be shuffled # in the table cache as required. fp_metric_table = Table( fp_table_name, fp_meta, Column('id', Integer, primary_key=True), Column('fp_id', Integer, nullable=False, key='fp_id'), Column('feature_id', Integer, nullable=False), Column('value', DOUBLE(), nullable=True), mysql_charset='utf8', mysql_key_block_size='255', mysql_engine='InnoDB') fp_metric_table.create(engine, checkfirst=True) fp_table_created = True except: trace = traceback.format_exc() current_logger.error('%s' % trace) fail_msg = 'error :: create_features_profile :: failed to create table - %s' % fp_table_name current_logger.error('%s' % fail_msg) if context == 'training' or context == 'features_profile': # @added 20170806 - Bug #2130: MySQL - Aborted_clients # Added missing disposal if engine: fp_create_engine_disposal(current_skyline_app, engine) # Raise to webbapp I believe to provide traceback to user in UI raise else: current_logger.info('create_features_profile :: %s - automated so the table should exists continuing' % context) if not fp_table_created: trace = traceback.format_exc() current_logger.error('%s' % trace) fail_msg = 'error :: create_features_profile :: failed to determine True for create table - %s' % fp_table_name current_logger.error('%s' % fail_msg) if context == 'training' or context == 'features_profile': # @added 20170806 - Bug #2130: MySQL - Aborted_clients # Added missing disposal if engine: fp_create_engine_disposal(current_skyline_app, engine) # Raise to webbapp I believe to provide traceback to user in UI raise else: current_logger.info('create_features_profile :: %s - automated so the table should exists continuing' % context) # Insert features and values insert_statement = [] for fname_id, f_value in features_data: insert_statement.append({'fp_id': new_fp_id, 'feature_id': fname_id, 'value': f_value},) if insert_statement == []: trace = traceback.format_exc() current_logger.error('%s' % trace) fail_msg = 'error :: create_features_profile :: empty insert_statement for %s inserts' % fp_table_name current_logger.error('%s' % fail_msg) # raise # else: # feature_count = sum(1 for x in a if isinstance(x, insert_statement)) # current_logger.info( # 'fp_id - %s - %s feature values in insert_statement for %s ' % # (str(feature_count), str(new_fp_id), fp_table_name)) # feature_count = sum(1 for x in a if isinstance(x, insert_statement)) # current_logger.info( # 'fp_id - %s - feature values in insert_statement for %s ' % # (str(new_fp_id), fp_table_name)) try: connection = engine.connect() connection.execute(fp_metric_table.insert(), insert_statement) connection.close() current_logger.info('create_features_profile :: fp_id - %s - feature values inserted into %s' % (str(new_fp_id), fp_table_name)) except: trace = traceback.format_exc() current_logger.error('%s' % trace) fail_msg = 'error :: create_features_profile :: failed to insert a feature values into %s' % fp_table_name current_logger.error('%s' % fail_msg) if context == 'training' or context == 'features_profile': # @added 20170806 - Bug #2130: MySQL - Aborted_clients # Added missing disposal if engine: fp_create_engine_disposal(current_skyline_app, engine) # Raise to webbapp I believe to provide traceback to user in UI raise else: current_logger.info('create_features_profile :: %s - automated so the table should exists continuing' % context) # Create metric ts table if not exists ts_<metric_id> # Create z_ts_<metric_id> table # @modified 20170121 - Feature #1854: Ionosphere learn - generations # TODO Adding the option to not save timeseries to DB, as default? # ts_table_created = False ts_table_name = 'z_ts_%s' % str(metrics_id) try: ts_meta = MetaData() # @modified 20161222 - Task #1812: z_fp table type # Changed to InnoDB from MyISAM as no files open issues and MyISAM clean # up, there can be LOTS of file_per_table z_fp_ tables/files without # the MyISAM issues. z_fp_ tables are mostly read and will be shuffled # in the table cache as required. ts_metric_table = Table( ts_table_name, ts_meta, Column('id', Integer, primary_key=True), Column('fp_id', Integer, nullable=False, key='fp_id'), Column('timestamp', Integer, nullable=False), Column('value', DOUBLE(), nullable=True), mysql_charset='utf8', mysql_key_block_size='255', mysql_engine='InnoDB') ts_metric_table.create(engine, checkfirst=True) # ts_table_created = True current_logger.info('create_features_profile :: metric ts table created OK - %s' % (ts_table_name)) except: trace = traceback.format_exc() current_logger.error('%s' % trace) fail_msg = 'error :: create_features_profile :: failed to create table - %s' % ts_table_name current_logger.error('%s' % fail_msg) if context == 'training' or context == 'features_profile': # @added 20170806 - Bug #2130: MySQL - Aborted_clients # Added missing disposal if engine: fp_create_engine_disposal(current_skyline_app, engine) # Raise to webbapp I believe to provide traceback to user in UI raise else: current_logger.info('create_features_profile :: %s - automated so the table should exists continuing' % context) # Insert timeseries that the features profile was created from raw_timeseries = [] anomaly_json = '%s/%s.json' % (metric_training_data_dir, base_name) if path.isfile(anomaly_json): current_logger.info('create_features_profile :: metric anomaly json found OK - %s' % (anomaly_json)) try: # Read the timeseries json file with open(anomaly_json, 'r') as f: raw_timeseries = f.read() except: trace = traceback.format_exc() current_logger.error(trace) fail_msg = 'error :: create_features_profile :: failed to read timeseries data from %s' % anomaly_json current_logger.error('%s' % (fail_msg)) fail_msg = 'error: failed to read timeseries data from %s' % anomaly_json # end = timer() if context == 'training' or context == 'features_profile': # @added 20170806 - Bug #2130: MySQL - Aborted_clients # Added missing disposal if engine: fp_create_engine_disposal(current_skyline_app, engine) # Raise to webbapp I believe to provide traceback to user in UI raise else: trace = 'none' fail_msg = 'error: file not found - %s' % (anomaly_json) current_logger.error(fail_msg) # raise # Convert the timeseries to csv timeseries_array_str = str(raw_timeseries).replace('(', '[').replace(')', ']') timeseries = literal_eval(timeseries_array_str) datapoints = timeseries validated_timeseries = [] for datapoint in datapoints: try: new_datapoint = [str(int(datapoint[0])), float(datapoint[1])] validated_timeseries.append(new_datapoint) # @modified 20170913 - Task #2160: Test skyline with bandit # Added nosec to exclude from bandit tests except: # nosec continue insert_statement = [] for ts, value in validated_timeseries: insert_statement.append({'fp_id': new_fp_id, 'timestamp': ts, 'value': value},) try: connection = engine.connect() connection.execute(ts_metric_table.insert(), insert_statement) connection.close() current_logger.info('create_features_profile :: fp_id - %s - timeseries inserted into %s' % (str(new_fp_id), ts_table_name)) except: trace = traceback.format_exc() current_logger.error('%s' % trace) fail_msg = 'error :: create_features_profile :: failed to insert the timeseries into %s' % ts_table_name current_logger.error('%s' % fail_msg) if context == 'training' or context == 'features_profile': # @added 20170806 - Bug #2130: MySQL - Aborted_clients # Added missing disposal if engine: fp_create_engine_disposal(current_skyline_app, engine) raise else: current_logger.info('create_features_profile :: %s - automated so the table should exists continuing' % context) # Create a created features profile file try: # data = '[%s, %s, ]' % (new_fp_id, str(int(time.time()))) # write_data_to_file(skyline_app, features_profile_created_file, 'w', data) # @modified 20170115 - Feature #1854: Ionosphere learn - generations # Added parent_id and generation data = '[%s, %s, \'%s\', %s, %s, %s, %s, %s, %s]' % ( new_fp_id, str(int(time.time())), str(tsfresh_version), str(calculated_time), str(fcount), str(fsum), str(ts_full_duration), str(fp_parent_id), str(fp_generation)) write_data_to_file(current_skyline_app, features_profile_created_file, 'w', data) except: trace = traceback.format_exc() current_logger.error('%s' % trace) fail_msg = 'error :: create_features_profile :: failed to write fp.created file' current_logger.error('%s' % fail_msg) # Set ionosphere_enabled for the metric try: # update_statement = 'UPDATE metrics SET ionosphere_enabled=1 WHERE id=%s' % str(metrics_id) connection = engine.connect() # result = connection.execute('UPDATE metrics SET ionosphere_enabled=1 WHERE id=%s' % str(metrics_id)) # connection.execute(ts_metric_table.insert(), insert_statement) connection.execute( metrics_table.update( metrics_table.c.id == metrics_id).values(ionosphere_enabled=1)) connection.close() current_logger.info('create_features_profile :: ionosphere_enabled set on metric id: %s' % str(metrics_id)) except: trace = traceback.format_exc() current_logger.error(trace) fail_msg = 'error :: create_features_profile :: could not update metrics table and set ionosphere_enabled on id %s' % str(metrics_id) current_logger.error('%s' % fail_msg) # raise # Copy data from training data dir to features_profiles dir if not path.isdir(ts_features_profile_dir): mkdir_p(ts_features_profile_dir) if path.isdir(ts_features_profile_dir): current_logger.info('create_features_profile :: fp_id - %s - features profile dir created - %s' % (str(new_fp_id), ts_features_profile_dir)) # src_files = os.listdir(src) # for file_name in src_files: # full_file_name = path.join(src, file_name) # if (path.isfile(full_file_name)): # shutil.copy(full_file_name, dest) data_files = [] try: glob_path = '%s/*.*' % metric_training_data_dir data_files = glob.glob(glob_path) except: trace = traceback.format_exc() current_logger.error('%s' % trace) current_logger.error('error :: create_features_profile :: glob - fp_id - %s - training data not copied to %s' % (str(new_fp_id), ts_features_profile_dir)) for i_file in data_files: try: shutil.copy(i_file, ts_features_profile_dir) current_logger.info('create_features_profile :: fp_id - %s - training data copied - %s' % (str(new_fp_id), i_file)) except shutil.Error as e: trace = traceback.format_exc() current_logger.error('%s' % trace) current_logger.error('error :: create_features_profile :: shutil error - fp_id - %s - training data not copied to %s' % (str(new_fp_id), ts_features_profile_dir)) current_logger.error('error :: create_features_profile :: %s' % (e)) # Any error saying that the directory doesn't exist except OSError as e: trace = traceback.format_exc() current_logger.error('%s' % trace) current_logger.error('error :: create_features_profile :: OSError error - fp_id - %s - training data not copied to %s' % (str(new_fp_id), ts_features_profile_dir)) current_logger.error('error :: create_features_profile :: %s' % (e)) current_logger.info('create_features_profile :: fp_id - %s - training data copied to %s' % (str(new_fp_id), ts_features_profile_dir)) else: current_logger.error('error :: create_features_profile :: fp_id - %s - training data not copied to %s' % (str(new_fp_id), ts_features_profile_dir)) current_logger.info('create_features_profile :: disposing of any engine') try: if engine: fp_create_engine_disposal(current_skyline_app, engine) else: current_logger.info('create_features_profile :: no engine to dispose of' % (str(new_fp_id), ts_features_profile_dir)) except: trace = traceback.format_exc() current_logger.error('%s' % trace) current_logger.error('error :: create_features_profile :: OSError error - fp_id - %s - training data not copied to %s' % (str(new_fp_id), ts_features_profile_dir)) # @added 20170113 - Feature #1854: Ionosphere learn - Redis ionosphere.learn.work namespace # Ionosphere learn needs Redis works sets # When a features profile is created there needs to be work added to a Redis # set. When a human makes a features profile, we want Ionosphere to make a # use_full_duration_days features profile valid_learning_duration (e.g. # 3361) later. if settings.IONOSPHERE_LEARN and new_fp_id: create_redis_work_item = False if context == 'training_data' and ionosphere_job == 'learn_fp_human': create_redis_work_item = True # @modified 20170120 - Feature #1854: Ionosphere learn - generations # Added fp_learn parameter to allow the user to not learn the # use_full_duration_days if not fp_learn: create_redis_work_item = False current_logger.info('fp_learn is False not adding an item to Redis ionosphere.learn.work set') if ionosphere_job == 'learn_fp_automatic': create_redis_work_item = True # @added 20170131 - Feature #1886 Ionosphere learn - child like parent with evolutionary maturity # TODO: here a check may be required to evaluate whether the origin_fp_id # had a use_full_duration features profile created, however # due to the fact that it is in learn, suggests that it did # have, not 100% sure. origin_fp_id_was_allowed_to_learn = False child_use_full_duration_count_of_origin_fp_id = 1 # TODO: Determine the state # child_use_full_duration_count_of_origin_fp_id = SELECT COUNT(id) FROM ionosphere WHERE parent_id=origin_fp_id AND full_duration=use_full_duration if child_use_full_duration_count_of_origin_fp_id == 0: current_logger.info('the origin parent was not allowed to learn not adding to Redis ionosphere.learn.work set') create_redis_work_item = False if create_redis_work_item: try: current_logger.info( 'adding work to Redis ionosphere.learn.work set - [\'Soft\', \'%s\', %s, \'%s\', %s, %s] to make a learn features profile later' % ( str(ionosphere_job), str(requested_timestamp), base_name, str(new_fp_id), str(fp_generation))) redis_conn = StrictRedis(unix_socket_path=settings.REDIS_SOCKET_PATH) redis_conn.sadd('ionosphere.learn.work', ['Soft', str(ionosphere_job), int(requested_timestamp), base_name, int(new_fp_id), int(fp_generation)]) except: current_logger.error(traceback.format_exc()) current_logger.error( 'error :: failed adding work to Redis ionosphere.learn.work set - [\'Soft\', \'%s\', %s, \'%s\', %s, %s] to make a learn features profile later' % ( str(ionosphere_job), str(requested_timestamp), base_name, str(new_fp_id), str(fp_generation))) # @added 20170806 - Bug #2130: MySQL - Aborted_clients # Added missing disposal if engine: fp_create_engine_disposal(current_skyline_app, engine) return str(new_fp_id), True, False, fail_msg, trace
def get_ionosphere_fp_ids_for_full_duration( current_skyline_app, metric_id, full_duration=0, enabled=True): """ Return the ionosphere table database rows as a dict """ function_str = 'functions.database.queries.get_ionosphere_fp_ids_for_full_duration' log_msg = None trace = None if enabled: enabled = 1 else: enabled = 0 current_skyline_app_logger = current_skyline_app + 'Log' current_logger = logging.getLogger(current_skyline_app_logger) fp_ids_full_duration = {} try: engine, fail_msg, trace = get_engine(current_skyline_app) except Exception as e: trace = traceback.format_exc() current_logger.error(trace) fail_msg = 'error :: %s :: could not get a MySQL engine - %s' % (function_str, e) current_logger.error('%s' % fail_msg) if engine: engine_disposal(current_skyline_app, engine) if current_skyline_app == 'webapp': # Raise to webapp raise return fp_ids_full_duration try: ionosphere_table, log_msg, trace = ionosphere_table_meta(current_skyline_app, engine) except Exception as e: current_logger.error(traceback.format_exc()) current_logger.error('error :: %s :: failed to get ionosphere_table meta for metric id %s - %s' % ( function_str, str(metric_id), e)) if engine: engine_disposal(engine) if current_skyline_app == 'webapp': # Raise to webapp raise return fp_ids_full_duration try: connection = engine.connect() if full_duration: stmt = select([ionosphere_table]).\ where(ionosphere_table.c.metric_id == int(metric_id)).\ where(ionosphere_table.c.full_duration == int(full_duration)).\ where(ionosphere_table.c.enabled == enabled) else: stmt = select([ionosphere_table]).\ where(ionosphere_table.c.metric_id == int(metric_id)).\ where(ionosphere_table.c.enabled == enabled) results = connection.execute(stmt) if results: for row in results: fp_id = row['id'] fp_ids_full_duration[fp_id] = row connection.close() except Exception as e: current_logger.error(traceback.format_exc()) current_logger.error('error :: %s :: could not get ionosphere rows for metric id %s - %s' % ( function_str, str(metric_id), e)) if engine: engine_disposal(engine) if current_skyline_app == 'webapp': # Raise to webapp raise return fp_ids_full_duration if engine: engine_disposal(current_skyline_app, engine) if log_msg: del log_msg if trace: del trace return fp_ids_full_duration