Source code for haive.core.common.mixins.rich_logger_mixin
"""Rich logging mixin for enhanced console output.This module provides a mixin for adding rich console logging capabilities toPydantic models. It leverages the Rich library to enable colorized, formattedconsole output with features like syntax highlighting and rich traceback display.Usage: from pydantic import BaseModel from haive.core.common.mixins import RichLoggerMixin class MyProcessor(RichLoggerMixin, BaseModel): name: str def process(self, data): self._info(f"Processing data with {self.name}") try: # Processing logic result = self._process_data(data) self._debug(f"Processed result: {result}") return result except Exception as e: self._error(f"Failed to process data: {e}") raise # Create with debug enabled processor = MyProcessor(name="TestProcessor", debug=True) processor.process({"test": "data"})"""importloggingfrompydanticimportBaseModel,PrivateAttrfromrich.consoleimportConsolefromrich.loggingimportRichHandler
[docs]classRichLoggerMixin(BaseModel):"""Mixin that provides rich console logging capabilities. This mixin adds a configurable logger with rich formatting to any Pydantic model. It creates a logger named after the class, configures it with Rich's handler for pretty console output, and provides convenience methods for different log levels with appropriate styling. Attributes: debug: Boolean flag to control debug output visibility. """# Debug flag to control debug outputdebug:bool=False# Private logger instance_logger:logging.Logger|None=PrivateAttr(default=None)_logger_setup:bool=PrivateAttr(default=False)@propertydeflogger(self)->logging.Logger:"""Get or create logger with rich handler. This property lazily initializes a logger with a Rich handler, creating it only when first accessed. The logger is named using the module and class name for proper log categorization. Returns: Configured logging.Logger instance with Rich formatting. """ifself._loggerisNoneornotself._logger_setup:# Create logger with module.class namelogger_name=f"{self.__class__.__module__}.{self.__class__.__name__}"self._logger=logging.getLogger(logger_name)# Only add handler if not already presentifnotself._logger.handlers:# Create rich handler with clean formathandler=RichHandler(console=Console(stderr=True),show_time=True,show_path=False,# Keep it cleanrich_tracebacks=True,)handler.setFormatter(logging.Formatter("%(message)s"))self._logger.addHandler(handler)self._logger.setLevel(logging.INFO)self._logger_setup=Truereturnself._loggerdef_debug(self,msg:str,*args,**kwargs)->None:"""Debug logging - only shows if debug=True. Args: msg: The message to log. *args: Additional positional arguments for the logger. **kwargs: Additional keyword arguments for the logger. """ifself.debug:self.logger.debug(f"[dim cyan]{self.__class__.__name__}:[/] {msg}",*args,**kwargs)def_info(self,msg:str,*args,**kwargs)->None:"""Info logging with standard formatting. Args: msg: The message to log. *args: Additional positional arguments for the logger. **kwargs: Additional keyword arguments for the logger. """self.logger.info(msg,*args,**kwargs)def_warning(self,msg:str,*args,**kwargs)->None:"""Warning logging with yellow highlighting. Args: msg: The message to log. *args: Additional positional arguments for the logger. **kwargs: Additional keyword arguments for the logger. """self.logger.warning(f"[yellow]{msg}[/]",*args,**kwargs)def_error(self,msg:str,*args,**kwargs)->None:"""Error logging with red highlighting. Args: msg: The message to log. *args: Additional positional arguments for the logger. **kwargs: Additional keyword arguments for the logger. """self.logger.error(f"[red]{msg}[/]",*args,**kwargs)