Files
blender-portable-repo/scripts/addons/asset_pipeline/logging.py
T
2026-03-17 14:58:51 -06:00

117 lines
3.4 KiB
Python

# SPDX-FileCopyrightText: 2021 Blender Studio Tools Authors
#
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
from . import prefs, constants
def get_logger(name="asset_pipeline"):
logger = logging.getLogger(name)
addon_prefs = prefs.get_addon_prefs()
logging_level = int(addon_prefs.logger_level)
# Return logger if it has already been setup
if len(logger.handlers) > 0:
return logger
# create console handler and set level to debug
logger.setLevel(logging_level)
ch = logging.StreamHandler()
ch.setLevel(logging_level)
# create formatter
formatter = logging.Formatter('%(levelname)s-%(name)s: %(message)s')
# add formatter to ch
ch.setFormatter(formatter)
# add ch to logger
logger.addHandler(ch)
return logger
PROFILE_KEYS = {
"IMPORT": "To import Collection & add suffixes",
"MAPPING": "To create Asset Mapping",
"TRANSFER_DATA": "To apply all Transferable Data",
"OBJECTS": "To remap all Obejcts",
"INDEXES": "To restore Active Indexes on all Objects",
"COLLECTIONS": "To remap all Collections",
"SHARED_IDS": "To remap all Shared IDs",
"MERGE": "To complete entire merge process",
"TOTAL": "Total time to sync this direction",
}
TD_KEYS = [type for type in constants.TRANSFER_DATA_TYPES]
INFO_KEYS = ["TOTAL"] # Profile Keys to print in the logger's info mode
_profiler_instance = None
def get_profiler():
global _profiler_instance
if not _profiler_instance:
_profiler_instance = Profiler()
return _profiler_instance
class Profiler:
def __init__(self) -> None:
self.pull_profiles = {}
self.push_profiles = {}
self._logger = get_logger()
def add(self, elapsed_time: int, key: str):
if self._is_push:
profiles = self.push_profiles
else: # is pull
profiles = self.pull_profiles
if key not in profiles:
profiles[key] = elapsed_time
else:
profiles[key] += elapsed_time
def log_all(self):
self.log_profiles("PULL", self.pull_profiles)
self.log_profiles("PUSH", self.push_profiles)
def log_profiles(self, direction: str, profiles: dict):
if profiles == {}:
return
for key, value in profiles.items():
seconds = self.get_non_scientific_number(value)
# Special case for transfer data keys
if key in TD_KEYS:
name = constants.TRANSFER_DATA_TYPES[key][0]
self._logger.debug(
f"{direction} TD: {name.upper()} - {seconds} seconds to transfer {name} data for all objects"
)
continue
msg = f"{direction} {key} - {seconds} seconds {PROFILE_KEYS[key]}"
if key in INFO_KEYS:
self._logger.info(msg)
else:
self._logger.debug(msg)
def get_non_scientific_number(self, x: float):
float_str = f'{x:.64f}'.rstrip('0')
significant_digits = 0
for index, c in enumerate(float_str):
if significant_digits == 3:
return float_str[:index:]
if c != "0" and c != ".":
significant_digits += 1
def reset(self):
self.pull_profiles = {}
self._is_push = False
self._logger = get_logger()
def set_push(self, is_push=True):
self._is_push = is_push