From bbd4a64d905725551214db91ea56b03a2c52e173 Mon Sep 17 00:00:00 2001 From: OdyAsh Date: Thu, 3 Apr 2025 14:35:17 +0200 Subject: [PATCH 1/3] Enhance logging and stdin/stdout interface - Add enhanced logging with colorful output and detailed exception handling - Implement rich exception formatting with source code context - Add display of local variables in exception tracebacks - Improve stdio interface with streaming option for terminal usage - Add sample logging exception output for reference --- .../sample_logging_exception_output.png | Bin 0 -> 74599 bytes src/ansari/ansari_logger.py | 190 +++++++++++++++++- src/ansari/app/main_stdio.py | 26 ++- src/ansari/presenters/stdio_presenter.py | 14 +- 4 files changed, 217 insertions(+), 13 deletions(-) create mode 100644 docs/code_outputs/sample_logging_exception_output.png diff --git a/docs/code_outputs/sample_logging_exception_output.png b/docs/code_outputs/sample_logging_exception_output.png new file mode 100644 index 0000000000000000000000000000000000000000..f5babb0c76bd3d077ce2596de243918a112bfa59 GIT binary patch literal 74599 zcmb@u1yGz@l(yT1;2sF>5G1%e1Si1*3GVLh9^4@WY21Rl2X}XO*T!8N{^sP&)J)aA zcc$w8RZUS}?`pdH+k3CQ*89ARPz5A^s*5p1Q@8~^~+uGb%^KAQqV0N~~KXE9-A zSM4LPkMet!##1C83qRi~bTQ#Kp~YdmP?N~hquZE$h6x0hXI>s+CxNG>LtDrZ@;;PpFc1$m={Q5%}-Vun&p zhJ=wK-IJAEKP!GKHvTrkQ)~|Yq{^ScGOJ)d>$!V540%G3W6$%;z|atqA1VBgzYi%@ z&spfV!sve=V*0{SB>#EwL-haZh5d0aplk(~v@iNU-km&Ft${R-P>9^l_2fGG{J~*1 zCsZ_hN%Hm6#K8zCg#zJuyx$7TymK;Db$|~hUXGlZr3`8`3LbAzaE8_E(Ml`rJ%K~Z z(kr{>7Vb`m4A`1R-XQ5*#!bO39O_+nN{B`qIn64C7WOW~4zXpUqFCU!+wdF%v%#Ay z<*5sPADRTkuWtlq1MtLqXXO>^>U!O|-xLV`ruU)CZdAOuxDc83=ln9na$*0Tsz%6! z$PW|RP-#jX~L|Ujl*=m^-S3Y* SX^A2nLZI_#z|BxcH(d*!{p24=EW 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

;ZNu@;H3`7%8GEv}5qC&88hIZUec?d3 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 a@Ba@I4B%^F>Hx(60000 str: + """ + Format exception info with colorful traceback and variable values. + + Example output: + ``` + list indices must be integers or slices, not str + TypeError: list indices must be integers or slices, not str + Traceback (most recent call last): + File "path/to/file1.py", line 328, in + > + Local variables: + var_1 = val_1 + var_2 = val_2 + /// /// /// + /// /// /// + ... and x more + File "path/to/file2.py", line 669, in + + Local variables: + var_1 = val_1 + /// /// /// + ... and x more + File /////////////////////////////////////// + ///////////////////// + Local variables: + /// /// /// + + and so on... + ``` + """ + exc_type, exc_value, tb = exc_info + + # Format the exception header + exc_name = exc_type.__name__ + exc_message = str(exc_value) + header = self.colorize(f"{exc_name}: {exc_message}", Colors.LEVEL_COLORS["ERROR"]) + + # Process the traceback + tb_frames = [] + current_tb = tb + while current_tb: + frame = current_tb.tb_frame + filename = frame.f_code.co_filename + lineno = current_tb.tb_lineno + function = frame.f_code.co_name + locals_dict = frame.f_locals.copy() + tb_frames.append((filename, lineno, function, locals_dict)) + current_tb = current_tb.tb_next + + # Generate enhanced traceback with variable information + lines = [header] + lines.append(self.colorize("Traceback (most recent call last):", Colors.BOLD)) + + for filename, lineno, function, locals_dict in tb_frames: + frame_header = self.colorize(f'File "{filename}", line {lineno}, in {function}', Colors.YELLOW) + lines.append(f" {frame_header}") + + # Try to get the source line + try: + source_line = linecache_getline(filename, lineno).strip() + if source_line: + lines.append(self.colorize(f" {source_line}", Colors.WHITE)) + except Exception: + pass # Skip if we can't get the source line + + # Add local variables (similar to loguru's style) + var_lines = [] + for name, value in locals_dict.items(): + # Skip magic and module variables to reduce noise + if name.startswith("__") or name.startswith("_["): + continue + try: + # Safer way to get string representation + if isinstance(value, (str, int, float, bool, type(None))): + val_str = repr(value) + else: + val_str = str(value) + + if len(val_str) > 50: + val_str = val_str[:47] + "..." + var_lines.append(f"{name} = {val_str}") + except Exception: + var_lines.append(f"{name} = ") + + if var_lines: + vars_header = self.colorize(" Local variables:", Colors.CYAN) + lines.append(vars_header) + for var_line in var_lines[:10]: # Limit to 10 variables to avoid overwhelming output + lines.append(self.colorize(f" {var_line}", Colors.CYAN + Colors.DIM)) + + if len(var_lines) > 10: + lines.append(self.colorize(f" ... and {len(var_lines) - 10} more", Colors.DIM)) + + return "\n".join(lines) + + +# For accessing source lines safely +def linecache_getline(filename, lineno): + """Get line from file, with better error handling than linecache.""" + try: + with open(filename, "r") as f: + lines = f.readlines() + if 1 <= lineno <= len(lines): + return lines[lineno - 1] + except (IOError, IndexError): + pass + return "" + + def get_logger(name: str) -> logging.Logger: """Creates and returns a logger instance for the specified module. @@ -15,6 +197,7 @@ def get_logger(name: str) -> logging.Logger: Returns: logging.Logger: Configured logger instance. """ + logging_level = get_settings().LOGGING_LEVEL.upper() # Create a logger @@ -31,11 +214,8 @@ def get_logger(name: str) -> logging.Logger: console_handler = logging.StreamHandler(sys.stdout) console_handler.setLevel(logging_level) - # Create formatter - formatter = logging.Formatter( - "%(asctime)s | %(levelname)s | %(name)s:%(funcName)s:%(lineno)d | %(message)s", - datefmt="%Y-%m-%d %H:%M:%S", - ) + # Create formatter that handles colors based on environment + formatter = EnhancedFormatter(datefmt="%Y-%m-%d %H:%M:%S") # Add formatter to handler console_handler.setFormatter(formatter) diff --git a/src/ansari/app/main_stdio.py b/src/ansari/app/main_stdio.py index 4a79192..ae782bd 100644 --- a/src/ansari/app/main_stdio.py +++ b/src/ansari/app/main_stdio.py @@ -25,17 +25,27 @@ def main( input: Optional[str] = typer.Option( None, "--input", "-i", help="Input to send to the agent. If not provided, starts interactive mode." ), + stream: bool = typer.Option( + False, "--stream", "-s", help="Stream the output word by word. If False, prints the complete answer at once." + ), ): """ Run the Ansari agent. If input is provided, process it and exit. If no input is provided, start interactive mode. """ # Convert log level string to logging constant + # Get the root logger and set its level to match the CLI argument + # Note: We don't use logging.basicConfig() to avoid duplicate logs + # Our custom get_logger() function has already configured the loggers numeric_level = getattr(logging, log_level.upper(), None) if not isinstance(numeric_level, int): raise ValueError(f"Invalid log level: {log_level}") - logging.basicConfig(level=numeric_level) + # Update the logger's level + logging.getLogger().setLevel(numeric_level) + # Also update our module's logger level + logger.setLevel(numeric_level) + settings = get_settings() if agent == "AnsariClaude": @@ -53,13 +63,19 @@ def main( result = agent_instance.process_input(input) # Handle the result which could be either a generator or other iterable if result: - for word in result: - if word is not None: + print("Model response:") + if stream: + # Stream output word by word + for word in result: print(word, end="", flush=True) - print() + print() + else: + # Collect the entire response and print at once + complete_response = "".join([word for word in result if word is not None]) + print(complete_response) else: # No input provided, start interactive mode - presenter = StdioPresenter(agent_instance, skip_greeting=True) + presenter = StdioPresenter(agent_instance, skip_greeting=True, stream=stream) presenter.present() diff --git a/src/ansari/presenters/stdio_presenter.py b/src/ansari/presenters/stdio_presenter.py index f8e65a7..8ba073c 100644 --- a/src/ansari/presenters/stdio_presenter.py +++ b/src/ansari/presenters/stdio_presenter.py @@ -4,9 +4,10 @@ class StdioPresenter: - def __init__(self, agent: Ansari, skip_greeting=False): + def __init__(self, agent: Ansari, skip_greeting=False, stream=False): self.agent = agent self.skip_greeting = skip_greeting + self.stream = stream def present(self): if not self.skip_greeting: @@ -18,10 +19,17 @@ def present(self): result = self.agent.process_input(inp) # Handle the result which could be either a generator or other iterable if result: - for word in result: - if word is not None: + print("Model response:") + if self.stream: + # Stream output word by word + for word in result: sys.stdout.write(word) sys.stdout.flush() + else: + # Collect the entire response and output at once + complete_response = "".join([word for word in result]) + sys.stdout.write(complete_response) + sys.stdout.flush() sys.stdout.write("\n> ") sys.stdout.flush() inp = sys.stdin.readline() From 200da418be24bd39d16a39042dd6470ec3339975 Mon Sep 17 00:00:00 2001 From: OdyAsh Date: Mon, 14 Apr 2025 08:03:14 +0200 Subject: [PATCH 2/3] refactor(logging): Enhance logging system with Rich integration * Replace custom colorized formatter with Rich handler for improved readability and functionality. * Add file-based logging with custom formatting tailored for VS Code compatibility. * Introduce Rich traceback handler with enhanced exception details, including local variables. * Simplify logging setup and ensure seamless integration with development mode features. * Update `.gitignore` to exclude log files. --- .gitignore | 1 + src/ansari/ansari_logger.py | 280 ++++++++++++------------------------ 2 files changed, 91 insertions(+), 190 deletions(-) diff --git a/.gitignore b/.gitignore index e6fbdb6..2c9016b 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ docs/recordings/* etc/ example_projects/ lib/ +logs/ share/ src/ansari_backend.egg-info/* tmp/ diff --git a/src/ansari/ansari_logger.py b/src/ansari/ansari_logger.py index f459a5f..fdc5a07 100644 --- a/src/ansari/ansari_logger.py +++ b/src/ansari/ansari_logger.py @@ -3,189 +3,74 @@ import logging import os import sys +import re +import time +from typing import Optional + +from rich.console import Console +from rich.logging import RichHandler +from rich.traceback import install as install_rich_traceback from ansari.config import get_settings -# ANSI color codes -class Colors: - RESET = "\033[0m" - GREEN = "\033[32m" - MAGENTA = "\033[35m" - CYAN = "\033[36m" - YELLOW = "\033[33m" - WHITE = "\033[37m" - BOLD = "\033[1m" - DIM = "\033[2m" - LEVEL_COLORS = { - "DEBUG": "\033[34m", # Blue - "INFO": "\033[0m", # RESET # (alternative: \033[37m - White), - "WARNING": "\033[33m", # Yellow - "ERROR": "\033[31m", # Red - "CRITICAL": "\033[1;31m", # Bold Red - } - - -class EnhancedFormatter(logging.Formatter): - """Advanced formatter that provides rich, colorful logging with enhanced exception handling. - - Features: - - Colorful log output similar to loguru - - Rich exception formatting with source code context - - Local variable display in exception tracebacks - - Smart color detection based on terminal capabilities +# Install rich traceback handler globally +install_rich_traceback( + show_locals=True, + max_frames=10, + suppress=[], + width=None, + word_wrap=True, +) + + +def create_file_handler(name: str, logging_level: str) -> logging.FileHandler: + """Creates and configures a file handler for logging. + + Args: + name (str): The name of the module for the log file. + logging_level (str): The logging level to set for the handler. + + Returns: + logging.FileHandler: Configured file handler instance. """ + # Ensure logs directory exists + log_dir = os.path.join(os.getcwd(), "logs") + os.makedirs(log_dir, exist_ok=True) + + log_file = os.path.join(log_dir, f"{name}.log") + file_handler = logging.FileHandler( + filename=log_file, + mode="a", # Append mode + encoding="utf-8", # Use UTF-8 encoding to support Unicode characters + ) + file_handler.setLevel(logging_level) + + # Custom formatter for files with forward slashes and function name in square brackets + class VSCodePathFormatter(logging.Formatter): + # ANSI color code regex pattern + ANSI_ESCAPE_PATTERN = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])") - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - # Determine if colors should be used - self.use_colors = sys.stdout.isatty() or os.environ.get("GITHUB_ACTIONS") is not None - - def colorize(self, text, color): - """Wrap text with color codes if colors are enabled.""" - if self.use_colors: - return f"{color}{text}{Colors.RESET}" - return text - - def format(self, record): - # Get the level color or default to reset if not found - level_color = Colors.LEVEL_COLORS.get(record.levelname, Colors.RESET) - - # Format components with appropriate colors (if enabled) - timestamp = self.colorize(self.formatTime(record), Colors.GREEN) - level = self.colorize(record.levelname, level_color) - if get_settings().DEV_MODE: - # Create a clickable VS Code link in the format that VS Code recognizes - code_loc = f"{record.name.replace(".", "/")}:{record.lineno} [{record.funcName}()]" - else: - # Else, use the standard format - code_loc = f"{record.name}:{record.funcName}:{record.lineno}" - code_location = self.colorize(code_loc, Colors.MAGENTA) - - # Use level color for message except for INFO level (keep those plain) - if record.levelname == "INFO": - message = record.getMessage() # No coloring for INFO messages - else: - message = self.colorize(record.getMessage(), level_color) - - # Combine everything with the pipe separator - formatted_log = f"{timestamp} | {level} | {code_location} | {message}" - - # Add exception info if available - if record.exc_info: - formatted_exception = self.format_exception(record.exc_info) - formatted_log = f"{formatted_log}\n{formatted_exception}" - - return formatted_log - - def format_exception(self, exc_info) -> str: - """ - Format exception info with colorful traceback and variable values. - - Example output: - ``` - list indices must be integers or slices, not str - TypeError: list indices must be integers or slices, not str - Traceback (most recent call last): - File "path/to/file1.py", line 328, in - > - Local variables: - var_1 = val_1 - var_2 = val_2 - /// /// /// - /// /// /// - ... and x more - File "path/to/file2.py", line 669, in - - Local variables: - var_1 = val_1 - /// /// /// - ... and x more - File /////////////////////////////////////// - ///////////////////// - Local variables: - /// /// /// - - and so on... - ``` - """ - exc_type, exc_value, tb = exc_info - - # Format the exception header - exc_name = exc_type.__name__ - exc_message = str(exc_value) - header = self.colorize(f"{exc_name}: {exc_message}", Colors.LEVEL_COLORS["ERROR"]) - - # Process the traceback - tb_frames = [] - current_tb = tb - while current_tb: - frame = current_tb.tb_frame - filename = frame.f_code.co_filename - lineno = current_tb.tb_lineno - function = frame.f_code.co_name - locals_dict = frame.f_locals.copy() - tb_frames.append((filename, lineno, function, locals_dict)) - current_tb = current_tb.tb_next - - # Generate enhanced traceback with variable information - lines = [header] - lines.append(self.colorize("Traceback (most recent call last):", Colors.BOLD)) - - for filename, lineno, function, locals_dict in tb_frames: - frame_header = self.colorize(f'File "{filename}", line {lineno}, in {function}', Colors.YELLOW) - lines.append(f" {frame_header}") - - # Try to get the source line - try: - source_line = linecache_getline(filename, lineno).strip() - if source_line: - lines.append(self.colorize(f" {source_line}", Colors.WHITE)) - except Exception: - pass # Skip if we can't get the source line - - # Add local variables (similar to loguru's style) - var_lines = [] - for name, value in locals_dict.items(): - # Skip magic and module variables to reduce noise - if name.startswith("__") or name.startswith("_["): - continue - try: - # Safer way to get string representation - if isinstance(value, (str, int, float, bool, type(None))): - val_str = repr(value) - else: - val_str = str(value) - - if len(val_str) > 50: - val_str = val_str[:47] + "..." - var_lines.append(f"{name} = {val_str}") - except Exception: - var_lines.append(f"{name} = ") - - if var_lines: - vars_header = self.colorize(" Local variables:", Colors.CYAN) - lines.append(vars_header) - for var_line in var_lines[:10]: # Limit to 10 variables to avoid overwhelming output - lines.append(self.colorize(f" {var_line}", Colors.CYAN + Colors.DIM)) - - if len(var_lines) > 10: - lines.append(self.colorize(f" ... and {len(var_lines) - 10} more", Colors.DIM)) - - return "\n".join(lines) - - -# For accessing source lines safely -def linecache_getline(filename, lineno): - """Get line from file, with better error handling than linecache.""" - try: - with open(filename, "r") as f: - lines = f.readlines() - if 1 <= lineno <= len(lines): - return lines[lineno - 1] - except (IOError, IndexError): - pass - return "" + def format(self, record): + # Format path with forward slashes and function name in square brackets + path_format = f"{record.name.replace('.','/')}:{record.lineno} [{record.funcName}()]" + + # Format time without milliseconds + # Override the default formatTime to remove milliseconds + created = self.converter(record.created) + time_format = time.strftime("%Y-%m-%d %H:%M:%S", created) + + # Get the message and strip any ANSI color codes + message = record.getMessage() + clean_message = self.ANSI_ESCAPE_PATTERN.sub("", message) + + # Combine everything + return f"{time_format} | {record.levelname} | {path_format} | {clean_message}" + + # Use the custom formatter for files + file_formatter = VSCodePathFormatter() # No datefmt needed as we're formatting time manually + file_handler.setFormatter(file_formatter) + return file_handler def get_logger(name: str) -> logging.Logger: @@ -197,9 +82,16 @@ def get_logger(name: str) -> logging.Logger: Returns: logging.Logger: Configured logger instance. """ - logging_level = get_settings().LOGGING_LEVEL.upper() + # Create a Rich console for logging + console = Console( + highlight=True, # Syntax highlighting + markup=True, # Enable Rich markup + log_path=False, # Don't write to a log file directly - we'll handle that separately + log_time_format="%Y-%m-%d %H:%M:%S", + ) + # Create a logger logger = logging.getLogger(name) @@ -210,17 +102,25 @@ def get_logger(name: str) -> logging.Logger: # Set the logging level logger.setLevel(logging_level) - # Create console handler - console_handler = logging.StreamHandler(sys.stdout) - console_handler.setLevel(logging_level) - - # Create formatter that handles colors based on environment - formatter = EnhancedFormatter(datefmt="%Y-%m-%d %H:%M:%S") - - # Add formatter to handler - console_handler.setFormatter(formatter) - - # Add handler to logger - logger.addHandler(console_handler) + # Create Rich handler with VS Code compatible formatting in DEV_MODE + rich_handler = RichHandler( + console=console, + enable_link_path=get_settings().DEV_MODE, # Enable VS Code clickable links in DEV_MODE + markup=True, + rich_tracebacks=True, + tracebacks_show_locals=True, + show_time=True, + show_level=True, + show_path=True, + ) + rich_handler.setLevel(logging_level) + + # Add the Rich handler to the logger + logger.addHandler(rich_handler) + + # Add file handler if DEV_MODE is enabled + if get_settings().DEV_MODE: + file_handler = create_file_handler(name, logging_level) + logger.addHandler(file_handler) return logger From 8e365b1b64bf7dede78ad4f8863fa9d413bd7c67 Mon Sep 17 00:00:00 2001 From: OdyAsh Date: Mon, 14 Apr 2025 08:04:31 +0200 Subject: [PATCH 3/3] refactor(logging): Simplify imports in logger module * Remove unused `sys` and `Optional` imports to clean up the code. --- src/ansari/ansari_logger.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ansari/ansari_logger.py b/src/ansari/ansari_logger.py index fdc5a07..4c3d1e2 100644 --- a/src/ansari/ansari_logger.py +++ b/src/ansari/ansari_logger.py @@ -2,10 +2,8 @@ import logging import os -import sys import re import time -from typing import Optional from rich.console import Console from rich.logging import RichHandler