log: honour fastagent.config.yaml logger.level so one knob controls Pallas + fast-agent
This commit is contained in:
@@ -20,6 +20,7 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
class _JSONFormatter(logging.Formatter):
|
class _JSONFormatter(logging.Formatter):
|
||||||
@@ -68,21 +69,55 @@ class _HealthAccessFilter(logging.Filter):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _level_from_fastagent_config() -> str | None:
|
||||||
|
"""Return the ``logger.level`` string from ``fastagent.config.yaml`` if set.
|
||||||
|
|
||||||
|
We intentionally parse the YAML by hand (rather than importing fast-agent's
|
||||||
|
config loader) because ``setup_logging`` runs *before* fast-agent is
|
||||||
|
initialised — importing its config machinery here would reverse the
|
||||||
|
bootstrap order and swallow our first few log lines.
|
||||||
|
"""
|
||||||
|
cfg_path = Path.cwd() / "fastagent.config.yaml"
|
||||||
|
if not cfg_path.exists():
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
with open(cfg_path) as fh:
|
||||||
|
data = yaml.safe_load(fh) or {}
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
logger_cfg = data.get("logger") or {}
|
||||||
|
level = logger_cfg.get("level")
|
||||||
|
return str(level) if level else None
|
||||||
|
|
||||||
|
|
||||||
def setup_logging() -> None:
|
def setup_logging() -> None:
|
||||||
"""Configure Pallas logging.
|
"""Configure Pallas logging.
|
||||||
|
|
||||||
- ``pallas.*`` logger: INFO by default, JSON to stdout. Override via the
|
Log level resolution order (first match wins):
|
||||||
``PALLAS_LOG_LEVEL`` environment variable (``DEBUG``, ``INFO``,
|
|
||||||
``WARNING``, ``ERROR``). DEBUG unlocks bearer-forwarding diagnostics
|
1. ``PALLAS_LOG_LEVEL`` environment variable — explicit override.
|
||||||
on the ``pallas.forward`` and ``pallas.auth`` loggers — essential when
|
2. ``logger.level`` in ``fastagent.config.yaml`` — unified control knob
|
||||||
troubleshooting Mnemosyne / workspace-scoped agent calls.
|
so bumping fast-agent's level also flips on Pallas's bearer-forwarding
|
||||||
|
diagnostics.
|
||||||
|
3. ``INFO``.
|
||||||
|
|
||||||
|
``DEBUG`` unlocks diagnostics on the ``pallas.forward`` and
|
||||||
|
``pallas.auth`` loggers — essential when troubleshooting Mnemosyne /
|
||||||
|
workspace-scoped agent calls.
|
||||||
|
|
||||||
- ``httpx`` / ``httpcore``: WARNING (prevent request-level debug flooding)
|
- ``httpx`` / ``httpcore``: WARNING (prevent request-level debug flooding)
|
||||||
- ``uvicorn.access``: health path filter applied
|
- ``uvicorn.access``: health path filter applied
|
||||||
"""
|
"""
|
||||||
handler = logging.StreamHandler()
|
handler = logging.StreamHandler()
|
||||||
handler.setFormatter(_JSONFormatter())
|
handler.setFormatter(_JSONFormatter())
|
||||||
|
|
||||||
level_name = os.environ.get("PALLAS_LOG_LEVEL", "INFO").upper()
|
level_name = (
|
||||||
|
os.environ.get("PALLAS_LOG_LEVEL")
|
||||||
|
or _level_from_fastagent_config()
|
||||||
|
or "INFO"
|
||||||
|
).upper()
|
||||||
level = getattr(logging, level_name, logging.INFO)
|
level = getattr(logging, level_name, logging.INFO)
|
||||||
|
|
||||||
pallas_logger = logging.getLogger("pallas")
|
pallas_logger = logging.getLogger("pallas")
|
||||||
|
|||||||
Reference in New Issue
Block a user