def gather_initial_info(log_dir: str):
    """ Log one time info

    For example, CPU/GPU info, version of this package, region, datetime for start of experiment,
    CO2 estimate data.

    :param log_dir: the log directory to write to
    :return: gathered information
    """

    info_path = safe_file_path(os.path.join(log_dir, INFOPATH))

    data = {}

    # Gather all the one-time info specified by the appropriate router
    for info_ in INITIAL_INFO:
        key = info_["name"]
        compatabilities = info_["compatability"]
        if _validate_compatabilities(compatabilities):
            data[key] = info_["routing"]["function"]()

    with open(info_path, "wb") as info_file:
        pickle.dump(data, info_file)

    # touch datafile to clear out any past cruft and write headers

    data_path = safe_file_path(os.path.join(log_dir, DATAPATH))
    if os.path.exists(data_path):
        os.remove(data_path)

    Path(data_path).touch()

    return data
def gather_initial_info(log_dir):
    # TODO: log one time info: CPU/GPU info, version of this package, region, datetime for start of experiment, CO2 estimate data.
    # this will be used to build a latex table later.

    info_path = safe_file_path(os.path.join(log_dir, INFOPATH))

    data = {}

    # Gather all the one-time info specified by the appropriate router
    for info_ in INITIAL_INFO:
        key = info_["name"]
        compatabilities = info_["compatability"]
        if _validate_compatabilities(compatabilities):
            data[key] = info_["routing"]["function"]()

    with open(info_path, "wb") as info_file:
        pickle.dump(data, info_file)

    # touch datafile to clear out any past cruft and write headers

    data_path = safe_file_path(os.path.join(log_dir, DATAPATH))
    if os.path.exists(data_path):
        os.remove(data_path)

    Path(data_path).touch()

    return data
    def _setup_logging(self):
        """
        Private function to set up logging handlers

        :return:
        """
        # Create a custom logger
        logger = logging.getLogger(
            "experiment_impact_tracker.compute_tracker.ImpactTracker")

        # Create handlers
        c_handler = logging.StreamHandler()
        f_handler = logging.FileHandler(
            safe_file_path(
                os.path.join(self.logdir, BASE_LOG_PATH,
                             "impact_tracker_log.log")))
        c_handler.setLevel(logging.WARNING)
        f_handler.setLevel(logging.ERROR)

        # Create formatters and add it to handlers
        c_format = logging.Formatter("%(name)s - %(levelname)s - %(message)s")
        f_format = logging.Formatter(
            "%(asctime)s - %(name)s - %(levelname)s - %(message)s")
        c_handler.setFormatter(c_format)
        f_handler.setFormatter(f_format)

        # Add handlers to the logger
        logger.addHandler(c_handler)
        logger.addHandler(f_handler)
        self.logger = logger
def _sample_and_log_power(log_dir, initial_info, logger=None):
    """
    Iterates over compatible metrics and logs the relevant information.

    :param log_dir: The log directory to use
    :param initial_info: Any initial information that was gathered
    :param logger: A logger to use
    :return: collected data
    """
    current_process = psutil.Process(os.getppid())
    process_ids = [current_process.pid] + [
        child.pid for child in current_process.children(recursive=True)
    ]
    process_ids = list(
        set(process_ids))  # dedupe so that we don't double count by accident

    required_headers = _get_compatible_data_headers(
        get_current_region_info_cached()[0])

    header_information = {}

    # for all required headers make sure that we hit the corresponding function which gets that info
    # some functions return multiple values in one call (for example one RAPL reading could get multiple things)
    # so in that case we fill in information on multiple headers at once even though they have the same routing
    # information.
    for header in required_headers:
        if header["name"] in header_information.keys():
            # we already got that info from a multi-return function call
            continue

        start = time.time()

        results = header["routing"]["function"](
            process_ids,
            logger=logger,
            region=initial_info["region"]["id"],
            log_dir=log_dir,
        )

        end = time.time()
        logger.info("Datapoint {} took {} seconds".format(
            header["name"], (end - start)))

        if isinstance(results, dict):
            # if we return a dict of results, could account for multiple headers
            for header_name, item in results.items():
                header_information[header_name] = item
        else:
            header_information[header["name"]] = results
    header_information["process_ids"] = process_ids
    # once we have gotten all the required info through routing calls for all headers, we log it
    log_path = safe_file_path(os.path.join(log_dir, DATAPATH))
    try:
        write_json_data_to_file(log_path, header_information)
    except:
        logger.error(header_information)
        raise
    return header_information