json logging

This commit is contained in:
2025-12-24 00:26:20 +01:00
parent e2c18b07a5
commit 6654496379
4 changed files with 32 additions and 16 deletions

View File

@@ -13,4 +13,5 @@ dependencies = [
"python-dotenv", "python-dotenv",
"httpx", "httpx",
"logfire>=4.16.0", "logfire>=4.16.0",
"python-json-logger>=4.0.0",
] ]

View File

@@ -7,10 +7,20 @@ import logging
import httpx import httpx
import logfire import logfire
# Set up logging BEFORE logfire (otherwise basicConfig is ignored)
from pythonjsonlogger import jsonlogger
log_level = os.getenv("LOG_LEVEL", "INFO").upper()
handler = logging.StreamHandler()
handler.setFormatter(jsonlogger.JsonFormatter("%(asctime)s %(name)s %(levelname)s %(message)s"))
logging.basicConfig(
level=getattr(logging, log_level, logging.INFO),
handlers=[handler],
)
logger = logging.getLogger(__name__)
# Configure Logfire for observability # Configure Logfire for observability
# Uses LOGFIRE_TOKEN in production, or local auth from `logfire auth` in dev
logfire.configure( logfire.configure(
project_name='cavepediav2',
environment=os.getenv('ENVIRONMENT', 'development'), environment=os.getenv('ENVIRONMENT', 'development'),
) )
logfire.instrument_pydantic_ai() logfire.instrument_pydantic_ai()
@@ -19,14 +29,6 @@ logfire.instrument_httpx()
from pydantic_ai import Agent, ModelMessage, RunContext from pydantic_ai import Agent, ModelMessage, RunContext
from pydantic_ai.settings import ModelSettings from pydantic_ai.settings import ModelSettings
# Set up logging based on environment
log_level = logging.DEBUG if os.getenv("DEBUG") else logging.INFO
logging.basicConfig(
level=log_level,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
CAVE_MCP_URL = os.getenv("CAVE_MCP_URL", "https://mcp.caving.dev/mcp") CAVE_MCP_URL = os.getenv("CAVE_MCP_URL", "https://mcp.caving.dev/mcp")
logger.info(f"Initializing Cavepedia agent with CAVE_MCP_URL={CAVE_MCP_URL}") logger.info(f"Initializing Cavepedia agent with CAVE_MCP_URL={CAVE_MCP_URL}")

View File

@@ -14,13 +14,27 @@ from pydantic_ai.settings import ModelSettings
load_dotenv() load_dotenv()
# Set up logging based on environment # Set up logging based on environment
log_level = logging.DEBUG if os.getenv("DEBUG") else logging.INFO from pythonjsonlogger import jsonlogger
log_level = os.getenv("LOG_LEVEL", "INFO").upper()
json_formatter = jsonlogger.JsonFormatter("%(asctime)s %(name)s %(levelname)s %(message)s")
# Configure root logger with JSON
handler = logging.StreamHandler()
handler.setFormatter(json_formatter)
logging.basicConfig( logging.basicConfig(
level=log_level, level=getattr(logging, log_level, logging.INFO),
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" handlers=[handler],
) )
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Apply JSON formatter to uvicorn loggers (works even when run via `uvicorn src.main:app`)
for uvicorn_logger_name in ("uvicorn", "uvicorn.error", "uvicorn.access"):
uvicorn_logger = logging.getLogger(uvicorn_logger_name)
uvicorn_logger.handlers = [handler]
uvicorn_logger.setLevel(getattr(logging, log_level, logging.INFO))
uvicorn_logger.propagate = False
# Validate required environment variables # Validate required environment variables
if not os.getenv("ANTHROPIC_API_KEY"): if not os.getenv("ANTHROPIC_API_KEY"):
logger.error("ANTHROPIC_API_KEY environment variable is required") logger.error("ANTHROPIC_API_KEY environment variable is required")
@@ -41,12 +55,9 @@ logger.info("Creating AG-UI app...")
async def handle_agent_request(request: Request) -> Response: async def handle_agent_request(request: Request) -> Response:
"""Handle incoming AG-UI requests with dynamic role-based MCP configuration.""" """Handle incoming AG-UI requests with dynamic role-based MCP configuration."""
# Debug: log all incoming headers
logger.info(f"DEBUG: All request headers: {dict(request.headers)}")
# Extract user roles from request headers # Extract user roles from request headers
roles_header = request.headers.get("x-user-roles", "") roles_header = request.headers.get("x-user-roles", "")
logger.info(f"DEBUG: x-user-roles header value: '{roles_header}'")
user_roles = [] user_roles = []
if roles_header: if roles_header:

2
web/agent/uv.lock generated
View File

@@ -236,6 +236,7 @@ dependencies = [
{ name = "openai" }, { name = "openai" },
{ name = "pydantic-ai" }, { name = "pydantic-ai" },
{ name = "python-dotenv" }, { name = "python-dotenv" },
{ name = "python-json-logger" },
{ name = "starlette" }, { name = "starlette" },
{ name = "uvicorn" }, { name = "uvicorn" },
] ]
@@ -249,6 +250,7 @@ requires-dist = [
{ name = "openai" }, { name = "openai" },
{ name = "pydantic-ai" }, { name = "pydantic-ai" },
{ name = "python-dotenv" }, { name = "python-dotenv" },
{ name = "python-json-logger", specifier = ">=4.0.0" },
{ name = "starlette" }, { name = "starlette" },
{ name = "uvicorn" }, { name = "uvicorn" },
] ]