Plain logs need regex parsing per line. JSON logs are field-typed: every line has request_id, user_id, agent_step, level, message. A grep for request_id=ABC gives you every log of that one request across all components. Loki / Datadog / CloudWatch all ingest JSON natively.
JSONFormatter: every record is {"ts", "level", "request_id", "user_id", "agent_step", "msg"}.
Log handler rotates the file (RotatingFileHandler) for any long-running process.
Never log secrets: regex-strip Authorization headers before serialization.
fastapi middleware -> JSON log {request_id, level, msg, ...}
Loki / Datadog ingest -> searchable by any field
JSON logs are searchable by any field. Plain logs are searchable by accident.