feat: add logging
This commit is contained in:
parent
a43873109c
commit
8bf781b67d
4
main.py
4
main.py
@ -1,5 +1,6 @@
|
|||||||
from src.integrations.gigachat_api_client import GigaChatClient
|
from src.integrations.gigachat_api_client import GigaChatClient
|
||||||
from src.bot.telegram_userbot import TelegramUserBot
|
from src.bot.telegram_userbot import TelegramUserBot
|
||||||
|
from src.utils.logging import setup_logging
|
||||||
from src.core.configuration import config
|
from src.core.configuration import config
|
||||||
|
|
||||||
|
|
||||||
@ -7,6 +8,9 @@ def main() -> None:
|
|||||||
"""
|
"""
|
||||||
Entry point for starting the Telegram user bot.
|
Entry point for starting the Telegram user bot.
|
||||||
"""
|
"""
|
||||||
|
# Configure logging
|
||||||
|
setup_logging()
|
||||||
|
|
||||||
# Load API credentials and configuration
|
# Load API credentials and configuration
|
||||||
api_id: str = config.API_ID
|
api_id: str = config.API_ID
|
||||||
api_hash: str = config.API_HASH
|
api_hash: str = config.API_HASH
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import logging
|
||||||
|
from logging import Logger
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
@ -27,6 +29,9 @@ class TelegramUserBot:
|
|||||||
api_hash (str): The API hash for the Telegram application.
|
api_hash (str): The API hash for the Telegram application.
|
||||||
gigachat_client (GigaChatClient): An instance of GigaChatClient for handling AI responses.
|
gigachat_client (GigaChatClient): An instance of GigaChatClient for handling AI responses.
|
||||||
"""
|
"""
|
||||||
|
# Configure logging
|
||||||
|
self.logger: Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
self.app: Client = Client(session_name, api_id=api_id, api_hash=api_hash)
|
self.app: Client = Client(session_name, api_id=api_id, api_hash=api_hash)
|
||||||
self.gigachat_client: GigaChatClient = gigachat_client
|
self.gigachat_client: GigaChatClient = gigachat_client
|
||||||
self.register_handlers()
|
self.register_handlers()
|
||||||
@ -35,6 +40,7 @@ class TelegramUserBot:
|
|||||||
"""
|
"""
|
||||||
Registers the message handlers for the bot.
|
Registers the message handlers for the bot.
|
||||||
"""
|
"""
|
||||||
|
self.logger.debug("Registering handlers.")
|
||||||
self.app.on_message(filters.command("ai") & filters.text)(self.handle_ai_command)
|
self.app.on_message(filters.command("ai") & filters.text)(self.handle_ai_command)
|
||||||
|
|
||||||
async def handle_ai_command(self, client: Client, message: Message) -> None:
|
async def handle_ai_command(self, client: Client, message: Message) -> None:
|
||||||
@ -45,14 +51,18 @@ class TelegramUserBot:
|
|||||||
client (Client): The Pyrogram client instance.
|
client (Client): The Pyrogram client instance.
|
||||||
message (Message): The incoming Telegram message.
|
message (Message): The incoming Telegram message.
|
||||||
"""
|
"""
|
||||||
|
self.logger.info(f"Received /ai command from chat_id={message.chat.id}")
|
||||||
|
|
||||||
# Extract the command argument
|
# Extract the command argument
|
||||||
command_arg: Optional[str] = " ".join(message.text.split()[1:])
|
command_arg: Optional[str] = " ".join(message.text.split()[1:])
|
||||||
|
|
||||||
if not command_arg:
|
if not command_arg:
|
||||||
|
self.logger.warning(f"No argument provided for /ai command by chat_id={message.chat.id}")
|
||||||
await message.reply_text("Please provide a message after /ai.")
|
await message.reply_text("Please provide a message after /ai.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Send an initial message indicating processing
|
# Send an initial message indicating processing
|
||||||
|
self.logger.debug(f"Processing request for chat_id={message.chat.id}")
|
||||||
processing_message: Message = await message.reply_text(f"{self.gigachat_client.model_name} is processing your request...")
|
processing_message: Message = await message.reply_text(f"{self.gigachat_client.model_name} is processing your request...")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -61,6 +71,7 @@ class TelegramUserBot:
|
|||||||
|
|
||||||
# Get a response from GigaChat
|
# Get a response from GigaChat
|
||||||
response: str = self.gigachat_client.get_response(str(message.chat.id), command_arg)
|
response: str = self.gigachat_client.get_response(str(message.chat.id), command_arg)
|
||||||
|
self.logger.debug(f"Received response for chat_id={message.chat.id}")
|
||||||
|
|
||||||
# Stop typing animation
|
# Stop typing animation
|
||||||
await client.send_chat_action(message.chat.id, ChatAction.CANCEL)
|
await client.send_chat_action(message.chat.id, ChatAction.CANCEL)
|
||||||
@ -68,6 +79,9 @@ class TelegramUserBot:
|
|||||||
# Edit the processing message with the generated response
|
# Edit the processing message with the generated response
|
||||||
await processing_message.edit_text(response)
|
await processing_message.edit_text(response)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
# Log the exception details
|
||||||
|
self.logger.error(f"Error processing /ai command for chat_id={message.chat.id}: {e}", exc_info=True)
|
||||||
|
|
||||||
# Stop typing animation in case of an error
|
# Stop typing animation in case of an error
|
||||||
await client.send_chat_action(message.chat.id, ChatAction.CANCEL)
|
await client.send_chat_action(message.chat.id, ChatAction.CANCEL)
|
||||||
|
|
||||||
@ -78,5 +92,9 @@ class TelegramUserBot:
|
|||||||
"""
|
"""
|
||||||
Starts the bot.
|
Starts the bot.
|
||||||
"""
|
"""
|
||||||
|
self.logger.info("Bot is starting.")
|
||||||
print("Bot is running.")
|
print("Bot is running.")
|
||||||
self.app.run()
|
try:
|
||||||
|
self.app.run()
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.critical(f"Failed to start the bot: {e}", exc_info=True)
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import logging
|
||||||
|
from logging import Logger
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
from langchain_core.runnables.history import RunnableWithMessageHistory
|
from langchain_core.runnables.history import RunnableWithMessageHistory
|
||||||
@ -18,8 +20,13 @@ class GigaChatClient:
|
|||||||
api_token (str): The API token for authenticating with the GigaChat API.
|
api_token (str): The API token for authenticating with the GigaChat API.
|
||||||
model_name (str): The GigaChat model to use. Defaults to "GigaChat".
|
model_name (str): The GigaChat model to use. Defaults to "GigaChat".
|
||||||
"""
|
"""
|
||||||
|
# Configure logging
|
||||||
|
self.logger: Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
self.api_token: str = api_token
|
self.api_token: str = api_token
|
||||||
self.model_name: str = model_name
|
self.model_name: str = model_name
|
||||||
|
self.logger.info(f"Initialize GigaChat client Using model: {self.model_name}")
|
||||||
|
|
||||||
self.llm: GigaChat = self._create_llm(model_name)
|
self.llm: GigaChat = self._create_llm(model_name)
|
||||||
self.store: Dict[str, InMemoryChatMessageHistory] = {}
|
self.store: Dict[str, InMemoryChatMessageHistory] = {}
|
||||||
self.conversation = RunnableWithMessageHistory(self.llm, self.get_session_history)
|
self.conversation = RunnableWithMessageHistory(self.llm, self.get_session_history)
|
||||||
@ -34,6 +41,7 @@ class GigaChatClient:
|
|||||||
Returns:
|
Returns:
|
||||||
GigaChat: Configured GigaChat instance.
|
GigaChat: Configured GigaChat instance.
|
||||||
"""
|
"""
|
||||||
|
self.logger.debug(f"Creating GigaChat LLM with model: {model_name}")
|
||||||
return GigaChat(
|
return GigaChat(
|
||||||
credentials=self.api_token,
|
credentials=self.api_token,
|
||||||
scope="GIGACHAT_API_PERS",
|
scope="GIGACHAT_API_PERS",
|
||||||
@ -53,7 +61,10 @@ class GigaChatClient:
|
|||||||
InMemoryChatMessageHistory: The chat history for the session.
|
InMemoryChatMessageHistory: The chat history for the session.
|
||||||
"""
|
"""
|
||||||
if session_id not in self.store:
|
if session_id not in self.store:
|
||||||
|
self.logger.debug(f"Creating new session history for session_id: {session_id}")
|
||||||
self.store[session_id] = InMemoryChatMessageHistory()
|
self.store[session_id] = InMemoryChatMessageHistory()
|
||||||
|
else:
|
||||||
|
self.logger.debug(f"Retrieving existing session history for session_id: {session_id}")
|
||||||
return self.store[session_id]
|
return self.store[session_id]
|
||||||
|
|
||||||
def set_model(self, model_name: str) -> None:
|
def set_model(self, model_name: str) -> None:
|
||||||
@ -63,6 +74,7 @@ class GigaChatClient:
|
|||||||
Args:
|
Args:
|
||||||
model_name (str): The new GigaChat model to use.
|
model_name (str): The new GigaChat model to use.
|
||||||
"""
|
"""
|
||||||
|
self.logger.info(f"Switching model to: {model_name}")
|
||||||
self.llm = self._create_llm(model_name)
|
self.llm = self._create_llm(model_name)
|
||||||
self.conversation = RunnableWithMessageHistory(self.llm, self.get_session_history)
|
self.conversation = RunnableWithMessageHistory(self.llm, self.get_session_history)
|
||||||
|
|
||||||
@ -77,8 +89,14 @@ class GigaChatClient:
|
|||||||
Returns:
|
Returns:
|
||||||
str: The response text.
|
str: The response text.
|
||||||
"""
|
"""
|
||||||
response = self.conversation.invoke(
|
self.logger.info(f"Generating response for session_id: {session_id}")
|
||||||
input=text,
|
try:
|
||||||
config={"configurable": {"session_id": session_id}},
|
response = self.conversation.invoke(
|
||||||
)
|
input=text,
|
||||||
return response.content
|
config={"configurable": {"session_id": session_id}},
|
||||||
|
)
|
||||||
|
self.logger.debug(f"Response for session_id {session_id}")
|
||||||
|
return response.content
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"Error while getting response for session_id: {session_id}. Error: {e}", exc_info=True)
|
||||||
|
raise
|
||||||
|
62
src/utils/logging.py
Normal file
62
src/utils/logging.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import logging
|
||||||
|
import logging.config
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
def setup_logging(output_to_console=False) -> None:
|
||||||
|
"""
|
||||||
|
Configures the logging system.
|
||||||
|
|
||||||
|
This function sets up logging with optional output to the console and ensures
|
||||||
|
log files are rotated daily. It creates a detailed logging format and retains
|
||||||
|
log files for a week.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
output_to_console (bool): If True, log messages will also be printed to the console.
|
||||||
|
Defaults to False.
|
||||||
|
"""
|
||||||
|
# Define the default handlers to use. Always logs to a file.
|
||||||
|
handlers: list[str] = ['file']
|
||||||
|
if output_to_console:
|
||||||
|
# Add console logging if requested
|
||||||
|
handlers.append('console')
|
||||||
|
|
||||||
|
# Generate the log file name with the current date
|
||||||
|
log_filename: str = f'logs/log-{datetime.now().strftime("%Y-%m-%d")}.log'
|
||||||
|
|
||||||
|
# Configure the logging settings using a dictionary
|
||||||
|
logging.config.dictConfig({
|
||||||
|
'version': 1, # Logging configuration version
|
||||||
|
'disable_existing_loggers': True, # Deny other loggers to remain active
|
||||||
|
'formatters': {
|
||||||
|
'detailed': { # Define a detailed logging format
|
||||||
|
'format': (
|
||||||
|
'%(asctime)s | %(levelname)-8s | '
|
||||||
|
'%(filename)s.%(funcName)s, line %(lineno)d: '
|
||||||
|
'%(message)s'
|
||||||
|
),
|
||||||
|
'datefmt': '%Y-%m-%d %H:%M:%S' # Timestamp format
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'handlers': {
|
||||||
|
# Console handler outputs log messages to the console
|
||||||
|
'console': {
|
||||||
|
'class': 'logging.StreamHandler', # Standard output stream
|
||||||
|
'formatter': 'detailed', # Use the detailed formatter
|
||||||
|
},
|
||||||
|
# File handler writes log messages to a file, rotating daily
|
||||||
|
'file': {
|
||||||
|
'class': 'logging.handlers.TimedRotatingFileHandler',
|
||||||
|
'filename': log_filename, # Log file path
|
||||||
|
'when': 'midnight', # Rotate log files at midnight
|
||||||
|
'interval': 1, # Rotate daily
|
||||||
|
'backupCount': 7, # Keep up to 7 old log files
|
||||||
|
'formatter': 'detailed', # Use the detailed formatter
|
||||||
|
},
|
||||||
|
},
|
||||||
|
# Define the root logger configuration
|
||||||
|
'root': {
|
||||||
|
'handlers': handlers, # Handlers to use (console, file, or both)
|
||||||
|
'level': 'DEBUG', # Log level (DEBUG logs all levels)
|
||||||
|
},
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user