mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-04-30 23:02:50 +00:00
* feat: add server-side auth schemes and protocol extensions - add server auth scheme base class and implementations (api key, bearer token, basic/digest auth, mtls) - add server-side extension system for a2a protocol extensions - add extensions middleware for x-a2a-extensions header management - add extension validation and registry utilities - enhance auth utilities with server-side support - add async intercept method to match client call interceptor protocol - fix type_checking import to resolve mypy errors with a2aconfig * feat: add transport negotiation and content type handling - add transport negotiation logic with fallback support - add content type parser and encoder utilities - add transport configuration models (client and server) - add transport types and enums - enhance config with transport settings - add negotiation events for transport and content type * feat: add a2a delegation support to LiteAgent * feat: add file input support to a2a delegation and tasks Introduces handling of file inputs in A2A delegation flows by converting file dictionaries to protocol-compatible parts and propagating them through delegation and task execution functions. Updates include utility functions for file conversion, changes to message construction, and passing input_files through relevant APIs. * feat: liteagent a2a delegation support to kickoff methods
132 lines
3.6 KiB
Python
132 lines
3.6 KiB
Python
"""Structured JSON logging utilities for A2A module."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from contextvars import ContextVar
|
|
from datetime import datetime, timezone
|
|
import json
|
|
import logging
|
|
from typing import Any
|
|
|
|
|
|
_log_context: ContextVar[dict[str, Any] | None] = ContextVar(
|
|
"log_context", default=None
|
|
)
|
|
|
|
|
|
class JSONFormatter(logging.Formatter):
|
|
"""JSON formatter for structured logging.
|
|
|
|
Outputs logs as JSON with consistent fields for log aggregators.
|
|
"""
|
|
|
|
def format(self, record: logging.LogRecord) -> str:
|
|
"""Format log record as JSON string."""
|
|
log_data: dict[str, Any] = {
|
|
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
"level": record.levelname,
|
|
"logger": record.name,
|
|
"message": record.getMessage(),
|
|
}
|
|
|
|
if record.exc_info:
|
|
log_data["exception"] = self.formatException(record.exc_info)
|
|
|
|
context = _log_context.get()
|
|
if context is not None:
|
|
log_data.update(context)
|
|
|
|
if hasattr(record, "task_id"):
|
|
log_data["task_id"] = record.task_id
|
|
if hasattr(record, "context_id"):
|
|
log_data["context_id"] = record.context_id
|
|
if hasattr(record, "agent"):
|
|
log_data["agent"] = record.agent
|
|
if hasattr(record, "endpoint"):
|
|
log_data["endpoint"] = record.endpoint
|
|
if hasattr(record, "extension"):
|
|
log_data["extension"] = record.extension
|
|
if hasattr(record, "error"):
|
|
log_data["error"] = record.error
|
|
|
|
for key, value in record.__dict__.items():
|
|
if key.startswith("_") or key in (
|
|
"name",
|
|
"msg",
|
|
"args",
|
|
"created",
|
|
"filename",
|
|
"funcName",
|
|
"levelname",
|
|
"levelno",
|
|
"lineno",
|
|
"module",
|
|
"msecs",
|
|
"pathname",
|
|
"process",
|
|
"processName",
|
|
"relativeCreated",
|
|
"stack_info",
|
|
"exc_info",
|
|
"exc_text",
|
|
"thread",
|
|
"threadName",
|
|
"taskName",
|
|
"message",
|
|
):
|
|
continue
|
|
if key not in log_data:
|
|
log_data[key] = value
|
|
|
|
return json.dumps(log_data, default=str)
|
|
|
|
|
|
class LogContext:
|
|
"""Context manager for adding fields to all logs within a scope.
|
|
|
|
Example:
|
|
with LogContext(task_id="abc", context_id="xyz"):
|
|
logger.info("Processing task") # Includes task_id and context_id
|
|
"""
|
|
|
|
def __init__(self, **fields: Any) -> None:
|
|
self._fields = fields
|
|
self._token: Any = None
|
|
|
|
def __enter__(self) -> LogContext:
|
|
current = _log_context.get() or {}
|
|
new_context = {**current, **self._fields}
|
|
self._token = _log_context.set(new_context)
|
|
return self
|
|
|
|
def __exit__(self, *args: Any) -> None:
|
|
_log_context.reset(self._token)
|
|
|
|
|
|
def configure_json_logging(logger_name: str = "crewai.a2a") -> None:
|
|
"""Configure JSON logging for the A2A module.
|
|
|
|
Args:
|
|
logger_name: Logger name to configure.
|
|
"""
|
|
logger = logging.getLogger(logger_name)
|
|
|
|
for handler in logger.handlers[:]:
|
|
logger.removeHandler(handler)
|
|
|
|
handler = logging.StreamHandler()
|
|
handler.setFormatter(JSONFormatter())
|
|
logger.addHandler(handler)
|
|
|
|
|
|
def get_logger(name: str) -> logging.Logger:
|
|
"""Get a logger configured for structured JSON output.
|
|
|
|
Args:
|
|
name: Logger name.
|
|
|
|
Returns:
|
|
Configured logger instance.
|
|
"""
|
|
return logging.getLogger(name)
|