diff --git a/agent-office/app/main.py b/agent-office/app/main.py index fbb60df..0b39bcc 100644 --- a/agent-office/app/main.py +++ b/agent-office/app/main.py @@ -116,8 +116,18 @@ def agent_tasks( return {"tasks": tasks_list, "items": tasks_list} @app.get("/api/agent-office/agents/{agent_id}/logs") -def agent_logs(agent_id: str, limit: int = 50): - return {"logs": get_logs(agent_id, limit)} +async def agent_logs(agent_id: str, limit: int = 50): + from .service_proxy import fetch_service_logs + + agent_items = get_logs(agent_id, limit=limit) + service_items = await fetch_service_logs(agent_id, limit=limit) + + def _sort_key(x): + # agent_logs: created_at, service: ts + return x.get("ts") or x.get("created_at") or "" + + merged = sorted(agent_items + service_items, key=_sort_key, reverse=True) + return {"logs": merged[:limit]} @app.get("/api/agent-office/tasks/pending") def pending_tasks(): diff --git a/agent-office/tests/test_log_merge.py b/agent-office/tests/test_log_merge.py new file mode 100644 index 0000000..69a20bd --- /dev/null +++ b/agent-office/tests/test_log_merge.py @@ -0,0 +1,47 @@ +import pytest +import respx +import httpx +from fastapi.testclient import TestClient + +from app.main import app +from app.db import add_log, _conn + + +@pytest.fixture(autouse=True) +def _clean_logs(): + with _conn() as conn: + conn.execute("DELETE FROM agent_logs WHERE agent_id = 'lotto'") + yield + + +@respx.mock +def test_agent_logs_endpoint_merges_db_and_service_logs(): + add_log("lotto", "큐레이션 완료: #1234 conf=0.78") + respx.get("http://lotto:8000/logs/recent").mock( + return_value=httpx.Response(200, json={ + "logs": [ + {"ts": "2026-05-28T10:00:00Z", "source": "access", + "method": "GET", "path": "/api/lotto/latest", + "status": 200, "ms": 8, + "message": "GET /api/lotto/latest → 200 (8ms)"}, + {"ts": "2026-05-28T10:00:02Z", "source": "log", + "logger": "lotto", "level": "info", + "message": "성과 통계 캐시 갱신"}, + ] + }) + ) + + client = TestClient(app) + resp = client.get("/api/agent-office/agents/lotto/logs?limit=20") + assert resp.status_code == 200 + logs = resp.json()["logs"] + + sources = {x["source"] for x in logs} + assert "agent" in sources + assert "access" in sources + assert "log" in sources + + messages = [x["message"] for x in logs] + assert any("큐레이션 완료" in m for m in messages) + assert any("성과 통계 캐시 갱신" in m for m in messages) + assert any("/api/lotto/latest" in m for m in messages)