diff --git a/backend/danswer/db/chat.py b/backend/danswer/db/chat.py index 4ad43a631..de9634ddb 100644 --- a/backend/danswer/db/chat.py +++ b/backend/danswer/db/chat.py @@ -156,6 +156,53 @@ def delete_chat_session( db_session.commit() +class ChatSessionSkeleton: + session_id: int + user_id: int + one_shot: bool + time_created: datetime.datetime + time_updated: datetime.datetime + + def __init__( + self, + session_id: int, + user_id: int, + one_shot: bool, + time_created: datetime.datetime, + time_updated: datetime.datetime, + ) -> None: + self.session_id = session_id + self.user_id = user_id + self.one_shot = one_shot + self.time_created = time_created + self.time_updated = time_updated + + +def get_chat_sessions_skeleton( + db_session: Session, +) -> list[ChatSessionSkeleton]: + stmt = select( + ChatSession.id, + ChatSession.user_id, + ChatSession.one_shot, + ChatSession.time_created, + ChatSession.time_updated, + ) + + result = db_session.execute(stmt).all() + + return [ + ChatSessionSkeleton( + session_id=s.id, + user_id=s.user_id, + one_shot=s.one_shot, + time_created=s.time_created, + time_updated=s.time_updated, + ) + for s in result + ] + + def get_chat_message( chat_message_id: int, user_id: UUID | None, diff --git a/backend/danswer/main.py b/backend/danswer/main.py index 4c23f6d2b..5f3f78f0b 100644 --- a/backend/danswer/main.py +++ b/backend/danswer/main.py @@ -71,8 +71,8 @@ from danswer.server.manage.llm.api import admin_router as llm_admin_router from danswer.server.manage.llm.api import basic_router as llm_router from danswer.server.manage.secondary_index import router as secondary_index_router from danswer.server.manage.slack_bot import router as slack_bot_management_router -from danswer.server.manage.users import router as user_router from danswer.server.manage.telemetry import router as telemetry_router +from danswer.server.manage.users import router as user_router from danswer.server.middleware.latency_logging import add_latency_logging_middleware from danswer.server.query_and_chat.chat_backend import router as chat_router from danswer.server.query_and_chat.query_backend import ( diff --git a/backend/danswer/server/manage/telemetry.py b/backend/danswer/server/manage/telemetry.py index 3db73cf0a..afad6cb3e 100644 --- a/backend/danswer/server/manage/telemetry.py +++ b/backend/danswer/server/manage/telemetry.py @@ -8,23 +8,21 @@ from sqlalchemy.orm import Session from danswer.auth.users import current_admin_user from danswer.configs.constants import FileOrigin +from danswer.db.chat import get_chat_sessions_skeleton from danswer.db.chat import get_empty_chat_messages_entries from danswer.db.engine import get_session from danswer.db.models import User +from danswer.file_store.file_store import FileStore from danswer.file_store.file_store import get_default_file_store router = APIRouter() -@router.post("/admin/generate-report") -async def generate_report( - _: User | None = Depends(current_admin_user), - db_session: Session = Depends(get_session), -) -> list[str]: - report_id = str(uuid.uuid4()) +# TODO: can probably merge these helpers into one and use __annotations__ to get fields and headers +def generate_chat_messages_report( + db_session: Session, file_store: FileStore, report_id: str +) -> None: messages = get_empty_chat_messages_entries(db_session) - file_store = get_default_file_store(db_session) - # write to memory buffer and store using pg_file_store with io.StringIO() as csvbuf: csvwriter = csv.writer(csvbuf, delimiter=",") @@ -42,4 +40,43 @@ async def generate_report( file_type="text/csv", ) - return [str(m.time_sent) for m in messages] + +def generate_chat_sessions_report( + db_session: Session, file_store: FileStore, report_id: str +) -> None: + sessions = get_chat_sessions_skeleton(db_session) + # write to memory buffer and store using pg_file_store + with io.StringIO() as csvbuf: + csvwriter = csv.writer(csvbuf, delimiter=",") + csvwriter.writerow( + ["session_id", "user_id", "one_shot", "time_created", "time_updated"] + ) + + for s in sessions: + csvwriter.writerow( + [s.session_id, s.user_id, s.one_shot, s.time_created, s.time_updated] + ) + + # after writing seek to begining of buffer + csvbuf.seek(0) + file_store.save_file( + file_name=f"{report_id}_chat_sessions", + content=csvbuf, + display_name=f"{report_id}_chat_sessions", + file_origin=FileOrigin.OTHER, + file_type="text/csv", + ) + + +@router.post("/admin/generate-report") +async def generate_report( + _: User | None = Depends(current_admin_user), + db_session: Session = Depends(get_session), +) -> list[str]: + report_id = str(uuid.uuid4()) + file_store = get_default_file_store(db_session) + + generate_chat_messages_report(db_session, file_store, report_id) + generate_chat_sessions_report(db_session, file_store, report_id) + + return ["Success"] diff --git a/web/src/app/admin/telemetry/interfaces.ts b/web/src/app/admin/telemetry/interfaces.ts index adb1874e5..9674d5ce2 100644 --- a/web/src/app/admin/telemetry/interfaces.ts +++ b/web/src/app/admin/telemetry/interfaces.ts @@ -1,3 +1 @@ -export interface TelemetryReport { - -} +export interface TelemetryReport {} diff --git a/web/src/app/admin/telemetry/page.tsx b/web/src/app/admin/telemetry/page.tsx index 1345fe4ff..61e2dffca 100644 --- a/web/src/app/admin/telemetry/page.tsx +++ b/web/src/app/admin/telemetry/page.tsx @@ -4,7 +4,15 @@ import { Settings, TelemetryReport } from "./interfaces"; import { fetchSS } from "@/lib/utilsSS"; import { FiSettings } from "react-icons/fi"; -import { Callout, Divider, Table, TableHead, TableHeaderCell, TableRow, Text } from "@tremor/react"; +import { + Callout, + Divider, + Table, + TableHead, + TableHeaderCell, + TableRow, + Text, +} from "@tremor/react"; import { Button } from "@tremor/react"; function TelemetryReportsTable() { @@ -19,12 +27,12 @@ function TelemetryReportsTable() { - ) + ); } function DataDisclaimer({ props }) { return ( -
+
@@ -42,7 +50,7 @@ function DataDisclaimer({ props }) {
- ) + ); } export default async function Page() { @@ -66,17 +74,13 @@ export default async function Page() { Export Telemetry about usage statistics for all users in the workspace. - -
); } diff --git a/web/src/components/admin/Layout.tsx b/web/src/components/admin/Layout.tsx index be65572a4..7a927a994 100644 --- a/web/src/components/admin/Layout.tsx +++ b/web/src/components/admin/Layout.tsx @@ -191,10 +191,9 @@ export async function Layout({ children }: { children: React.ReactNode }) {
Export Telemetry
), - link: "/admin/telemetry" - - } - ] + link: "/admin/telemetry", + }, + ], }, { name: "Settings",