Parcourir la source

Remove global config from logger (#2974)

* Remove global config from loggers

* Fix bug
Graham Neubig il y a 1 an
Parent
commit
88d53e781f
2 fichiers modifiés avec 57 ajouts et 37 suppressions
  1. 49 28
      opendevin/core/config.py
  2. 8 9
      opendevin/core/logger.py

+ 49 - 28
opendevin/core/config.py

@@ -1,5 +1,4 @@
 import argparse
-import logging
 import os
 import pathlib
 import platform
@@ -12,10 +11,9 @@ from typing import Any, ClassVar, MutableMapping, get_args, get_origin
 import toml
 from dotenv import load_dotenv
 
+from opendevin.core import logger
 from opendevin.core.utils import Singleton
 
-logger = logging.getLogger(__name__)
-
 load_dotenv()
 
 
@@ -239,7 +237,9 @@ class AppConfig(metaclass=Singleton):
         if name in self.llms:
             return self.llms[name]
         if name is not None and name != 'llm':
-            logger.warning(f'llm config group {name} not found, using default config')
+            logger.opendevin_logger.warning(
+                f'llm config group {name} not found, using default config'
+            )
         if 'llm' not in self.llms:
             self.llms['llm'] = LLMConfig()
         return self.llms['llm']
@@ -377,21 +377,23 @@ def load_from_env(cfg: AppConfig, env_or_toml_dict: dict | MutableMapping[str, s
                         cast_value = field_type(value)
                     setattr(sub_config, field_name, cast_value)
                 except (ValueError, TypeError):
-                    logger.error(
+                    logger.opendevin_logger.error(
                         f'Error setting env var {env_var_name}={value}: check that the value is of the right type'
                     )
 
     if 'SANDBOX_TYPE' in env_or_toml_dict:
-        logger.error('SANDBOX_TYPE is deprecated. Please use SANDBOX_BOX_TYPE instead.')
+        logger.opendevin_logger.error(
+            'SANDBOX_TYPE is deprecated. Please use SANDBOX_BOX_TYPE instead.'
+        )
         env_or_toml_dict['SANDBOX_BOX_TYPE'] = env_or_toml_dict.pop('SANDBOX_TYPE')
     # Start processing from the root of the config object
     set_attr_from_env(cfg)
 
     # load default LLM config from env
-    default_llm_config = config.get_llm_config()
+    default_llm_config = cfg.get_llm_config()
     set_attr_from_env(default_llm_config, 'LLM_')
     # load default agent config from env
-    default_agent_config = config.get_agent_config()
+    default_agent_config = cfg.get_agent_config()
     set_attr_from_env(default_agent_config, 'AGENT_')
 
 
@@ -407,10 +409,10 @@ def load_from_toml(cfg: AppConfig, toml_file: str = 'config.toml'):
         with open(toml_file, 'r', encoding='utf-8') as toml_contents:
             toml_config = toml.load(toml_contents)
     except FileNotFoundError as e:
-        logger.info(f'Config file not found: {e}')
+        logger.opendevin_logger.info(f'Config file not found: {e}')
         return
     except toml.TomlDecodeError as e:
-        logger.warning(
+        logger.opendevin_logger.warning(
             f'Cannot parse config from toml, toml values have not been applied.\nError: {e}',
             exc_info=False,
         )
@@ -429,7 +431,9 @@ def load_from_toml(cfg: AppConfig, toml_file: str = 'config.toml'):
         if isinstance(value, dict):
             try:
                 if key is not None and key.lower() == 'agent':
-                    logger.info('Attempt to load default agent config from config toml')
+                    logger.opendevin_logger.info(
+                        'Attempt to load default agent config from config toml'
+                    )
                     non_dict_fields = {
                         k: v for k, v in value.items() if not isinstance(v, dict)
                     }
@@ -437,13 +441,15 @@ def load_from_toml(cfg: AppConfig, toml_file: str = 'config.toml'):
                     cfg.set_agent_config(agent_config, 'agent')
                     for nested_key, nested_value in value.items():
                         if isinstance(nested_value, dict):
-                            logger.info(
+                            logger.opendevin_logger.info(
                                 f'Attempt to load group {nested_key} from config toml as agent config'
                             )
                             agent_config = AgentConfig(**nested_value)
                             cfg.set_agent_config(agent_config, nested_key)
                 if key is not None and key.lower() == 'llm':
-                    logger.info('Attempt to load default LLM config from config toml')
+                    logger.opendevin_logger.info(
+                        'Attempt to load default LLM config from config toml'
+                    )
                     non_dict_fields = {
                         k: v for k, v in value.items() if not isinstance(v, dict)
                     }
@@ -451,13 +457,13 @@ def load_from_toml(cfg: AppConfig, toml_file: str = 'config.toml'):
                     cfg.set_llm_config(llm_config, 'llm')
                     for nested_key, nested_value in value.items():
                         if isinstance(nested_value, dict):
-                            logger.info(
+                            logger.opendevin_logger.info(
                                 f'Attempt to load group {nested_key} from config toml as llm config'
                             )
                             llm_config = LLMConfig(**nested_value)
                             cfg.set_llm_config(llm_config, nested_key)
             except (TypeError, KeyError) as e:
-                logger.warning(
+                logger.opendevin_logger.warning(
                     f'Cannot parse config from toml, toml values have not been applied.\n Error: {e}',
                     exc_info=False,
                 )
@@ -476,7 +482,7 @@ def load_from_toml(cfg: AppConfig, toml_file: str = 'config.toml'):
                 # read the key in sandbox and remove it from core
                 setattr(sandbox_config, new_key, core_config.pop(key))
             else:
-                logger.warning(f'Unknown sandbox config: {key}')
+                logger.opendevin_logger.warning(f'Unknown sandbox config: {key}')
 
         # the new style values override the old style values
         if 'sandbox' in toml_config:
@@ -485,7 +491,7 @@ def load_from_toml(cfg: AppConfig, toml_file: str = 'config.toml'):
         # update the config object with the new values
         AppConfig(sandbox=sandbox_config, **core_config)
     except (TypeError, KeyError) as e:
-        logger.warning(
+        logger.opendevin_logger.warning(
             f'Cannot parse config from toml, toml values have not been applied.\nError: {e}',
             exc_info=False,
         )
@@ -513,7 +519,7 @@ def finalize_config(cfg: AppConfig):
             llm.embedding_base_url = llm.base_url
 
     if cfg.use_host_network and platform.system() == 'Darwin':
-        logger.warning(
+        logger.opendevin_logger.warning(
             'Please upgrade to Docker Desktop 4.29.0 or later to use host network mode on macOS. '
             'See https://github.com/docker/roadmap/issues/238#issuecomment-2044688144 for more information.'
         )
@@ -523,12 +529,6 @@ def finalize_config(cfg: AppConfig):
         pathlib.Path(cfg.cache_dir).mkdir(parents=True, exist_ok=True)
 
 
-config = AppConfig()
-load_from_toml(config)
-load_from_env(config, os.environ)
-finalize_config(config)
-
-
 # Utility function for command line --group argument
 def get_llm_config_arg(
     llm_config_arg: str, toml_file: str = 'config.toml'
@@ -564,23 +564,25 @@ def get_llm_config_arg(
     if llm_config_arg.startswith('llm.'):
         llm_config_arg = llm_config_arg[4:]
 
-    logger.info(f'Loading llm config from {llm_config_arg}')
+    logger.opendevin_logger.info(f'Loading llm config from {llm_config_arg}')
 
     # load the toml file
     try:
         with open(toml_file, 'r', encoding='utf-8') as toml_contents:
             toml_config = toml.load(toml_contents)
     except FileNotFoundError as e:
-        logger.error(f'Config file not found: {e}')
+        logger.opendevin_logger.error(f'Config file not found: {e}')
         return None
     except toml.TomlDecodeError as e:
-        logger.error(f'Cannot parse llm group from {llm_config_arg}. Exception: {e}')
+        logger.opendevin_logger.error(
+            f'Cannot parse llm group from {llm_config_arg}. Exception: {e}'
+        )
         return None
 
     # update the llm config with the specified section
     if 'llm' in toml_config and llm_config_arg in toml_config['llm']:
         return LLMConfig(**toml_config['llm'][llm_config_arg])
-    logger.debug(f'Loading from toml failed for {llm_config_arg}')
+    logger.opendevin_logger.debug(f'Loading from toml failed for {llm_config_arg}')
     return None
 
 
@@ -667,3 +669,22 @@ def parse_arguments() -> argparse.Namespace:
         config.workspace_base = os.path.abspath(parsed_args.directory)
         print(f'Setting workspace base to {config.workspace_base}')
     return parsed_args
+
+
+def load_app_config(set_logging_levels: bool = True) -> AppConfig:
+    """Load the configuration from the config.toml file and environment variables.
+
+    Args:
+        set_logger_levels: Whether to set the global variables for logging levels.
+    """
+    config = AppConfig()
+    load_from_toml(config)
+    load_from_env(config, os.environ)
+    finalize_config(config)
+    if set_logging_levels:
+        logger.DEBUG = config.debug
+        logger.DISABLE_COLOR_PRINTING = config.disable_color
+    return config
+
+
+config = load_app_config()

+ 8 - 9
opendevin/core/logger.py

@@ -8,9 +8,8 @@ from typing import Literal, Mapping
 
 from termcolor import colored
 
-from opendevin.core.config import config
-
-DISABLE_COLOR_PRINTING = config.disable_color
+DISABLE_COLOR_PRINTING = False
+DEBUG = False
 
 ColorType = Literal[
     'red',
@@ -57,7 +56,7 @@ class ColoredFormatter(logging.Formatter):
             )
             name_str = colored(record.name, LOG_COLORS[msg_type])
             level_str = colored(record.levelname, LOG_COLORS[msg_type])
-            if msg_type in ['ERROR'] or config.debug:
+            if msg_type in ['ERROR'] or DEBUG:
                 return f'{time_str} - {name_str}:{level_str}: {record.filename}:{record.lineno}\n{msg_type_color}\n{msg}'
             return f'{time_str} - {msg_type_color}\n{msg}'
         elif msg_type == 'STEP':
@@ -118,7 +117,7 @@ def get_console_handler():
     """Returns a console handler for logging."""
     console_handler = logging.StreamHandler()
     console_handler.setLevel(logging.INFO)
-    if config.debug:
+    if DEBUG:
         console_handler.setLevel(logging.DEBUG)
     console_handler.setFormatter(console_formatter)
     return console_handler
@@ -131,7 +130,7 @@ def get_file_handler(log_dir=None):
     timestamp = datetime.now().strftime('%Y-%m-%d')
     file_name = f'opendevin_{timestamp}.log'
     file_handler = logging.FileHandler(os.path.join(log_dir, file_name))
-    if config.debug:
+    if DEBUG:
         file_handler.setLevel(logging.DEBUG)
     file_handler.setFormatter(file_formatter)
     return file_handler
@@ -160,7 +159,7 @@ sys.excepthook = log_uncaught_exceptions
 
 opendevin_logger = logging.getLogger('opendevin')
 opendevin_logger.setLevel(logging.INFO)
-if config.debug:
+if DEBUG:
     opendevin_logger.setLevel(logging.DEBUG)
 opendevin_logger.addHandler(get_file_handler())
 opendevin_logger.addHandler(get_console_handler())
@@ -191,13 +190,13 @@ class LlmFileHandler(logging.FileHandler):
         """
         self.filename = filename
         self.message_counter = 1
-        if config.debug:
+        if DEBUG:
             self.session = datetime.now().strftime('%y-%m-%d_%H-%M')
         else:
             self.session = 'default'
         self.log_directory = os.path.join(os.getcwd(), 'logs', 'llm', self.session)
         os.makedirs(self.log_directory, exist_ok=True)
-        if not config.debug:
+        if not DEBUG:
             # Clear the log directory if not in debug mode
             for file in os.listdir(self.log_directory):
                 file_path = os.path.join(self.log_directory, file)