json logging
This commit is contained in:
@@ -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",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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}")
|
||||||
|
|||||||
@@ -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
2
web/agent/uv.lock
generated
@@ -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" },
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user