feat: add colored and formatted logging
Add a custom logging setup function to add custom levels and custom formatters (partly for future use with extended logging functionality). Also implemented a basic colored formatter to make our logs nicer. Also improved the handling of logging in external libraries, so now we should only get WARNings or above. ref: N25B-233
This commit is contained in:
1
src/control_backend/logging/__init__.py
Normal file
1
src/control_backend/logging/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .setup_logging import setup_logging
|
||||
50
src/control_backend/logging/setup_logging.py
Normal file
50
src/control_backend/logging/setup_logging.py
Normal file
@@ -0,0 +1,50 @@
|
||||
import logging
|
||||
import logging.config
|
||||
import os
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
def add_logging_level(level_name: str, level_num: int, method_name: str | None = None) -> None:
|
||||
"""
|
||||
Adds a logging level to the `logging` module and the
|
||||
currently configured logging class.
|
||||
"""
|
||||
if not method_name:
|
||||
method_name = level_name.lower()
|
||||
|
||||
if hasattr(logging, level_name):
|
||||
raise AttributeError(f"{level_name} already defined in logging module")
|
||||
if hasattr(logging, method_name):
|
||||
raise AttributeError(f"{method_name} already defined in logging module")
|
||||
if hasattr(logging.getLoggerClass(), method_name):
|
||||
raise AttributeError(f"{method_name} already defined in logger class")
|
||||
|
||||
def log_for_level(self, message, *args, **kwargs):
|
||||
if self.isEnabledFor(level_num):
|
||||
self._log(level_num, message, args, **kwargs)
|
||||
|
||||
def log_to_root(message, *args, **kwargs):
|
||||
logging.log(level_num, message, *args, **kwargs)
|
||||
|
||||
logging.addLevelName(level_num, level_name)
|
||||
setattr(logging, level_name, level_num)
|
||||
setattr(logging.getLoggerClass(), method_name, log_for_level)
|
||||
setattr(logging, method_name, log_to_root)
|
||||
|
||||
|
||||
def setup_logging(path: str = "logging_config.yaml") -> None:
|
||||
if os.path.exists(path):
|
||||
with open(path) as f:
|
||||
try:
|
||||
config = yaml.safe_load(f.read())
|
||||
|
||||
if "custom_levels" in config:
|
||||
for level_name, level_num in config["custom_levels"].items():
|
||||
add_logging_level(level_name, level_num)
|
||||
|
||||
logging.config.dictConfig(config)
|
||||
except (AttributeError, yaml.YAMLError) as e:
|
||||
logging.warning(f"Could not load logging configuration: {e}")
|
||||
else:
|
||||
logging.warning("Logging config file not found. Using default logging configuration.")
|
||||
@@ -8,23 +8,25 @@ import zmq
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
# Internal imports
|
||||
from control_backend.agents.ri_communication_agent import RICommunicationAgent
|
||||
from control_backend.agents.bdi.bdi_core import BDICoreAgent
|
||||
from control_backend.agents.vad_agent import VADAgent
|
||||
from control_backend.agents.llm.llm import LLMAgent
|
||||
from control_backend.agents.bdi.text_extractor import TBeliefExtractor
|
||||
from control_backend.agents.belief_collector.belief_collector import BeliefCollectorAgent
|
||||
from control_backend.agents.llm.llm import LLMAgent
|
||||
|
||||
# Internal imports
|
||||
from control_backend.agents.ri_communication_agent import RICommunicationAgent
|
||||
from control_backend.agents.vad_agent import VADAgent
|
||||
from control_backend.api.v1.router import api_router
|
||||
from control_backend.core.config import settings
|
||||
from control_backend.core.zmq_context import context
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
from control_backend.logging import setup_logging
|
||||
|
||||
|
||||
@contextlib.asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
setup_logging()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
logger.info("%s starting up.", app.title)
|
||||
|
||||
# Initiate sockets
|
||||
@@ -34,7 +36,6 @@ async def lifespan(app: FastAPI):
|
||||
app.state.internal_comm_socket = internal_comm_socket
|
||||
logger.info("Internal publishing socket bound to %s", internal_comm_socket)
|
||||
|
||||
|
||||
# Initiate agents
|
||||
ri_communication_agent = RICommunicationAgent(
|
||||
settings.agent_settings.ri_communication_agent_name + "@" + settings.agent_settings.host,
|
||||
|
||||
Reference in New Issue
Block a user