Skip to content

Commit

Permalink
AutoGPT: Enhance log readability of autogpt.core
Browse files Browse the repository at this point in the history
  • Loading branch information
Pwuts committed Sep 15, 2023
1 parent 5074d69 commit 9bd13c5
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 41 deletions.
6 changes: 5 additions & 1 deletion autogpts/autogpt/autogpt/core/runner/cli_app/main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import click

from autogpt.core.agent import AgentSettings, SimpleAgent
from autogpt.core.runner.client_lib.logging import get_client_logger
from autogpt.core.runner.client_lib.logging import (
configure_root_logger, get_client_logger
)
from autogpt.core.runner.client_lib.parser import (
parse_ability_result,
parse_agent_name_and_goals,
Expand All @@ -13,6 +15,8 @@
async def run_auto_gpt(user_configuration: dict):
"""Run the Auto-GPT CLI client."""

configure_root_logger()

client_logger = get_client_logger()
client_logger.debug("Getting agent settings")

Expand Down
83 changes: 75 additions & 8 deletions autogpts/autogpt/autogpt/core/runner/client_lib/logging.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@
import logging
import sys

from colorama import Fore, Style

SIMPLE_LOG_FORMAT = "%(asctime)s %(levelname)s %(message)s"
DEBUG_LOG_FORMAT = (
"%(asctime)s.%(msecs)03d %(levelname)s %(filename)s:%(lineno)d %(message)s"
)


def configure_root_logger():
console_formatter = FancyConsoleFormatter(SIMPLE_LOG_FORMAT)

stdout = logging.StreamHandler(stream=sys.stdout)
stdout.setLevel(logging.DEBUG)
stdout.addFilter(BelowLevelFilter(logging.WARNING))
stdout.setFormatter(console_formatter)
stderr = logging.StreamHandler()
stderr.setLevel(logging.WARNING)
stderr.setFormatter(console_formatter)

logging.basicConfig(level=logging.DEBUG, handlers=[stdout, stderr])


def get_client_logger():
Expand All @@ -7,14 +29,59 @@ def get_client_logger():
client_logger = logging.getLogger("autogpt_client_application")
client_logger.setLevel(logging.DEBUG)

formatter = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
return client_logger

ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(formatter)

client_logger.addHandler(ch)
class FancyConsoleFormatter(logging.Formatter):
"""
A custom logging formatter designed for console output.
return client_logger
This formatter enhances the standard logging output with color coding. The color
coding is based on the level of the log message, making it easier to distinguish
between different types of messages in the console output.
The color for each level is defined in the LEVEL_COLOR_MAP class attribute.
"""

# level -> (level & text color, title color)
LEVEL_COLOR_MAP = {
logging.DEBUG: Fore.LIGHTBLACK_EX,
logging.INFO: Fore.BLUE,
logging.WARNING: Fore.YELLOW,
logging.ERROR: Fore.RED,
logging.CRITICAL: Fore.RED + Style.BRIGHT,
}

def format(self, record: logging.LogRecord) -> str:
# Make sure `msg` is a string
if not hasattr(record, "msg"):
record.msg = ""
elif not type(record.msg) == str:
record.msg = str(record.msg)

# Determine default color based on error level
level_color = ""
if record.levelno in self.LEVEL_COLOR_MAP:
level_color = self.LEVEL_COLOR_MAP[record.levelno]
record.levelname = f"{level_color}{record.levelname}{Style.RESET_ALL}"

# Determine color for message
color = getattr(record, "color", level_color)
color_is_specified = hasattr(record, "color")

# Don't color INFO messages unless the color is explicitly specified.
if color and (record.levelno != logging.INFO or color_is_specified):
record.msg = f"{color}{record.msg}{Style.RESET_ALL}"

return super().format(record)


class BelowLevelFilter(logging.Filter):
"""Filter for logging levels below a certain threshold."""

def __init__(self, below_level: int):
super().__init__()
self.below_level = below_level

def filter(self, record: logging.LogRecord):
return record.levelno < self.below_level
3 changes: 2 additions & 1 deletion autogpts/autogpt/autogpt/logs/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
if TYPE_CHECKING:
from autogpt.config import Config

from .filters import BelowLevelFilter
from autogpt.core.runner.client_lib.logging import BelowLevelFilter

from .formatters import AutoGptFormatter
from .handlers import TTSHandler, TypingConsoleHandler

Expand Down
36 changes: 5 additions & 31 deletions autogpts/autogpt/autogpt/logs/formatters.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
import logging

from colorama import Fore, Style

from .utils import remove_color_codes
from colorama import Style

from autogpt.core.runner.client_lib.logging import FancyConsoleFormatter

class AutoGptFormatter(logging.Formatter):
"""
Allows to handle custom placeholders 'title_color' and 'message_no_color'.
To use this formatter, make sure to pass 'color', 'title' as log extras.
"""
from .utils import remove_color_codes

# level -> (level & text color, title color)
LEVEL_COLOR_MAP = {
logging.DEBUG: Fore.LIGHTBLACK_EX,
logging.INFO: Fore.BLUE,
logging.WARNING: Fore.YELLOW,
logging.ERROR: Fore.RED,
logging.CRITICAL: Fore.RED + Style.BRIGHT,
}

class AutoGptFormatter(FancyConsoleFormatter):
def format(self, record: logging.LogRecord) -> str:
# Make sure `msg` is a string
if not hasattr(record, "msg"):
Expand All @@ -31,26 +19,12 @@ def format(self, record: logging.LogRecord) -> str:
if record.msg and not getattr(record, "preserve_color", False):
record.msg = remove_color_codes(record.msg)

# Determine default color based on error level
level_color = ""
if record.levelno in self.LEVEL_COLOR_MAP:
level_color = self.LEVEL_COLOR_MAP[record.levelno]
record.levelname = f"{level_color}{record.levelname}{Style.RESET_ALL}"

# Determine color for message
color = getattr(record, "color", level_color)
color_is_specified = hasattr(record, "color")

# Determine color for title
title = getattr(record, "title", "")
title_color = getattr(record, "title_color", "") or level_color
title_color = getattr(record, "title_color", "") or self.LEVEL_COLOR_MAP.get(record.levelno, "")
if title and title_color:
title = f"{title_color + Style.BRIGHT}{title}{Style.RESET_ALL}"
# Make sure record.title is set, and padded with a space if not empty
record.title = f"{title} " if title else ""

# Don't color INFO messages unless the color is explicitly specified.
if color and (record.levelno != logging.INFO or color_is_specified):
record.msg = f"{color}{record.msg}{Style.RESET_ALL}"

return super().format(record)

0 comments on commit 9bd13c5

Please sign in to comment.