diff --git a/.gitignore b/.gitignore index 49ea43e..267f502 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ .env venv -.vscode -**/__pycache__ \ No newline at end of file +.vscode/ +*.log +logs +**/__pycache__ diff --git a/docker-compose.yml b/docker-compose.yml index 417bc03..e7103db 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,6 +13,8 @@ services: ROCKET_CHAT_PASSWORD: ${ROCKET_CHAT_PASSWORD} ROCKET_CHAT_URL: ${ROCKET_CHAT_URL} MONGO_URL_FOR_APP: ${MONGO_URL_FOR_APP} + volumes: + - ./logs:/logs depends_on: - mongodb diff --git a/log_snippets.md b/log_snippets.md new file mode 100644 index 0000000..d1abd71 --- /dev/null +++ b/log_snippets.md @@ -0,0 +1,36 @@ +# Примеры логирования + +## Дополнительные поля + несколько логеров +```python +from logger_config import general_logger, requests_logger, debug_logger +import random + +def foo(): + requests_logger.info("Got request", extra={"user":"maintainer", "random": random.random()}) + + # emulate super important actions + m = random.randint(1, 6) + debug_logger.debug(f"Request had number: {m}") + a = 1 / 0 + +if __name__ == '__main__': + general_logger.info("Script started.") + try: + foo() + except Exception as e: + general_logger.error(e, exc_info=True) + general_logger.info("Script finished.") +``` + +### Консоль +```json lines +{"timestamp": "2025-03-07 22:21:19,554", "name": "general", "level": "INFO", "msg": "Script started."} +{"timestamp": "2025-03-07 22:21:19,554", "name": "debug", "level": "DEBUG", "msg": "Request had number: 6"} +{"timestamp": "2025-03-07 22:21:19,554", "name": "general", "level": "ERROR", "msg": "division by zero", "exc_info": "Traceback (most recent call last):\n File \"C:\\Users\\wwwod\\PycharmProjects\\mse1h2025-rocket0\\snippet.py\", line 15, in \n foo()\n ~~~^^\n File \"C:\\Users\\wwwod\\PycharmProjects\\mse1h2025-rocket0\\snippet.py\", line 10, in foo\n a = 1 / 0\n ~~^~~\nZeroDivisionError: division by zero"} +{"timestamp": "2025-03-07 22:21:19,556", "name": "general", "level": "INFO", "msg": "Script finished."} +``` + +### Файл requests.log +```json +{"timestamp": "2025-03-07 22:21:19,554", "name": "requests", "level": "INFO", "msg": "Got request", "user": "maintainer", "random": 0.7549071001025663} +``` \ No newline at end of file diff --git a/logger_config.py b/logger_config.py new file mode 100644 index 0000000..8805b5d --- /dev/null +++ b/logger_config.py @@ -0,0 +1,35 @@ +import logging +import os +from logging.handlers import RotatingFileHandler +from pythonjsonlogger import json + +LOG_DIR = "logs" +os.makedirs(LOG_DIR, exist_ok=True) + + +def setup_logger(name: str, level: int = logging.INFO, to_console: bool = False, to_file: str | None = None) -> logging.Logger: + logger = logging.getLogger(name) + logger.setLevel(level) + + formatter = json.JsonFormatter( + "%(asctime)s %(name)s %(levelname)s %(message)s", + rename_fields={"asctime": "timestamp", "name": "name", "levelname": "level", "message": "msg"}, + ) + + if to_console: + console_handler = logging.StreamHandler() + console_handler.setLevel(level) + console_handler.setFormatter(formatter) + logger.addHandler(console_handler) + + if to_file and len(to_file) > 0: + file_handler = RotatingFileHandler(os.path.join(LOG_DIR, to_file), maxBytes=1000000, backupCount=5, encoding="utf-8") + file_handler.setLevel(level) + file_handler.setFormatter(formatter) + logger.addHandler(file_handler) + + return logger + +general_logger = setup_logger("general", logging.INFO, to_console=True) +requests_logger = setup_logger("requests", logging.INFO, to_file="requests.log") +debug_logger = setup_logger("debug", logging.DEBUG, to_console=True) diff --git a/requirements.txt b/requirements.txt index 426f312..cb924b4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,6 +8,7 @@ pydantic==2.10.6 pydantic_core==2.27.2 pymongo==4.6.3 python-dotenv==1.0.1 +python-json-logger==3.3.0 requests==2.32.3 rocketchat-async==4.2.0 rocketchat_API==1.35.0