diff --git a/app/routers/debug.py b/app/routers/debug.py index c98f2f9..55c1f65 100644 --- a/app/routers/debug.py +++ b/app/routers/debug.py @@ -10,7 +10,7 @@ from pydantic import BaseModel, Field from app.config import get_recent_log_lines, settings from app.radio_sync import get_contacts_selected_for_radio_sync, get_radio_channel_limit -from app.repository import MessageRepository +from app.repository import MessageRepository, StatisticsRepository from app.routers.health import HealthResponse, build_health_data from app.services.radio_runtime import radio_runtime from app.version_info import get_app_build_info, git_output @@ -87,11 +87,18 @@ class DebugRadioProbe(BaseModel): channels: DebugChannelAudit | None = None +class DebugDatabaseInfo(BaseModel): + total_dms: int + total_channel_messages: int + total_outgoing: int + + class DebugSnapshotResponse(BaseModel): captured_at: str application: DebugApplicationInfo health: HealthResponse runtime: DebugRuntimeInfo + database: DebugDatabaseInfo radio_probe: DebugRadioProbe logs: list[str] @@ -258,6 +265,7 @@ async def _probe_radio() -> DebugRadioProbe: async def debug_support_snapshot() -> DebugSnapshotResponse: """Return a support/debug snapshot with recent logs and live radio state.""" health_data = await build_health_data(radio_runtime.is_connected, radio_runtime.connection_info) + statistics = await StatisticsRepository.get_all() radio_probe = await _probe_radio() channels_with_incoming_messages = ( await MessageRepository.count_channels_with_incoming_messages() @@ -282,6 +290,11 @@ async def debug_support_snapshot() -> DebugSnapshotResponse: "force_channel_slot_reconfigure": settings.force_channel_slot_reconfigure, }, ), + database=DebugDatabaseInfo( + total_dms=statistics["total_dms"], + total_channel_messages=statistics["total_channel_messages"], + total_outgoing=statistics["total_outgoing"], + ), radio_probe=radio_probe, logs=[*LOG_COPY_BOUNDARY_PREFIX, *get_recent_log_lines(limit=1000)], ) diff --git a/tests/test_api.py b/tests/test_api.py index 1031540..574b968 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -160,6 +160,35 @@ class TestDebugEndpoint: assert payload["radio_probe"]["performed"] is False assert payload["radio_probe"]["errors"] == ["Radio not connected"] assert payload["runtime"]["channels_with_incoming_messages"] == 0 + assert payload["database"]["total_dms"] == 0 + assert payload["database"]["total_channel_messages"] == 0 + assert payload["database"]["total_outgoing"] == 0 + + @pytest.mark.asyncio + async def test_support_snapshot_includes_database_message_totals(self, test_db, client): + """Debug snapshot includes stored DM/channel/outgoing totals.""" + await _insert_contact("ab" * 32, "Alice") + await test_db.conn.execute( + "INSERT INTO channels (key, name, is_hashtag, on_radio) VALUES (?, ?, ?, ?)", + ("CD" * 16, "#ops", 1, 0), + ) + await test_db.conn.execute( + "INSERT INTO messages (type, conversation_key, text, received_at, outgoing) VALUES (?, ?, ?, ?, ?)", + ("PRIV", "ab" * 32, "hello", 1000, 0), + ) + await test_db.conn.execute( + "INSERT INTO messages (type, conversation_key, text, received_at, outgoing) VALUES (?, ?, ?, ?, ?)", + ("CHAN", "CD" * 16, "room msg", 1001, 1), + ) + await test_db.conn.commit() + + response = await client.get("/api/debug") + + assert response.status_code == 200 + payload = response.json() + assert payload["database"]["total_dms"] == 1 + assert payload["database"]["total_channel_messages"] == 1 + assert payload["database"]["total_outgoing"] == 1 class TestRadioDisconnectedHandler: