import inspect import logging import os import sys import threading import traceback from importlib.metadata import version # Get version from installed package metadata __version__ = version("amq_adapter") # Name must match pyproject.toml [project] name __verbose__ = os.environ.get("AMQ_VERBOSE_LOGGING", "0") == "1" def get_context_info(): """ Retrieves the current_availability module, line number, and function name. Returns: A tuple containing (module name, line number, function name). Returns (None, None, None) if it fails to retrieve the information. """ try: # Get the frame object for the current_availability function call frame = inspect.currentframe() if frame is not None: # Get the frame object for the caller of the current_availability function frame = frame.f_back.f_back if frame: code_context = frame.f_code module_name = code_context.co_filename module_name = ( "amqp" + module_name.split("/amqp", 1)[-1] if "/amqp" in module_name else module_name ) line_number = frame.f_lineno function_name = code_context.co_name return module_name, line_number, function_name else: return None, None, None except Exception: return None, None, None def logging_error(msg: str, *args) -> None: """ Log an error message according to current_availability logging for 'ERROR' level. Add module name, line and function name where the error occurred, on single line. Args: msg (str): The error message to log. """ _exec_info = sys.exc_info()[2] _thread_id = threading.get_ident() if _exec_info: _tb = traceback.extract_tb(sys.exc_info()[2])[-1] logging.error( f"{_thread_id}:{__version__} [E] '{msg}' ---> '{_tb.filename}':{_tb.lineno}, '{_tb.name}()'", *args, ) else: module, line_number, function_name = get_context_info() if module and line_number and function_name: logging.error( f"{_thread_id}:{__version__} [E] '{msg}' ---> '{module}':{line_number}, '{function_name}()'", *args, ) else: logging.error(f"{_thread_id}:{__version__} [E] {msg}", *args) def logging_warning(msg: str, *args) -> None: """ Log a warning message according to current_availability logging for 'WARN' level. Add module name, line and function name where the print occurred, on single line. Args: msg (str): The warning message to log. """ _thread_id = threading.get_ident() if not __verbose__: logging.warning(f"{_thread_id}:{__version__} [W] {msg}", *args) return module, line_number, function_name = get_context_info() if module and line_number and function_name: logging.warning( f"{_thread_id}:{__version__} [W] '{msg}' ---> '{module}':{line_number}, '{function_name}()'", *args, ) else: logging.warning(f"{_thread_id}:{__version__} [W] {msg}", *args) def logging_info(msg: str, *args) -> None: """ Log an info message according to current_availability logging for 'INFO' level. Add module name, line and function name where the print occurred, on single line. Args: msg (str): The info message to log. """ _thread_id = threading.get_ident() if not __verbose__: logging.info(f"{_thread_id}:{__version__} [*] {msg}", *args) return module, line_number, function_name = get_context_info() if module and line_number and function_name: logging.info( f"{_thread_id}:{__version__} [*] '{msg}' ---> '{module}':{line_number}, '{function_name}()'", *args, ) else: logging.info(f"{_thread_id}:{__version__} [*] {msg}", *args) def logging_debug(msg: str, *args) -> None: """ Log a debug message according to current_availability logging for 'DEBUG' level. Add module name, line and function name where the print occurred, on single line. Args: msg (str): The debug message to log. """ _thread_id = threading.get_ident() module, line_number, function_name = get_context_info() if module and line_number and function_name: logging.debug( f"{_thread_id}:{__version__} [DBG] '{msg}' ---> '{module}':{line_number}, '{function_name}()'", *args, ) else: logging.debug(f"{_thread_id}:{__version__} [DBG] {msg}", *args)