diff --git a/kairon/chat/routers/web_client.py b/kairon/chat/routers/web_client.py index 4a79d60f9..46e28c4a3 100644 --- a/kairon/chat/routers/web_client.py +++ b/kairon/chat/routers/web_client.py @@ -77,5 +77,5 @@ async def reload_model( """ Retrieves chat client config of a bot. """ - background_tasks.add_task(ChatUtils.reload, bot) + background_tasks.add_task(ChatUtils.reload, bot, current_user.get_user()) return {"message": "Reloading Model!"} diff --git a/kairon/chat/utils.py b/kairon/chat/utils.py index a75c35c7d..172aa3bed 100644 --- a/kairon/chat/utils.py +++ b/kairon/chat/utils.py @@ -1,5 +1,6 @@ import datetime import json +import os from typing import Text, Dict from loguru import logger @@ -11,7 +12,9 @@ from .agent_processor import AgentProcessor from .. import Utility from ..live_agent.factory import LiveAgentFactory +from ..shared.account.activity_log import UserActivityLogger from ..shared.actions.utils import ActionUtility +from ..shared.constants import UserActivityType from ..shared.live_agent.processor import LiveAgentsProcessor from ..shared.metering.constants import MetricType from ..shared.metering.metering_processor import MeteringProcessor @@ -29,8 +32,20 @@ async def chat(data: Text, account: int, bot: Text, user: Text, is_integration_u return chat_response @staticmethod - def reload(bot: Text): - AgentProcessor.reload(bot) + def reload(bot: Text, user: Text): + exc = None + status = "Success" + try: + AgentProcessor.reload(bot) + except Exception as e: + logger.error(e) + exc = str(e) + status = "Failed" + finally: + UserActivityLogger.add_log(a_type=UserActivityType.model_reload.value, + email=user, bot=bot, + data={"username": user, "process_id": os.getpid(), "exception": exc, + "status": status}) @staticmethod def __attach_agent_handoff_metadata(account: int, bot: Text, sender_id: Text, bot_predictions, tracker): diff --git a/kairon/shared/constants.py b/kairon/shared/constants.py index 5f18109dd..576d137ce 100644 --- a/kairon/shared/constants.py +++ b/kairon/shared/constants.py @@ -58,6 +58,7 @@ class UserActivityType(str, Enum): login_refresh_token = "login_refresh_token" invalid_login = 'invalid_login' template_creation = 'template_creation' + model_reload = "model_reload" class EventClass(str, Enum): diff --git a/tests/integration_test/chat_service_test.py b/tests/integration_test/chat_service_test.py index a4ad18f4a..1958ec467 100644 --- a/tests/integration_test/chat_service_test.py +++ b/tests/integration_test/chat_service_test.py @@ -2,6 +2,7 @@ import json import os import time +from datetime import datetime, timedelta from unittest import mock from urllib.parse import urlencode, quote_plus @@ -828,6 +829,32 @@ def test_reload(mock_store): assert header in actual_headers +@patch('kairon.chat.utils.ChatUtils.reload') +def test_reload_logging(mock_reload): + processor = MongoProcessor() + start_time = datetime.utcnow() - timedelta(days=1) + end_time = datetime.utcnow() + timedelta(days=1) + mock_reload.return_value = None + response = client.get( + f"/api/bot/{bot}/reload", + headers={ + "Authorization": token_type + " " + token + }, + ) + actual = response.json() + assert actual["success"] + assert actual["error_code"] == 0 + assert actual["data"] is None + assert actual["message"] == "Reloading Model!" + logs = processor.get_logs(bot, "audit_logs", start_time, end_time) + logs[0].pop('timestamp') + logs[0].pop('_id') + logs[0]['data'].pop('process_id') + assert logs[0] == {'attributes': [{'key': 'bot', 'value': bot}], 'user': 'test@chat.com', 'action': 'activity', + 'entity': 'model_reload', + 'data': {'message': None, 'username': 'test@chat.com', 'exception': None, 'status': 'Success'}} + + def test_reload_exception(): response = client.get( f"/api/bot/{bot}/reload",